Buy
Buy

The Important CLI Options & phpunit.xml.dist

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

Find your terminal. But this time, run phpunit with a -h option:

./vendor/bin/phpunit -h

Woh! That is a lot of options. Ok, let's talk about every single one of them. Just kidding! I've never even used most of these options! But there are a few awesome flags that will be very useful.

Google for "PHPUnit cli" to find their page about this. It's a bit prettier than reading the terminal. At the top of the output, it says that you can pass one or more files or directories. That's useful to run just one test class or all the classes in one directory. For example, we could run just the DinosaurFactoryTest:

./vendor/bin/phpunit tests/AppBundle/Factory/DinosaurFactoryTest.php

The Symfony PHPUnit Bridge

Oh, and before I forget, Google for "Symfony PHPUnit Bridge" to find a special component that lives in Symfony.com: symfony/phpunit-bridge.

This is a wrapper around PHPUnit that adds a couple of extra features like deprecation reporting that will tell you about deprecated code paths that you're using during your tests.

Tip

In Symfony 4, this is the officially-recommended way to use PHPUnit. You should install this instead of installing PHPUnit directly.

Basically, after you install this, you'll use vendor/bin/simple-phpunit to activate it. It supports all the same options.

The --filter Option

Back on the PHPUnit docs, my favorite option by far is --filter. This let's you run just one test method, and it's critical when you're trying to debug one test.

If you scroll down, the docs show a bunch of examples. Usually, I copy the method name I'm testing, pass --filter and then paste that name. But you can get a lot fancier.

Let's try a few! First, re-run the test with another flag: --debug:

./vendor/bin/phpunit tests/AppBundle/Factory/DinosaurFactoryTest.php --debug

The output now tells us which tests are running. Let's run just one of them:

./vendor/bin/phpunit --filter testItGrowsADinosaurFromASpecification --debug

And... yes! It ran three tests, because this one method has a data provider. But sometimes, you'll need to debug just one test case of a provider. Surround the method name in quotes, and then add #1:

./vendor/bin/phpunit --filter 'testItGrowsADinosaurFromASpecification #1' --debug

Ah, so cool! You can also use @default response - that's the test case that we gave a special name.

./vendor/bin/phpunit --filter 'testItGrowsADinosaurFromASpecification @default response' --debug

For the longest time, I didn't know you could do this. I love it.

Stopping on Failure or Error

If you're running a lot of tests, you can tell PHPUnit to stop immediately when one of them has an error or fails... instead of waiting for all of them to finish running.

To do that, use the --stop-on-failure and --stop-on-error options:

./vendor/bin/phpunit --stop-on-failure --stop-on-error

We don't have any errors - yes! - but you get the idea!

The phpunit.xml.dist File

There are many other options... but you can do even more in the configuration file! And we already have one! PHPUnit automatically looks for a phpunit.xml file and then a phpunit.xml.dist file.

This configures a few really important things... like bootstrap. Thanks to this, PHPUnit requires the autoloader before running the tests. But there is so much more you can do: tweak php.ini settings, set environment variables, configure test suites or tweak code coverage setup.

Most of the time, you'll have just one test suite... which means that all the test are always executed. But you could, for example, separate your unit, integration and functional tests into different suites so that you could run them independently. That's kind of cool, because integration and functional tests are much slower than unit tests.

Let's do one quick example: add a test suite called entities and set its directory to tests/*Bundle/Entity.

To run this suite, use:

./vendor/bin/phpunit --testsuite entities --debug

It runs only those tests.

Ok, enough of this! Let's get back to work and talk about integration tests: what they are, and when they can save your life.

