Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine
This tutorial has a new version, check it out!

The Important CLI Options & phpunit.xml.dist

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $10.00

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!

4
Login or Register to join the conversation
Default user avatar
Default user avatar toporovvv | posted 5 years ago

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

Reply

Hey toporovvv

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

Reply
Default user avatar

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...

Reply

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

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

While the fundamentals of PHPUnit haven't changed, this tutorial *is* built on an older version of Symfony and PHPUnit.

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.0, <7.4",
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "doctrine/doctrine-bundle": "^1.6", // 1.10.3
        "doctrine/orm": "^2.5", // v2.7.2
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "sensio/distribution-bundle": "^5.0.19", // v5.0.21
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.28
        "symfony/monolog-bundle": "^3.1.0", // v3.1.2
        "symfony/polyfill-apcu": "^1.0", // v1.6.0
        "symfony/swiftmailer-bundle": "^2.3.10", // v2.6.7
        "symfony/symfony": "3.3.*", // v3.3.13
        "twig/twig": "^1.0||^2.0" // v2.4.4
    },
    "require-dev": {
        "doctrine/data-fixtures": "^1.3", // 1.3.3
        "doctrine/doctrine-fixtures-bundle": "^2.3", // v2.4.1
        "liip/functional-test-bundle": "^1.8", // 1.8.0
        "phpunit/phpunit": "^6.3", // 6.5.2
        "sensio/generator-bundle": "^3.0", // v3.1.6
        "symfony/phpunit-bridge": "^3.0" // v3.4.30
    }
}
userVoice