Quickly switching between PCOV and Xdebug
There are at least two PHP extensions I need during the development of a PHP application or package: PCOV and Xdebug.
PCOV is relatively new. Built by by Joe Watkins, it provides fast code coverage for use with phpunit/phpunit
.
Xdebug has been around for a while. Built by Derick Rethans, it is a development tool that can not only be used for collecting code coverage, but also provides a single-step debugger for use with IDEs, is equipped with a profiler, upgrades var_dump()
, and more. Since it does more things differently, it is slower at collecting code coverage.
Both are great tools and have their place. When I want to collect code coverage with recent versions of phpunit/phpunit
, I use PCOV. When I work on a project with older versions of phpunit/phpunit
, I use Xdebug to collect code coverage. When I want to debug production code while running tests in PhpStorm, I use Xdebug.
There are drawbacks, however. PCOV does not play well with Xdebug, so I only want one of them to be enabled at a time. Xdebug adds significant overhead when running other tasks in PHP, so I prefer to disable Xdebug when I do not need it.
Before I can enable or disable PCOV and Xdebug, I need to install and configure them. I am going to demonstrate the installation of both on PHP 7.4.
Installation of PCOV
Run
pecl install pcov
and take note of last few lines that are shown when the installation process is finished and the location of pcov.so
is revealed (we need it in a moment):
Build process completed successfully
Installing '/usr/local/Cellar/php/7.4.6/pecl/20190902/pcov.so'
install ok: channel://pecl.php.net/pcov-1.0.6
Extension pcov enabled in php.ini
Configuration of PCOV
Run
php --ini
to show the names of configuration files loaded by PHP:
Configuration File (php.ini) Path: /usr/local/etc/php/7.4
Loaded Configuration File: /usr/local/etc/php/7.4/php.ini
Scan for additional .ini files in: /usr/local/etc/php/7.4/conf.d
Additional .ini files parsed: /usr/local/etc/php/7.4/conf.d/ext-opcache.ini
Open /usr/local/etc/php/7.4/php.ini
and remove
- extension="pcov.so"
Create a file /usr/local/etc/php/7.4/conf.d/ext-pcov.ini
, but use the exact location of pcov.so
we noted earlier:
extension="/usr/local/Cellar/php/7.4.5_2/pecl/20190902/pcov.so"
Run
php --ini
again and observe that ext-pcov.ini
has been loaded:
Configuration File (php.ini) Path: /usr/local/etc/php/7.4
Loaded Configuration File: /usr/local/etc/php/7.4/php.ini
Scan for additional .ini files in: /usr/local/etc/php/7.4/conf.d
Additional .ini files parsed: /usr/local/etc/php/7.4/conf.d/ext-opcache.ini,
/usr/local/etc/php/7.4/conf.d/ext-pcov.ini
Installation of Xdebug
Run
pecl install xdebug
and take note of the location of xdebug.so
:
Build process completed successfully
Installing '/usr/local/Cellar/php/7.4.6/pecl/20190902/xdebug.so'
install ok: channel://pecl.php.net/xdebug-2.9.5
Extension xdebug enabled in php.ini
Configuration of Xdebug
Run
php --ini
to show the names of configuration files loaded by PHP:
Configuration File (php.ini) Path: /usr/local/etc/php/7.4
Loaded Configuration File: /usr/local/etc/php/7.4/php.ini
Scan for additional .ini files in: /usr/local/etc/php/7.4/conf.d
Additional .ini files parsed: /usr/local/etc/php/7.4/conf.d/ext-opcache.ini,
/usr/local/etc/php/7.4/conf.d/ext-pcov.ini
Open /usr/local/etc/php/7.4/php.ini
and remove
- zend_extension="xdebug.so"
Create a file /usr/local/etc/php/7.4/conf.d/ext-xdebug.ini
, but use the exact location of xdebug.so
we noted earlier:
zend_extension="/usr/local/Cellar/php/7.4.6/pecl/20190902/xdebug.so"
Run
php --ini
again and observe that ext-xdebug.ini
has been loaded:
Configuration File (php.ini) Path: /usr/local/etc/php/7.4
Loaded Configuration File: /usr/local/etc/php/7.4/php.ini
Scan for additional .ini files in: /usr/local/etc/php/7.4/conf.d
Additional .ini files parsed: /usr/local/etc/php/7.4/conf.d/ext-opcache.ini,
/usr/local/etc/php/7.4/conf.d/ext-pcov.ini,
/usr/local/etc/php/7.4/conf.d/ext-xdebug.ini
Disabling and enabling PCOV and Xdebug
Now that we have installed PCOV and Xdebug, we need a way for disabling and enabling them.
The easiest way to disable an extension is to prevent PHP from loading the corresponding configuration file. Since PHP is looking for files ending with a .ini
extension, renaming the file seems smart.
In Switching PHP versions when using Homebrew, I collect PHP versions previously installed with Homebrew.
Again, I would like to have a command that works regardless of which version of PHP I currently use. I would also prefer to use a short command, especially when I am going to run them often. To achieve this, I have added the following to my .zhsrc
:
# Toggle extension
function toggle()
{
name=$1
displayName=${2:-$1}
for phpVersion in ${installedPhpVersions[*]}; do
config="/usr/local/etc/php/${phpVersion}/conf.d/ext-${name}.ini"
if [[ -f "${config}" ]]; then
mv "${config}" "${config}.bak"
elif [[ -f "${config}.bak" ]]; then
mv "${config}.bak" "${config}"
fi
done
php -v
if [[ $(php -m | grep ${name}) ]]; then
echo "${displayName} extension has been enabled."
else
echo "${displayName} extension has been disabled."
fi
}
This function expects a single argument, the name of an extension, and optionally a second argument, the display name. The function iterates over all installed PHP versions, and either adds a .bak
extension to the name of a matching configuration file, or removes it - effectively disabling or enabling the corresponding extension.
Now I could run
toggle pcov
or
toggle xdebug
but to be honest, that is still too much work. I have added the following to .zshrc
instead:
# Toggle PCOV
function p () {
toggle pcov PCOV
}
# Toggle Xdebug
function x () {
toggle xdebug Xdebug
}
Thanks to these small functions, I can run
p
and
x
to quickly disable or enable PCOV and Xdebug.
Do you find this article helpful?
Do you have feedback?
Just blogged: Quicky switching between PCOV and @Xdebug.
— Andreas Möller (@localheinz) May 16, 2020
If you work with multiple versions of #PHP and need to collect code coverage with @phpunit or run mutation tests with @infection_php, you might like this.
🤓https://t.co/h4aes6vFha