3. The Command-Line Test Runner

The PHPUnit command-line test runner can be invoked through the phpunit command. The following code shows how to run tests with the PHPUnit command-line test runner:

  1. $ phpunit ArrayTest
  2. PHPUnit 8.5.0 by Sebastian Bergmann and contributors.
  3. ..
  4. Time: 0 seconds
  5. OK (2 tests, 2 assertions)

When invoked as shown above, the PHPUnit command-line test runner will look for a ArrayTest.php sourcefile in the current working directory, load it, and expect to find a ArrayTest test case class. It will then execute the tests of that class.

For each test run, the PHPUnit command-line tool prints one character to indicate progress:

.

Printed when the test succeeds.

F

Printed when an assertion fails while running the test method.

E

Printed when an error occurs while running the test method.

R

Printed when the test has been marked as risky (see Risky Tests).

S

Printed when the test has been skipped (see Incomplete and Skipped Tests).

I

Printed when the test is marked as being incomplete or not yet implemented (see Incomplete and Skipped Tests).

PHPUnit distinguishes between failures and errors. A failure is a violated PHPUnit assertion such as a failing assertSame() call. An error is an unexpected exception or a PHP error. Sometimes this distinction proves useful since errors tend to be easier to fix than failures. If you have a big list of problems, it is best to tackle the errors first and see if you have any failures left when they are all fixed.

Command-Line Options

Let’s take a look at the command-line test runner’s options in the following code:

  1. $ phpunit --help
  2. PHPUnit 8.5.0 by Sebastian Bergmann and contributors.
  3. Usage: phpunit [options] UnitTest [UnitTest.php]
  4. phpunit [options] <directory>
  5. Code Coverage Options:
  6. --coverage-clover <file> Generate code coverage report in Clover XML format
  7. --coverage-crap4j <file> Generate code coverage report in Crap4J XML format
  8. --coverage-html <dir> Generate code coverage report in HTML format
  9. --coverage-php <file> Export PHP_CodeCoverage object to file
  10. --coverage-text=<file> Generate code coverage report in text format
  11. Default: Standard output
  12. --coverage-xml <dir> Generate code coverage report in PHPUnit XML format
  13. --whitelist <dir> Whitelist <dir> for code coverage analysis
  14. --disable-coverage-ignore Disable annotations for ignoring code coverage
  15. --no-coverage Ignore code coverage configuration
  16. --dump-xdebug-filter <file> Generate script to set Xdebug code coverage filter
  17. Logging Options:
  18. --log-junit <file> Log test execution in JUnit XML format to file
  19. --log-teamcity <file> Log test execution in TeamCity format to file
  20. --testdox-html <file> Write agile documentation in HTML format to file
  21. --testdox-text <file> Write agile documentation in Text format to file
  22. --testdox-xml <file> Write agile documentation in XML format to file
  23. --reverse-list Print defects in reverse order
  24. Test Selection Options:
  25. --filter <pattern> Filter which tests to run
  26. --testsuite <name,...> Filter which testsuite to run
  27. --group ... Only runs tests from the specified group(s)
  28. --exclude-group ... Exclude tests from the specified group(s)
  29. --list-groups List available test groups
  30. --list-suites List available test suites
  31. --list-tests List available tests
  32. --list-tests-xml <file> List available tests in XML format
  33. --test-suffix ... Only search for test in files with specified
  34. suffix(es). Default: Test.php,.phpt
  35. Test Execution Options:
  36. --dont-report-useless-tests Do not report tests that do not test anything
  37. --strict-coverage Be strict about @covers annotation usage
  38. --strict-global-state Be strict about changes to global state
  39. --disallow-test-output Be strict about output during tests
  40. --disallow-resource-usage Be strict about resource usage during small tests
  41. --enforce-time-limit Enforce time limit based on test size
  42. --default-time-limit=<sec> Timeout in seconds for tests without @small, @medium or @large
  43. --disallow-todo-tests Disallow @todo-annotated tests
  44. --process-isolation Run each test in a separate PHP process
  45. --globals-backup Backup and restore $GLOBALS for each test
  46. --static-backup Backup and restore static attributes for each test
  47. --colors=<flag> Use colors in output ("never", "auto" or "always")
  48. --columns <n> Number of columns to use for progress output
  49. --columns max Use maximum number of columns for progress output
  50. --stderr Write to STDERR instead of STDOUT
  51. --stop-on-defect Stop execution upon first not-passed test
  52. --stop-on-error Stop execution upon first error
  53. --stop-on-failure Stop execution upon first error or failure
  54. --stop-on-warning Stop execution upon first warning
  55. --stop-on-risky Stop execution upon first risky test
  56. --stop-on-skipped Stop execution upon first skipped test
  57. --stop-on-incomplete Stop execution upon first incomplete test
  58. --fail-on-warning Treat tests with warnings as failures
  59. --fail-on-risky Treat risky tests as failures
  60. -v|--verbose Output more verbose information
  61. --debug Display debugging information
  62. --loader <loader> TestSuiteLoader implementation to use
  63. --repeat <times> Runs the test(s) repeatedly
  64. --teamcity Report test execution progress in TeamCity format
  65. --testdox Report test execution progress in TestDox format
  66. --testdox-group Only include tests from the specified group(s)
  67. --testdox-exclude-group Exclude tests from the specified group(s)
  68. --printer <printer> TestListener implementation to use
  69. --resolve-dependencies Resolve dependencies between tests
  70. --order-by=<order> Run tests in order: default|defects|duration|no-depends|random|reverse
  71. --random-order-seed=<N> Use a specific random seed <N> for random order
  72. --cache-result Write run result to cache to enable ordering tests defects-first
  73. Configuration Options:
  74. --prepend <file> A PHP script that is included as early as possible
  75. --bootstrap <file> A PHP script that is included before the tests run
  76. -c|--configuration <file> Read configuration from XML file
  77. --no-configuration Ignore default configuration file (phpunit.xml)
  78. --no-logging Ignore logging configuration
  79. --no-extensions Do not load PHPUnit extensions
  80. --include-path <path(s)> Prepend PHP's include_path with given path(s)
  81. -d key[=value] Sets a php.ini value
  82. --generate-configuration Generate configuration file with suggested settings
  83. --cache-result-file=<FILE> Specify result cache path and filename
  84. Miscellaneous Options:
  85. -h|--help Prints this usage information
  86. --version Prints the version and exits
  87. --atleast-version <min> Checks that version is greater than min and exits
  88. --check-version Check whether PHPUnit is the latest version

