├── .github
├── FUNDING.yml
└── workflows
│ └── ci.yml
├── .gitignore
├── .php-cs-fixer.dist.php
├── LICENSE
├── Makefile
├── README.md
├── composer.json
├── composer.lock
├── docker-compose.yml
├── docker
└── php-cli
│ └── Dockerfile
├── phpstan.neon
├── phpunit.xml.dist
├── readme
├── example-compact.png
├── example-default.png
├── example-profiling.png
├── example-quote.png
└── logo.png
├── src
├── Configuration.php
├── PhpUnitExtension.php
├── Quotes.php
└── Subscriber
│ └── Application
│ ├── ApplicationFinishedSubscriber.php
│ └── ApplicationStartedSubscriber.php
└── tests
├── ExampleTests
├── TestThatHasAllStatusesTest.php
└── TestThatPassesTest.php
├── OutputTest.php
├── SpyOutput.php
├── Unit
├── ConfigurationTest.php
├── PhpUnitExtensionTest.php
└── Subscriber
│ └── Application
│ ├── ApplicationFinishedSubscriberTest.php
│ └── ApplicationStartedSubscriberTest.php
├── phpunit.test-compact-mode.xml
├── phpunit.test-disable-by-default.xml
├── phpunit.test-profiling.xml
├── phpunit.test-with-quotes.xml
└── phpunit.test.xml
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: robiningelbrecht
4 | custom: ['https://www.buymeacoffee.com/ingelbrecht']
5 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on:
3 | pull_request:
4 | workflow_dispatch:
5 | jobs:
6 | test-suite:
7 | name: PHPStan, PHPcs & Testsuite
8 | runs-on: ubuntu-latest
9 | strategy:
10 | matrix:
11 | php-versions: [ '8.1', '8.2' ]
12 | phpunit-versions: [ '10.3', '11.0' ]
13 | exclude:
14 | - php-versions: 8.1
15 | phpunit-versions: 11.0
16 |
17 | steps:
18 | # https://github.com/marketplace/actions/setup-php-action
19 | - name: Setup PHP ${{ matrix.php-versions }} with Xdebug 3.x
20 | uses: shivammathur/setup-php@v2
21 | with:
22 | php-version: ${{ matrix.php-versions }}
23 | coverage: xdebug
24 |
25 | # https://github.com/marketplace/actions/checkout
26 | - name: Checkout code
27 | uses: actions/checkout@v3
28 |
29 | - name: Install PHPUnit ${{ matrix.phpunit-versions }}
30 | run: |
31 | rm composer.lock
32 | composer require phpunit/phpunit ^${{ matrix.phpunit-versions }}
33 |
34 | - name: Install dependencies
35 | run: composer install --prefer-dist
36 |
37 | - name: Run PHPStan
38 | run: vendor/bin/phpstan analyse
39 |
40 | #- name: Run PHPcs fixer dry-run
41 | # run: vendor/bin/php-cs-fixer fix --dry-run --stop-on-violation --config=.php-cs-fixer.dist.php
42 |
43 | - name: Run test suite
44 | run: vendor/bin/phpunit --fail-on-incomplete --log-junit junit.xml --coverage-clover clover.xml
45 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor
2 | .phpunit.cache
3 | .phpunit.result.cache
4 | .php-cs-fixer.cache
--------------------------------------------------------------------------------
/.php-cs-fixer.dist.php:
--------------------------------------------------------------------------------
1 | in(__DIR__)
5 | ->exclude('var')
6 | ->exclude('vendor')
7 | ->exclude('docker')
8 | ->exclude('bin');
9 |
10 | return (new PhpCsFixer\Config)
11 | ->setRules([
12 | '@Symfony' => true
13 | ])
14 | ->setFinder($finder);
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Robin Ingelbrecht
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | compose=docker compose
2 |
3 | dc:
4 | @${compose} -f docker-compose.yml $(cmd)
5 |
6 | dcr:
7 | @make dc cmd="run --rm php-cli $(cmd)"
8 |
9 | stop:
10 | @make dc cmd="stop"
11 |
12 | up:
13 | @make dc cmd="up -d"
14 |
15 | build-containers:
16 | @make dc cmd="up -d --build"
17 |
18 | down:
19 | @make dc cmd="down"
20 |
21 | composer:
22 | @make dcr cmd="composer $(arg)"
23 |
24 | # Code quality tools.
25 | phpunit:
26 | @make dcr cmd="vendor/bin/phpunit -d --enable-pretty-print -d --compact $(arg)"
27 |
28 | phpunit-with-coverage-report:
29 | @make phpunit arg="--coverage-clover=clover.xml -d --min-coverage=min-coverage-rules.php"
30 |
31 | phpstan:
32 | @make dcr cmd="vendor/bin/phpstan --memory-limit=1G $(arg)"
33 |
34 | csfix:
35 | @make dcr cmd="vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php"
36 |
37 | delete-snapshots:
38 | find . -name __snapshots__ -type d -prune -exec rm -rf {} \;
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
Better PHPUnit CLI output
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | ---
18 |
19 | I really like how [Pest PHP](https://pestphp.com/) formats and outputs test results,
20 | but I still prefer to use [PHPUnit](https://phpunit.de/). Luckily there's [Collision](https://github.com/nunomaduro/collision).
21 | This package is designed to give you beautiful error reporting when interacting with your app through the command line.
22 |
23 | ## Installation
24 |
25 | ```bash
26 | composer require robiningelbrecht/phpunit-pretty-print --dev
27 | ```
28 |
29 | ## Configuration
30 |
31 | Navigate to your `phpunit.xml.dist` file and add following config to set default options
32 | (you can also set these options at run time):
33 |
34 | ```xml
35 |
36 |
37 |
38 |
39 | ```
40 |
41 | Also make sure the `color` attribute is set to `true`:
42 |
43 | ```xml
44 |
46 |
47 | ```
48 |
49 | ## Options
50 |
51 | All these options can be set at runtime as well, see usage.
52 |
53 | ### Output profiling report
54 |
55 | ```xml
56 |
57 |
58 |
59 |
60 |
61 | ```
62 |
63 | ### Enable compact mode
64 |
65 | ```xml
66 |
67 |
68 |
69 |
70 |
71 | ```
72 |
73 | ### Feel good about yourself after running your testsuite by displaying a Chuck Noris quote
74 |
75 | ```xml
76 |
77 |
78 |
79 |
80 |
81 | ```
82 |
83 | ### Disable pretty print.
84 |
85 | This can be useful when you only want to prettify the output when forced via CLI (see usage).
86 |
87 | ```xml
88 |
89 |
90 |
91 |
92 |
93 | ```
94 |
95 | ## Usage
96 |
97 | ```bash
98 | > vendor/bin/phpunit
99 | ```
100 |
101 |
102 |
103 |
104 |
105 | ### Output profiling report
106 |
107 | ```bash
108 | > vendor/bin/phpunit -d --profiling
109 | ```
110 |
111 |
112 |
113 |
114 |
115 | ### Enable compact mode
116 |
117 | ```bash
118 | > vendor/bin/phpunit -d --compact
119 | ```
120 |
121 |
122 |
123 |
124 |
125 | ### Display Chuck Norris quote
126 |
127 | ```bash
128 | > vendor/bin/phpunit -d --display-quote
129 | ```
130 |
131 |
132 |
133 |
134 |
135 | ### Enable/disable pretty print
136 |
137 | ```bash
138 | > vendor/bin/phpunit -d --enable-pretty-print
139 | > vendor/bin/phpunit -d --disable-pretty-print
140 | ```
141 |
142 | ### Combine multiple options
143 |
144 | ```bash
145 | > vendor/bin/phpunit --configuration=tests/phpunit.test.xml -d --compact -d --display-quote
146 | ```
147 |
148 | ## PHPUnit 9.x
149 |
150 | This package does not support PHPUnit 9.x but Collision does out of the box. Run
151 |
152 | ```bash
153 | composer require nunomaduro/collision:^6.0
154 | ```
155 |
156 | Then add the Collision `printerClass` to your `phpunit.xml` in the `phpunit` section:
157 |
158 | ```xml
159 |
161 | ```
162 |
163 | ## Acknowledgements
164 |
165 | * API used for Chuck Noris quotes: https://api.chucknorris.io/
166 | * CLI formatting: https://github.com/nunomaduro/collision
167 |
168 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "robiningelbrecht/phpunit-pretty-print",
3 | "description": "Prettify PHPUnit output",
4 | "keywords": [
5 | "Testing",
6 | "PHP",
7 | "phpunit"
8 | ],
9 | "type": "library",
10 | "license": "MIT",
11 | "authors": [
12 | {
13 | "name": "Robin Ingelbrecht",
14 | "email": "ingelbrecht_robin@hotmail.com"
15 | }
16 | ],
17 | "require": {
18 | "php": "^8.1",
19 | "nunomaduro/collision": "^7.8|^8.0",
20 | "phpunit/phpunit": "^10.3|^11.0|^12.0"
21 | },
22 | "autoload": {
23 | "psr-4": {
24 | "RobinIngelbrecht\\PHPUnitPrettyPrint\\": "src/"
25 | }
26 | },
27 | "autoload-dev": {
28 | "psr-4": {
29 | "Tests\\": "tests/"
30 | }
31 | },
32 | "require-dev": {
33 | "friendsofphp/php-cs-fixer": "^3.9",
34 | "phpstan/phpstan": "^1.10",
35 | "spatie/phpunit-snapshot-assertions": "^5.0"
36 | },
37 | "config": {
38 | "sort-packages": true
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | services:
2 | php-cli:
3 | build: ./docker/php-cli
4 | container_name: phpunit-pretty-print-php-cli
5 | environment:
6 | - PHP_CS_FIXER_IGNORE_ENV=true
7 | volumes:
8 | - ./:/var/www/
9 | working_dir: /var/www
10 |
11 |
--------------------------------------------------------------------------------
/docker/php-cli/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM php:8.4-cli
2 |
3 | RUN apt-get update && apt-get install -y zip unzip git curl
4 | RUN docker-php-ext-install mysqli pdo pdo_mysql
5 |
6 | COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
--------------------------------------------------------------------------------
/phpstan.neon:
--------------------------------------------------------------------------------
1 | parameters:
2 | level: 9
3 | paths:
4 | - src
5 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 | tests/OutputTest.php
13 | tests/Unit
14 |
15 |
16 |
17 |
18 | src
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/readme/example-compact.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robiningelbrecht/phpunit-pretty-print/1faaf1b078674ef448e6ab24721db539d3cfca72/readme/example-compact.png
--------------------------------------------------------------------------------
/readme/example-default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robiningelbrecht/phpunit-pretty-print/1faaf1b078674ef448e6ab24721db539d3cfca72/readme/example-default.png
--------------------------------------------------------------------------------
/readme/example-profiling.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robiningelbrecht/phpunit-pretty-print/1faaf1b078674ef448e6ab24721db539d3cfca72/readme/example-profiling.png
--------------------------------------------------------------------------------
/readme/example-quote.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robiningelbrecht/phpunit-pretty-print/1faaf1b078674ef448e6ab24721db539d3cfca72/readme/example-quote.png
--------------------------------------------------------------------------------
/readme/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robiningelbrecht/phpunit-pretty-print/1faaf1b078674ef448e6ab24721db539d3cfca72/readme/logo.png
--------------------------------------------------------------------------------
/src/Configuration.php:
--------------------------------------------------------------------------------
1 | displayProfiling;
19 | }
20 |
21 | public function displayQuote(): bool
22 | {
23 | return $this->displayQuote;
24 | }
25 |
26 | public function useCompactMode(): bool
27 | {
28 | return $this->useCompactMode;
29 | }
30 |
31 | public static function fromParameterCollection(ParameterCollection $parameters): self
32 | {
33 | if (!$useProfiling = in_array('--profiling', $_SERVER['argv'], true)) {
34 | $useProfiling = $parameters->has('displayProfiling') && !self::isFalsy($parameters->get('displayProfiling'));
35 | }
36 | if (!$useCompactMode = in_array('--compact', $_SERVER['argv'], true)) {
37 | $useCompactMode = $parameters->has('useCompactMode') && !self::isFalsy($parameters->get('useCompactMode'));
38 | }
39 | if (!$displayQuote = in_array('--display-quote', $_SERVER['argv'], true)) {
40 | $displayQuote = $parameters->has('displayQuote') && !self::isFalsy($parameters->get('displayQuote'));
41 | }
42 |
43 | return new self(
44 | $useProfiling,
45 | $displayQuote,
46 | $useCompactMode,
47 | );
48 | }
49 |
50 | public static function isFalsy(mixed $value): bool
51 | {
52 | if (is_bool($value)) {
53 | return !$value;
54 | }
55 | if ('true' === $value) {
56 | return false;
57 | }
58 | if ('false' === $value) {
59 | return true;
60 | }
61 | if (is_int($value)) {
62 | return !$value;
63 | }
64 |
65 | return true;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/PhpUnitExtension.php:
--------------------------------------------------------------------------------
1 | isEnabled($parameters)) {
19 | return;
20 | }
21 |
22 | $_SERVER['PHPUNIT_RANDOM_ORDER_SEED'] = TestSuiteSorter::ORDER_RANDOMIZED === $configuration->executionOrder() ? $configuration->randomOrderSeed() : null;
23 | $configuration = Configuration::fromParameterCollection($parameters);
24 |
25 | $facade->replaceOutput();
26 | $facade->replaceProgressOutput();
27 | $facade->replaceResultOutput();
28 |
29 | $_SERVER['COLLISION_PRINTER'] = true;
30 | if ($configuration->useCompactMode()) {
31 | $_SERVER['COLLISION_PRINTER_COMPACT'] = true;
32 | }
33 | if ($configuration->displayProfiling()) {
34 | $_SERVER['COLLISION_PRINTER_PROFILE'] = true;
35 | }
36 |
37 | EnsurePrinterIsRegisteredSubscriber::register();
38 |
39 | $facade->registerSubscriber(new ApplicationStartedSubscriber());
40 | if (!$configuration->displayQuote()) {
41 | return;
42 | }
43 | $facade->registerSubscriber(new ApplicationFinishedSubscriber());
44 | }
45 |
46 | private function isEnabled(ParameterCollection $parameters): bool
47 | {
48 | if (!$parameters->has('enableByDefault')
49 | && !in_array('--enable-pretty-print', $_SERVER['argv'], true)
50 | && !in_array('--disable-pretty-print', $_SERVER['argv'], true)) {
51 | // Nothing has been set, assume the extension is enabled for backwards compatible reasons.
52 | return true;
53 | }
54 |
55 | if (in_array('--enable-pretty-print', $_SERVER['argv'], true)) {
56 | return true;
57 | }
58 | if (in_array('--disable-pretty-print', $_SERVER['argv'], true)) {
59 | return false;
60 | }
61 |
62 | if ($parameters->has('enableByDefault') && !Configuration::isFalsy($parameters->get('enableByDefault'))) {
63 | return true;
64 | }
65 |
66 | return false;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/Quotes.php:
--------------------------------------------------------------------------------
1 | %s', Quotes::getRandom()));
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Subscriber/Application/ApplicationStartedSubscriber.php:
--------------------------------------------------------------------------------
1 | ');
15 | render(sprintf(
16 | ' Runtime: %s
',
17 | $event->runtime()->asString()
18 | ));
19 | if (!empty($_SERVER['PHPUNIT_RANDOM_ORDER_SEED'])) {
20 | render(sprintf(
21 | ' Random Seed: %s
',
22 | $_SERVER['PHPUNIT_RANDOM_ORDER_SEED']
23 | ));
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/tests/ExampleTests/TestThatHasAllStatusesTest.php:
--------------------------------------------------------------------------------
1 | assertTrue(true);
24 | }
25 |
26 | public function testFail(): void
27 | {
28 | $this->assertTrue(false);
29 | }
30 |
31 | public function testFailWithDiff(): void
32 | {
33 | $this->assertEquals(
34 | ['one', 'two'],
35 | ['two', 'one']
36 | );
37 | }
38 |
39 | public function testError(): void
40 | {
41 | throw new \Exception('error');
42 | }
43 |
44 | public function testRisky(): void
45 | {
46 | }
47 |
48 | public function testSkip(): void
49 | {
50 | $this->markTestSkipped('skipped');
51 | }
52 |
53 | public function testIncomplete(): void
54 | {
55 | $this->markTestIncomplete('incomplete');
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/tests/ExampleTests/TestThatPassesTest.php:
--------------------------------------------------------------------------------
1 | assertFalse(false);
15 | $this->assertEquals(1, 1);
16 | }
17 |
18 | public function testDoSomeMoreAssertions(): void
19 | {
20 | usleep(self::SLEEP_IN_MICRO_SECONDS);
21 | $this->assertFalse(false);
22 | $this->assertEquals(1, 1);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tests/OutputTest.php:
--------------------------------------------------------------------------------
1 | assertStringContainsString('Tests: 3 failed, 1 risky, 1 incomplete, 1 skipped, 3 passed (7 assertions)', $output);
23 | $this->assertStringNotContainsString('Random Seed:', $output);
24 | }
25 |
26 | public function testWithProfiling(): void
27 | {
28 | $command = [
29 | 'vendor/bin/phpunit',
30 | '--configuration=tests/phpunit.test-profiling.xml',
31 | ];
32 |
33 | exec(implode(' ', $command), $out);
34 | $output = implode(PHP_EOL, $out);
35 |
36 | $this->assertMatchesRegularExpression('/Runtime: PHPUnit [\s\S]+ using PHP [\s\S]+ on [\s\S]+/', $output);
37 | $this->assertStringContainsString('Tests: 2 passed (4 assertions)', $output);
38 | $this->assertStringContainsString('Top 10 slowest tests', $output);
39 | }
40 |
41 | public function testWithProfilingAtRunTime(): void
42 | {
43 | $command = [
44 | 'vendor/bin/phpunit',
45 | 'tests/ExampleTests/TestThatPassesTest.php',
46 | '--configuration=tests/phpunit.test.xml',
47 | '-d --profiling',
48 | ];
49 | exec(implode(' ', $command), $out);
50 | $output = implode(PHP_EOL, $out);
51 |
52 | $this->assertMatchesRegularExpression('/Runtime: PHPUnit [\s\S]+ using PHP [\s\S]+ on [\s\S]+/', $output);
53 | $this->assertStringContainsString('Tests: 2 passed (4 assertions)', $output);
54 | $this->assertStringContainsString('Top 10 slowest tests', $output);
55 | }
56 |
57 | public function testPrintCompactMode(): void
58 | {
59 | $command = [
60 | 'vendor/bin/phpunit',
61 | '--configuration=tests/phpunit.test-compact-mode.xml',
62 | ];
63 |
64 | exec(implode(' ', $command), $out);
65 | $output = implode(PHP_EOL, $out);
66 |
67 | $this->assertMatchesRegularExpression('/Runtime: PHPUnit [\s\S]+ using PHP [\s\S]+ on [\s\S]+/', $output);
68 | $this->assertStringContainsString('.⨯⨯⨯!si..', $output);
69 | $this->assertStringContainsString('Tests: 3 failed, 1 risky, 1 incomplete, 1 skipped, 3 passed (7 assertions)', $output);
70 | }
71 |
72 | public function testPrintCompactModeAtRunTime(): void
73 | {
74 | $command = [
75 | 'vendor/bin/phpunit',
76 | '--configuration=tests/phpunit.test.xml',
77 | '-d --compact',
78 | ];
79 | exec(implode(' ', $command), $out);
80 | $output = implode(PHP_EOL, $out);
81 |
82 | $this->assertMatchesRegularExpression('/Runtime: PHPUnit [\s\S]+ using PHP [\s\S]+ on [\s\S]+/', $output);
83 | $this->assertStringContainsString('.⨯⨯⨯!si..', $output);
84 | $this->assertStringContainsString('Tests: 3 failed, 1 risky, 1 incomplete, 1 skipped, 3 passed (7 assertions)', $output);
85 | }
86 |
87 | public function testPrintWithQuote(): void
88 | {
89 | $command = [
90 | 'vendor/bin/phpunit',
91 | '--configuration=tests/phpunit.test-with-quotes.xml',
92 | ];
93 |
94 | exec(implode(' ', $command), $out);
95 |
96 | $print = implode(PHP_EOL, $out);
97 |
98 | $printContainsQuote = false;
99 | foreach (Quotes::getAll() as $quote) {
100 | if (!str_contains($print, $quote)) {
101 | continue;
102 | }
103 |
104 | $printContainsQuote = true;
105 | $this->addToAssertionCount(1);
106 | }
107 |
108 | if (!$printContainsQuote) {
109 | $this->fail('Quote not found');
110 | }
111 | }
112 |
113 | public function testPrintWithQuoteAtRuntime(): void
114 | {
115 | $command = [
116 | 'vendor/bin/phpunit',
117 | '--configuration=tests/phpunit.test.xml',
118 | '-d --display-quote',
119 | ];
120 |
121 | exec(implode(' ', $command), $out);
122 |
123 | $print = implode(PHP_EOL, $out);
124 |
125 | $printContainsQuote = false;
126 | foreach (Quotes::getAll() as $quote) {
127 | if (!str_contains($print, $quote)) {
128 | continue;
129 | }
130 |
131 | $printContainsQuote = true;
132 | $this->addToAssertionCount(1);
133 | }
134 |
135 | if (!$printContainsQuote) {
136 | $this->fail('Quote not found');
137 | }
138 | }
139 |
140 | public function testPrintWithRandomSeed(): void
141 | {
142 | $command = [
143 | 'vendor/bin/phpunit',
144 | '--configuration=tests/phpunit.test.xml',
145 | '--order-by=random',
146 | ];
147 |
148 | exec(implode(' ', $command), $out);
149 | $output = implode(PHP_EOL, $out);
150 | $this->assertStringContainsString('Tests: 3 failed, 1 risky, 1 incomplete, 1 skipped, 3 passed (7 assertions)', $output);
151 | $this->assertStringContainsString('Random Seed:', $output);
152 | }
153 |
154 | public function testItShouldBeEnabled(): void
155 | {
156 | $command = [
157 | 'vendor/bin/phpunit',
158 | 'tests/ExampleTests/TestThatPassesTest.php',
159 | '--configuration=tests/phpunit.test-disable-by-default.xml',
160 | '-d --enable-pretty-print',
161 | ];
162 | exec(implode(' ', $command), $out);
163 | $output = implode(PHP_EOL, $out);
164 |
165 | $this->assertMatchesRegularExpression('/Runtime: PHPUnit [\s\S]+ using PHP [\s\S]+ on [\s\S]+/', $output);
166 | $this->assertStringContainsString('Tests: 2 passed (4 assertions)', $output);
167 | }
168 |
169 | public function testItShouldBeDisabled(): void
170 | {
171 | $command = [
172 | 'vendor/bin/phpunit',
173 | 'tests/ExampleTests/TestThatPassesTest.php',
174 | '--configuration=tests/phpunit.test-disable-by-default.xml',
175 | ];
176 | exec(implode(' ', $command), $out);
177 | $output = implode(PHP_EOL, $out);
178 |
179 | $this->assertDoesNotMatchRegularExpression('/Runtime: PHPUnit [\s\S]+ using PHP [\s\S]+ on [\s\S]+/', $output);
180 | $this->assertStringContainsString('OK (2 tests, 4 assertions)', $output);
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/tests/SpyOutput.php:
--------------------------------------------------------------------------------
1 | messages = [...$this->messages, ...$messages];
17 | }
18 |
19 | public function write(string|iterable $messages, bool $newline = false, int $options = self::OUTPUT_NORMAL): void
20 | {
21 | if (!is_iterable($messages)) {
22 | $messages = [$messages];
23 | }
24 | $this->messages = [...$this->messages, ...$messages];
25 | }
26 |
27 | public function __toString(): string
28 | {
29 | return implode(PHP_EOL, $this->messages);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/tests/Unit/ConfigurationTest.php:
--------------------------------------------------------------------------------
1 | originalServer = $_SERVER;
18 | }
19 |
20 | protected function tearDown(): void
21 | {
22 | parent::tearDown();
23 |
24 | $_SERVER = $this->originalServer;
25 | }
26 |
27 | public function testFromParameterCollection(): void
28 | {
29 | $configuration = Configuration::fromParameterCollection(ParameterCollection::fromArray([
30 | 'displayProfiling' => 'true',
31 | 'useCompactMode' => 'true',
32 | 'displayQuote' => 'true',
33 | ]));
34 |
35 | $this->assertTrue($configuration->displayProfiling());
36 | $this->assertTrue($configuration->useCompactMode());
37 | $this->assertTrue($configuration->displayQuote());
38 |
39 | $configuration = Configuration::fromParameterCollection(ParameterCollection::fromArray([]));
40 |
41 | $this->assertFalse($configuration->displayProfiling());
42 | $this->assertFalse($configuration->useCompactMode());
43 | $this->assertFalse($configuration->displayQuote());
44 | }
45 |
46 | public function testFromParameterCollectionWithServerArguments(): void
47 | {
48 | $_SERVER['argv'][] = '--profiling';
49 | $_SERVER['argv'][] = '--compact';
50 | $_SERVER['argv'][] = '--display-quote';
51 | $configuration = Configuration::fromParameterCollection(ParameterCollection::fromArray([]));
52 |
53 | $this->assertTrue($configuration->displayProfiling());
54 | $this->assertTrue($configuration->useCompactMode());
55 | $this->assertTrue($configuration->displayQuote());
56 | }
57 |
58 | public function testIsFalsy(): void
59 | {
60 | $this->assertTrue(Configuration::isFalsy(0));
61 | $this->assertTrue(Configuration::isFalsy('false'));
62 | $this->assertTrue(Configuration::isFalsy(false));
63 | $this->assertTrue(Configuration::isFalsy('test'));
64 |
65 | $this->assertFalse(Configuration::isFalsy(1));
66 | $this->assertFalse(Configuration::isFalsy('true'));
67 | $this->assertFalse(Configuration::isFalsy(true));
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/tests/Unit/PhpUnitExtensionTest.php:
--------------------------------------------------------------------------------
1 | originalServer = $_SERVER;
21 |
22 | // We need to do some reflection magic here because of pour decisions in PHPUnit
23 | $eventFacade = EventFacade::instance();
24 | $reflection = new \ReflectionClass($eventFacade);
25 | $sealed = $reflection->getProperty('sealed');
26 | $sealed->setAccessible(true);
27 | $sealed->setValue($eventFacade, false);
28 | }
29 |
30 | protected function tearDown(): void
31 | {
32 | parent::tearDown();
33 |
34 | $_SERVER = $this->originalServer;
35 | }
36 |
37 | public function testBootstrapWithAllOptions(): void
38 | {
39 | $facade = new Facade();
40 |
41 | $configuration = (new Builder())->build([]);
42 | $parameters = ParameterCollection::fromArray([
43 | 'displayProfiling' => 'true',
44 | 'useCompactMode' => 'true',
45 | 'displayQuote' => 'true',
46 | ]);
47 |
48 | $extension = new PhpUnitExtension();
49 |
50 | $extension->bootstrap(
51 | $configuration,
52 | $facade,
53 | $parameters
54 | );
55 |
56 | $this->assertTrue($facade->replacesOutput());
57 | $this->assertTrue($facade->replacesProgressOutput());
58 | $this->assertTrue($facade->replacesResultOutput());
59 |
60 | $this->assertContains('COLLISION_PRINTER_COMPACT', array_keys($_SERVER));
61 | $this->assertContains('COLLISION_PRINTER_PROFILE', array_keys($_SERVER));
62 | }
63 |
64 | public function testBootstrapInCompactMode(): void
65 | {
66 | $facade = new Facade();
67 | $configuration = (new Builder())->build([]);
68 | $parameters = ParameterCollection::fromArray([
69 | 'useCompactMode' => 'true',
70 | ]);
71 |
72 | $extension = new PhpUnitExtension();
73 |
74 | $extension->bootstrap(
75 | $configuration,
76 | $facade,
77 | $parameters
78 | );
79 |
80 | $this->assertTrue($facade->replacesOutput());
81 | $this->assertTrue($facade->replacesProgressOutput());
82 | $this->assertTrue($facade->replacesResultOutput());
83 |
84 | $this->assertContains('COLLISION_PRINTER_COMPACT', array_keys($_SERVER));
85 | $this->assertNotContains('COLLISION_PRINTER_PROFILE', array_keys($_SERVER));
86 | }
87 |
88 | public function testBootstrapWithDisplayProfiling(): void
89 | {
90 | $facade = new Facade();
91 | $configuration = (new Builder())->build([]);
92 | $parameters = ParameterCollection::fromArray([
93 | 'displayProfiling' => 'true',
94 | ]);
95 |
96 | $extension = new PhpUnitExtension();
97 |
98 | $extension->bootstrap(
99 | $configuration,
100 | $facade,
101 | $parameters
102 | );
103 |
104 | $this->assertTrue($facade->replacesOutput());
105 | $this->assertTrue($facade->replacesProgressOutput());
106 | $this->assertTrue($facade->replacesResultOutput());
107 |
108 | $this->assertNotContains('COLLISION_PRINTER_COMPACT', array_keys($_SERVER));
109 | $this->assertContains('COLLISION_PRINTER_PROFILE', array_keys($_SERVER));
110 | }
111 |
112 | public function testBootstrapWithDisplayQuote(): void
113 | {
114 | $facade = new Facade();
115 | $configuration = (new Builder())->build([]);
116 | $parameters = ParameterCollection::fromArray([
117 | 'displayQuote' => 'true',
118 | ]);
119 |
120 | $extension = new PhpUnitExtension();
121 |
122 | $extension->bootstrap(
123 | $configuration,
124 | $facade,
125 | $parameters
126 | );
127 |
128 | $this->assertTrue($facade->replacesOutput());
129 | $this->assertTrue($facade->replacesProgressOutput());
130 | $this->assertTrue($facade->replacesResultOutput());
131 |
132 | $this->assertNotContains('COLLISION_PRINTER_COMPACT', array_keys($_SERVER));
133 | $this->assertNotContains('COLLISION_PRINTER_PROFILE', array_keys($_SERVER));
134 | }
135 |
136 | public function testItShouldBeEnabledThroughCli(): void
137 | {
138 | $facade = new Facade();
139 | $configuration = (new Builder())->build([]);
140 | $parameters = ParameterCollection::fromArray([
141 | 'displayProfiling' => 'true',
142 | 'useCompactMode' => 'true',
143 | 'displayQuote' => 'true',
144 | 'enableByDefault' => 'false',
145 | ]);
146 |
147 | $extension = new PhpUnitExtension();
148 |
149 | $_SERVER['argv'][] = '--enable-pretty-print';
150 |
151 | $extension->bootstrap(
152 | $configuration,
153 | $facade,
154 | $parameters
155 | );
156 |
157 | $this->assertTrue($facade->replacesOutput());
158 | $this->assertTrue($facade->replacesProgressOutput());
159 | $this->assertTrue($facade->replacesResultOutput());
160 |
161 | $this->assertContains('COLLISION_PRINTER_COMPACT', array_keys($_SERVER));
162 | $this->assertContains('COLLISION_PRINTER_PROFILE', array_keys($_SERVER));
163 | }
164 |
165 | public function testItShouldBeDisabledThroughCli(): void
166 | {
167 | $facade = new Facade();
168 | $configuration = (new Builder())->build([]);
169 | $parameters = ParameterCollection::fromArray([
170 | 'displayProfiling' => 'true',
171 | 'useCompactMode' => 'true',
172 | 'displayQuote' => 'true',
173 | ]);
174 |
175 | $extension = new PhpUnitExtension();
176 |
177 | $_SERVER['argv'][] = '--disable-pretty-print';
178 |
179 | $extension->bootstrap(
180 | $configuration,
181 | $facade,
182 | $parameters
183 | );
184 |
185 | $this->assertFalse($facade->replacesOutput());
186 | $this->assertFalse($facade->replacesProgressOutput());
187 | $this->assertFalse($facade->replacesResultOutput());
188 |
189 | $this->assertNotContains('COLLISION_PRINTER_COMPACT', array_keys($_SERVER));
190 | $this->assertNotContains('COLLISION_PRINTER_PROFILE', array_keys($_SERVER));
191 | }
192 |
193 | public function testItShouldBeEnabledWithParameter(): void
194 | {
195 | $facade = new Facade();
196 | $configuration = (new Builder())->build([]);
197 | $parameters = ParameterCollection::fromArray([
198 | 'displayProfiling' => 'true',
199 | 'useCompactMode' => 'true',
200 | 'displayQuote' => 'true',
201 | 'enableByDefault' => 'true',
202 | ]);
203 |
204 | $extension = new PhpUnitExtension();
205 |
206 | $extension->bootstrap(
207 | $configuration,
208 | $facade,
209 | $parameters
210 | );
211 |
212 | $this->assertTrue($facade->replacesOutput());
213 | $this->assertTrue($facade->replacesProgressOutput());
214 | $this->assertTrue($facade->replacesResultOutput());
215 |
216 | $this->assertContains('COLLISION_PRINTER_COMPACT', array_keys($_SERVER));
217 | $this->assertContains('COLLISION_PRINTER_PROFILE', array_keys($_SERVER));
218 | }
219 |
220 | public function testItShouldBeDisabledWithParameter(): void
221 | {
222 | $facade = new Facade();
223 | $configuration = (new Builder())->build([]);
224 | $parameters = ParameterCollection::fromArray([
225 | 'displayProfiling' => 'true',
226 | 'useCompactMode' => 'true',
227 | 'displayQuote' => 'true',
228 | 'enableByDefault' => 'false',
229 | ]);
230 |
231 | $extension = new PhpUnitExtension();
232 |
233 | $extension->bootstrap(
234 | $configuration,
235 | $facade,
236 | $parameters
237 | );
238 |
239 | $this->assertFalse($facade->replacesOutput());
240 | $this->assertFalse($facade->replacesProgressOutput());
241 | $this->assertFalse($facade->replacesResultOutput());
242 |
243 | $this->assertNotContains('COLLISION_PRINTER_COMPACT', array_keys($_SERVER));
244 | $this->assertNotContains('COLLISION_PRINTER_PROFILE', array_keys($_SERVER));
245 | }
246 | }
247 |
--------------------------------------------------------------------------------
/tests/Unit/Subscriber/Application/ApplicationFinishedSubscriberTest.php:
--------------------------------------------------------------------------------
1 | notify(new Finished(
30 | new Info(
31 | new Snapshot(
32 | HRTime::fromSecondsAndNanoseconds(1, 0),
33 | MemoryUsage::fromBytes(100),
34 | MemoryUsage::fromBytes(100),
35 | new GarbageCollectorStatus(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
36 | ),
37 | Duration::fromSecondsAndNanoseconds(1, 0),
38 | MemoryUsage::fromBytes(100),
39 | Duration::fromSecondsAndNanoseconds(1, 0),
40 | MemoryUsage::fromBytes(100),
41 | ),
42 | 0
43 | ));
44 |
45 | $this->assertEquals(3, substr_count($spyOutput, ''));
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/tests/Unit/Subscriber/Application/ApplicationStartedSubscriberTest.php:
--------------------------------------------------------------------------------
1 | notify(new Started(
31 | new Info(
32 | new Snapshot(
33 | HRTime::fromSecondsAndNanoseconds(1, 0),
34 | MemoryUsage::fromBytes(100),
35 | MemoryUsage::fromBytes(100),
36 | new GarbageCollectorStatus(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
37 | ),
38 | Duration::fromSecondsAndNanoseconds(1, 0),
39 | MemoryUsage::fromBytes(100),
40 | Duration::fromSecondsAndNanoseconds(1, 0),
41 | MemoryUsage::fromBytes(100),
42 | ),
43 | new Runtime()
44 | ));
45 |
46 | $this->assertMatchesRegularExpression('/Runtime: PHPUnit [\s\S]+ using PHP [\s\S]+ on [\s\S]+/', $spyOutput);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/tests/phpunit.test-compact-mode.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | ExampleTests
19 |
20 |
21 |
22 |
23 |
24 | src
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/tests/phpunit.test-disable-by-default.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | ExampleTests
19 |
20 |
21 |
22 |
23 |
24 | src
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/tests/phpunit.test-profiling.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | ExampleTests/TestThatPassesTest.php
19 |
20 |
21 |
22 |
23 |
24 | src
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/tests/phpunit.test-with-quotes.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | ExampleTests
19 |
20 |
21 |
22 |
23 |
24 | src
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/tests/phpunit.test.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | ExampleTests
19 |
20 |
21 |
22 |
23 |
24 | src
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------