Leave a comment!

  • 2018-04-19 Diego Aguiar

    Can you try requiring "symfony/phpunit-bridge" version 3

  • 2018-04-19 toporovvv

    PHP
    vagrant@ubuntu-xenial:/vagrant$ php -v
    PHP 7.2.4-1+ubuntu16.04.1+deb.sury.org+1 (cli) (built: Apr 5 2018 08:53:57) ( NTS )
    Copyright (c) 1997-2018 The PHP Group
    Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.4-1+ubuntu16.04.1+deb.sury.org+1, Copyright (c) 1999-2018, by Zend Technologies
    with Xdebug v2.6.0, Copyright (c) 2002-2018, by Derick Rethans

    Symfony:
    vagrant@ubuntu-xenial:/vagrant$ php bin/console about
    -------------------- --------------------------------------
    Symfony
    -------------------- --------------------------------------
    Version 3.3.10
    End of maintenance 01/2018 Expired
    End of life 07/2018
    -------------------- --------------------------------------
    Kernel
    -------------------- --------------------------------------
    Type AppKernel
    Name app
    Environment dev
    Debug true
    Charset UTF-8
    Root directory ./app
    Cache directory ./var/cache/dev (563 KiB)
    Log directory ./var/logs (8 KiB)
    -------------------- --------------------------------------
    PHP
    -------------------- --------------------------------------
    Version 7.2.4-1+ubuntu16.04.1+deb.sury.org+1
    Architecture 64 bits
    Intl locale n/a
    Timezone UTC (2018-04-19T18:07:19+00:00)
    OPcache true
    APCu false
    Xdebug true
    -------------------- --------------------------------------

    Actually, I cloned this repo https://github.com/knpunive... and packed it in Virtualbox VM. Here are my Vagrantfile and build script for it:
    https://bitbucket.org/renta...
    https://bitbucket.org/renta...

  • 2018-04-19 Diego Aguiar

    Hey toporovvv

    Could you tell me which Symfony and PHP version are you using?

  • 2018-04-19 toporovvv

    In my case PHPUnit Bridge did not worked (out of the box and after the "composer require --dev symfony/phpunit-bridge" from a Symfony documentation):

    vagrant@ubuntu-xenial:/vagrant$ ./vendor/bin/simple-phpunit
    symfony/yaml is not required in your composer.json and has not been removed
    ./composer.json has been updated
    Loading composer repositories with package information
    Updating dependencies
    Package operations: 23 installs, 0 updates, 0 removals
    - Installing phar-io/version (1.0.1): Downloading (100%)
    - Installing phar-io/manifest (1.0.1): Downloading (100%)
    - Installing phpunit/php-timer (1.0.9): Downloading (100%)
    - Installing sebastian/global-state (2.0.0): Downloading (100%)
    - Installing sebastian/recursion-context (3.0.0): Downloading (100%)
    - Installing sebastian/object-reflector (1.1.1): Downloading (100%)
    - Installing sebastian/object-enumerator (3.0.3): Downloading (100%)
    - Installing sebastian/resource-operations (1.0.0): Downloading (100%)
    - Installing myclabs/deep-copy (1.7.0): Downloading (100%)
    - Installing theseer/tokenizer (1.1.0): Downloading (100%)
    - Installing sebastian/version (2.0.1): Downloading (100%)
    - Installing sebastian/environment (3.1.0): Downloading (100%)
    - Installing sebastian/code-unit-reverse-lookup (1.0.1): Downloading (100%)
    - Installing phpunit/php-token-stream (2.0.2): Downloading (100%)
    - Installing phpunit/php-text-template (1.2.1): Downloading (100%)
    - Installing phpunit/php-file-iterator (1.4.5): Downloading (100%)
    - Installing phpunit/php-code-coverage (5.3.2): Downloading (100%)
    - Installing sebastian/exporter (3.1.0): Downloading (100%)
    - Installing doctrine/instantiator (1.0.5): Downloading (100%)
    - Installing phpunit/phpunit-mock-objects (5.0.6): Downloading (100%)
    - Installing sebastian/diff (2.0.1): Downloading (100%)
    - Installing sebastian/comparator (2.1.3): Downloading (100%)
    - Installing symfony/phpunit-bridge (v4.0.8): Symlinking from /vagrant/vendor/symfony/phpunit-bridge
    Writing lock file
    Generating optimized autoload files
    PHP Fatal error: Declaration of Symfony\Bridge\PhpUnit\TextUI\TestRunner::handleConfiguration(array &$arguments) must be compatible with PHPUnit\TextUI\TestRunner::handleConfiguration(array &$arguments): void in /vagrant/vendor/symfony/phpunit-bridge/TextUI/TestRunner.php on line 25
    PHP Stack trace:
    PHP 1. {main}() /vagrant/vendor/symfony/phpunit-bridge/bin/simple-phpunit:0
    PHP 2. include() /vagrant/vendor/symfony/phpunit-bridge/bin/simple-phpunit:251
    PHP 3. PHPUnit\TextUI\Command::main() /vagrant/vendor/bin/.phpunit/phpunit-6.5/phpunit:17
    PHP 4. Symfony\Bridge\PhpUnit\TextUI\Command->run() /vagrant/vendor/bin/.phpunit/phpunit-6.5/src/TextUI/Command.php:148
    PHP 5. Symfony\Bridge\PhpUnit\TextUI\Command->createRunner() /vagrant/vendor/bin/.phpunit/phpunit-6.5/src/TextUI/Command.php:161
    PHP 6. spl_autoload_call() /vagrant/vendor/symfony/phpunit-bridge/TextUI/Command.php:31
    PHP 7. Composer\Autoload\ClassLoader->loadClass() /vagrant/vendor/symfony/phpunit-bridge/TextUI/Command.php:31
    PHP 8. Composer\Autoload\includeFile() /vagrant/vendor/bin/.phpunit/phpunit-6.5/vendor/composer/ClassLoader.php:322
    PHP 9. include() /vagrant/vendor/bin/.phpunit/phpunit-6.5/vendor/composer/ClassLoader.php:444