phpunit UnitTest

Runs the tests that are provided by the class UnitTest. This class is expected to be declared in the UnitTest.php sourcefile.

UnitTest must be either a class that inherits from PHPUnit\Framework\TestCase or a class that provides a public static suite() method which returns a PHPUnit\Framework\Test object, for example an instance of the PHPUnit\Framework\TestSuite class.

phpunit UnitTest UnitTest.php

Runs the tests that are provided by the class UnitTest. This class is expected to be declared in the specified sourcefile.

--coverage-clover

Generates a logfile in XML format with the code coverage information for the tests run. See Logging for more details.

Please note that this functionality is only available when the tokenizer and Xdebug extensions are installed.

--coverage-crap4j

Generates a code coverage report in Crap4j format. See Code Coverage Analysis for more details.

Please note that this functionality is only available when the tokenizer and Xdebug extensions are installed.

--coverage-html

Generates a code coverage report in HTML format. See Code Coverage Analysis for more details.

Please note that this functionality is only available when the tokenizer and Xdebug extensions are installed.

--coverage-php

Generates a serialized PHP_CodeCoverage object with the code coverage information.

Please note that this functionality is only available when the tokenizer and Xdebug extensions are installed.

--coverage-text

Generates a logfile or command-line output in human readable format with the code coverage information for the tests run. See Logging for more details.

Please note that this functionality is only available when the tokenizer and Xdebug extensions are installed.

--log-junit

Generates a logfile in JUnit XML format for the tests run. See Logging for more details.

--testdox-html and --testdox-text

Generates agile documentation in HTML or plain text format for the tests that are run (see TestDox).

--filter

Only runs tests whose name matches the given regular expression pattern. If the pattern is not enclosed in delimiters, PHPUnit will enclose the pattern in / delimiters.

The test names to match will be in one of the following formats:

TestNamespace\TestCaseClass::testMethod

The default test name format is the equivalent of using the __METHOD__ magic constant inside the test method.

TestNamespace\TestCaseClass::testMethod with data set #0

When a test has a data provider, each iteration of the data gets the current index appended to the end of the default test name.

TestNamespace\TestCaseClass::testMethod with data set "my named data"

When a test has a data provider that uses named sets, each iteration of the data gets the current name appended to the end of the default test name. See Example 3.1 for an example of named data sets.

Example 3.1 Named data sets

  1. <?php
  2. use PHPUnit\Framework\TestCase;
  3. namespace TestNamespace;
  4. class TestCaseClass extends TestCase
  5. {
  6. /**
  7. * @dataProvider provider
  8. */
  9. public function testMethod($data)
  10. {
  11. $this->assertTrue($data);
  12. }
  13. public function provider()
  14. {
  15. return [
  16. 'my named data' => [true],
  17. 'my data' => [true]
  18. ];
  19. }
  20. }

/path/to/my/test.phpt

The test name for a PHPT test is the filesystem path.

See Example 3.2 for examples of valid filter patterns.

Example 3.2 Filter pattern examples

  1. --filter 'TestNamespace\\TestCaseClass::testMethod'
  2. --filter 'TestNamespace\\TestCaseClass'
  3. --filter TestNamespace
  4. --filter TestCaseClase
  5. --filter testMethod
  6. --filter '/::testMethod .*"my named data"/'
  7. --filter '/::testMethod .*#5$/'
  8. --filter '/::testMethod .*#(5|6|7)$/'

See Example 3.3 for some additional shortcuts that are available for matching data providers.

