Skip to content

Commit ae1cf4f

Browse files
Closes #6276
1 parent 1a484ac commit ae1cf4f

16 files changed

Lines changed: 201 additions & 8 deletions

ChangeLog-12.5.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ All notable changes of the PHPUnit 12.5 release series are documented in this fi
99
* [#4571](https://github.com/sebastianbergmann/phpunit/issues/4571): No warning when `--random-order-seed` is used when test execution order is not random
1010
* [#4975](https://github.com/sebastianbergmann/phpunit/issues/4975): `--filter` does not work when filter string starts with `#`
1111
* [#5354](https://github.com/sebastianbergmann/phpunit/issues/5354): JUnit XML logger does not handle `TestSuiteSkipped` event
12+
* [#6276](https://github.com/sebastianbergmann/phpunit/issues/6276): Exit with non-zero exit code when explicit test selection (`--filter`, `--group`, `--testsuite`) yields no tests
1213

1314
## [12.5.17] - 2026-04-08
1415

src/TextUI/ShellExitCodeCalculator.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public function calculate(Configuration $configuration, TestResult $result): int
2929
$failOnPhpunitDeprecation = false;
3030
$failOnPhpunitNotice = false;
3131
$failOnPhpunitWarning = false;
32-
$failOnEmptyTestSuite = false;
32+
$failOnEmptyTestSuite = $this->hasExplicitTestSelection($configuration);
3333
$failOnIncomplete = false;
3434
$failOnNotice = false;
3535
$failOnRisky = false;
@@ -181,4 +181,33 @@ public function calculate(Configuration $configuration, TestResult $result): int
181181

182182
return $returnCode;
183183
}
184+
185+
private function hasExplicitTestSelection(Configuration $configuration): bool
186+
{
187+
if ($configuration->hasFilter()) {
188+
return true;
189+
}
190+
191+
if ($configuration->hasExcludeFilter()) {
192+
return true;
193+
}
194+
195+
if ($configuration->hasGroups()) {
196+
return true;
197+
}
198+
199+
if ($configuration->hasExcludeGroups()) {
200+
return true;
201+
}
202+
203+
if ($configuration->includeTestSuites() !== []) {
204+
return true;
205+
}
206+
207+
if ($configuration->excludeTestSuites() !== []) {
208+
return true;
209+
}
210+
211+
return false;
212+
}
184213
}

tests/end-to-end/cli/exclude-multiple-test-suites.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ Test Suite Sorted
2222
Test Runner Execution Started (0 tests)
2323
Test Runner Execution Finished
2424
Test Runner Finished
25-
PHPUnit Finished (Shell Exit Code: 0)
25+
PHPUnit Finished (Shell Exit Code: 1)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:noNamespaceSchemaLocation="../../../../../phpunit.xsd">
4+
<testsuites>
5+
<testsuite name="empty">
6+
<directory>tests</directory>
7+
</testsuite>
8+
</testsuites>
9+
</phpunit>

tests/end-to-end/cli/fail-on/_files/empty-directory/tests/.gitkeep

Whitespace-only changes.

tests/end-to-end/cli/fail-on/do-not-fail-on-empty-test-suite-by-default.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Test Runner exits with shell exit code indicating success by default when no tests were run
2+
Test Runner exits with shell exit code indicating failure when --filter is used and no tests match
33
--FILE--
44
<?php declare(strict_types=1);
55
$_SERVER['argv'][] = '--do-not-cache-result';
@@ -23,4 +23,4 @@ Test Suite Filtered (0 tests)
2323
Test Runner Execution Started (0 tests)
2424
Test Runner Execution Finished
2525
Test Runner Finished
26-
PHPUnit Finished (Shell Exit Code: 0)
26+
PHPUnit Finished (Shell Exit Code: 1)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
Test Runner exits with shell exit code indicating success by default when no tests were run and no explicit test selection was used
3+
--FILE--
4+
<?php declare(strict_types=1);
5+
$_SERVER['argv'][] = '--do-not-cache-result';
6+
$_SERVER['argv'][] = '--debug';
7+
$_SERVER['argv'][] = '--configuration';
8+
$_SERVER['argv'][] = __DIR__ . '/_files/empty-directory/phpunit.xml';
9+
10+
require __DIR__ . '/../../../bootstrap.php';
11+
12+
(new PHPUnit\TextUI\Application)->run($_SERVER['argv']);
13+
--EXPECTF--
14+
PHPUnit Started (PHPUnit %s using %s)
15+
Test Runner Configured
16+
Event Facade Sealed
17+
Test Suite Loaded (0 tests)
18+
Test Runner Started
19+
Test Suite Sorted
20+
Test Runner Execution Started (0 tests)
21+
Test Runner Execution Finished
22+
Test Runner Finished
23+
PHPUnit Finished (Shell Exit Code: 0)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Test Runner exits with shell exit code indicating success when --filter does not match and --do-not-fail-on-empty-test-suite is used
3+
--FILE--
4+
<?php declare(strict_types=1);
5+
$_SERVER['argv'][] = '--do-not-cache-result';
6+
$_SERVER['argv'][] = '--no-configuration';
7+
$_SERVER['argv'][] = '--debug';
8+
$_SERVER['argv'][] = '--filter';
9+
$_SERVER['argv'][] = 'doesNotExist';
10+
$_SERVER['argv'][] = '--do-not-fail-on-empty-test-suite';
11+
$_SERVER['argv'][] = __DIR__ . '/../../event/_files/SuccessTest.php';
12+
13+
require __DIR__ . '/../../../bootstrap.php';
14+
15+
(new PHPUnit\TextUI\Application)->run($_SERVER['argv']);
16+
--EXPECTF--
17+
PHPUnit Started (PHPUnit %s using %s)
18+
Test Runner Configured
19+
Event Facade Sealed
20+
Test Suite Loaded (1 test)
21+
Test Runner Started
22+
Test Suite Sorted
23+
Test Suite Filtered (0 tests)
24+
Test Runner Execution Started (0 tests)
25+
Test Runner Execution Finished
26+
Test Runner Finished
27+
PHPUnit Finished (Shell Exit Code: 0)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Test Runner exits with shell exit code indicating success when --group does not match and --do-not-fail-on-empty-test-suite is used
3+
--FILE--
4+
<?php declare(strict_types=1);
5+
$_SERVER['argv'][] = '--do-not-cache-result';
6+
$_SERVER['argv'][] = '--no-configuration';
7+
$_SERVER['argv'][] = '--debug';
8+
$_SERVER['argv'][] = '--group';
9+
$_SERVER['argv'][] = 'doesNotExist';
10+
$_SERVER['argv'][] = '--do-not-fail-on-empty-test-suite';
11+
$_SERVER['argv'][] = __DIR__ . '/../../_files/groups/tests/FooTest.php';
12+
13+
require __DIR__ . '/../../../bootstrap.php';
14+
15+
(new PHPUnit\TextUI\Application)->run($_SERVER['argv']);
16+
--EXPECTF--
17+
PHPUnit Started (PHPUnit %s using %s)
18+
Test Runner Configured
19+
Event Facade Sealed
20+
Test Suite Loaded (3 tests)
21+
Test Runner Started
22+
Test Suite Sorted
23+
Test Suite Filtered (0 tests)
24+
Test Runner Execution Started (0 tests)
25+
Test Runner Execution Finished
26+
Test Runner Finished
27+
PHPUnit Finished (Shell Exit Code: 0)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
Test Runner exits with shell exit code indicating failure when --group does not match any tests
3+
--FILE--
4+
<?php declare(strict_types=1);
5+
$_SERVER['argv'][] = '--do-not-cache-result';
6+
$_SERVER['argv'][] = '--no-configuration';
7+
$_SERVER['argv'][] = '--debug';
8+
$_SERVER['argv'][] = '--group';
9+
$_SERVER['argv'][] = 'doesNotExist';
10+
$_SERVER['argv'][] = __DIR__ . '/../../_files/groups/tests/FooTest.php';
11+
12+
require __DIR__ . '/../../../bootstrap.php';
13+
14+
(new PHPUnit\TextUI\Application)->run($_SERVER['argv']);
15+
--EXPECTF--
16+
PHPUnit Started (PHPUnit %s using %s)
17+
Test Runner Configured
18+
Event Facade Sealed
19+
Test Suite Loaded (3 tests)
20+
Test Runner Started
21+
Test Suite Sorted
22+
Test Suite Filtered (0 tests)
23+
Test Runner Execution Started (0 tests)
24+
Test Runner Execution Finished
25+
Test Runner Finished
26+
PHPUnit Finished (Shell Exit Code: 1)

0 commit comments

Comments
 (0)