Example 3.3 Filter shortcuts

  1. --filter 'testMethod#2'
  2. --filter 'testMethod#2-4'
  3. --filter '#2'
  4. --filter '#2-4'
  5. --filter 'testMethod@my named data'
  6. --filter 'testMethod@my.*data'
  7. --filter '@my named data'
  8. --filter '@my.*data'

--testsuite

Only runs the test suite whose name matches the given pattern.

--group

Only runs tests from the specified group(s). A test can be tagged as belonging to a group using the @group annotation.

The @author and @ticket annotations are aliases for @group allowing to filter tests based on their authors or their ticket identifiers, respectively.

--exclude-group

Exclude tests from the specified group(s). A test can be tagged as belonging to a group using the @group annotation.

--list-groups

List available test groups.

--test-suffix

Only search for test files with specified suffix(es).

--dont-report-useless-tests

Do not report tests that do not test anything. See Risky Tests for details.

--strict-coverage

Be strict about unintentionally covered code. See Risky Tests for details.

--strict-global-state

Be strict about global state manipulation. See Risky Tests for details.

--disallow-test-output

Be strict about output during tests. See Risky Tests for details.

--disallow-todo-tests

Does not execute tests which have the @todo annotation in its docblock.

--enforce-time-limit

Enforce time limit based on test size. See Risky Tests for details.

--process-isolation

Run each test in a separate PHP process.

--no-globals-backup

Do not backup and restore $GLOBALS. See Global State for more details.

--static-backup

Backup and restore static attributes of user-defined classes. See Global State for more details.

--colors

Use colors in output. On Windows, use ANSICON or ConEmu.

There are three possible values for this option:

  • never: never displays colors in the output. This is the default value when --colors option is not used.
  • auto: displays colors in the output unless the current terminal doesn’t supports colors, or if the output is piped to a command or redirected to a file.
  • always: always displays colors in the output even when the current terminal doesn’t supports colors, or when the output is piped to a command or redirected to a file.

When --colors is used without any value, auto is the chosen value.

--columns

Defines the number of columns to use for progress output. If max is defined as value, the number of columns will be maximum of the current terminal.

--stderr

Optionally print to STDERR instead of STDOUT.

--stop-on-error

Stop execution upon first error.

--stop-on-failure

Stop execution upon first error or failure.

--stop-on-risky

Stop execution upon first risky test.

--stop-on-skipped

Stop execution upon first skipped test.

--stop-on-incomplete

Stop execution upon first incomplete test.

--verbose

Output more verbose information, for instance the names of tests that were incomplete or have been skipped.

--debug

Output debug information such as the name of a test when its execution starts.

--loader

Specifies the PHPUnit\Runner\TestSuiteLoader implementation to use.

The standard test suite loader will look for the sourcefile in the current working directory and in each directory that is specified in PHP’s include_path configuration directive. A class name such as Project_Package_Class is mapped to the source filename Project/Package/Class.php.

--repeat

Repeatedly runs the test(s) the specified number of times.

--testdox

Reports the test progress in TestDox format (see TestDox).

--printer

Specifies the result printer to use. The printer class must extend PHPUnit\Util\Printer and implement the PHPUnit\Framework\TestListener interface.

--bootstrap

A “bootstrap” PHP file that is run before the tests.

--configuration, -c

Read configuration from XML file. See The XML Configuration File for more details.

If phpunit.xml or phpunit.xml.dist (in that order) exist in the current working directory and --configuration is not used, the configuration will be automatically read from that file.

If a directory is specified and if phpunit.xml or phpunit.xml.dist (in that order) exists in this directory, the configuration will be automatically read from that file.

--no-configuration

Ignore phpunit.xml and phpunit.xml.dist from the current working directory.

--include-path

Prepend PHP’s include_path with given path(s).

-d

Sets the value of the given PHP configuration option.

Note

Please note that as of 4.8, options can be put after the argument(s).

TestDox

PHPUnit’s TestDox functionality looks at a test class and all the test method names and converts them from camel case (or snake_case) PHP names to sentences: testBalanceIsInitiallyZero() (or test_balance_is_initially_zero() becomes “Balance is initially zero”. If there are several test methods whose names only differ in a suffix of one or more digits, such as testBalanceCannotBecomeNegative() and testBalanceCannotBecomeNegative2(), the sentence “Balance cannot become negative” will appear only once, assuming that all of these tests succeed.

Let us take a look at the agile documentation generated for a BankAccount class:

  1. $ phpunit --testdox BankAccountTest
  2. PHPUnit 8.5.0 by Sebastian Bergmann and contributors.
  3. BankAccount
  4. Balance is initially zero
  5. Balance cannot become negative

Alternatively, the agile documentation can be generated in HTML or plain text format and written to a file using the --testdox-html and --testdox-text arguments.

Agile Documentation can be used to document the assumptions you make about the external packages that you use in your project. When you use an external package, you are exposed to the risks that the package will not behave as you expect, and that future versions of the package will change in subtle ways that will break your code, without you knowing it. You can address these risks by writing a test every time you make an assumption. If your test succeeds, your assumption is valid. If you document all your assumptions with tests, future releases of the external package will be no cause for concern: if the tests succeed, your system should continue working.