Skip to content

Commit 27ba995

Browse files
akotulusebastianbergmann
authored andcommitted
Resolved test suite run in separated process executed one by one in separated process.
1 parent de81d0e commit 27ba995

9 files changed

+450
-150
lines changed

phpunit.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
<directory suffix=".phpt">tests/end-to-end/mock-objects</directory>
3232
<directory suffix=".phpt">tests/end-to-end/phpt</directory>
3333
<directory suffix=".phpt">tests/end-to-end/regression</directory>
34+
<directory suffix=".phpt">tests/end-to-end/sandbox</directory>
3435
<directory suffix=".phpt">tests/end-to-end/self-direct-indirect</directory>
3536
<directory suffix=".phpt">tests/end-to-end/testdox</directory>
3637

src/Framework/TestRunner/templates/class.tpl

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
<?php declare(strict_types=1);
2+
use PHPUnit\Event;
23
use PHPUnit\Event\Facade;
4+
use PHPUnit\Framework\TestSuite;
35
use PHPUnit\Runner\CodeCoverage;
46
use PHPUnit\Runner\ErrorHandler;
7+
use PHPUnit\Runner\TestSuiteLoader;
58
use PHPUnit\TextUI\Configuration\Registry as ConfigurationRegistry;
69
use PHPUnit\TextUI\Configuration\CodeCoverageFilterRegistry;
710
use PHPUnit\TextUI\Configuration\PhpHandler;
@@ -31,7 +34,7 @@ if ($composerAutoload) {
3134
require $phar;
3235
}
3336

34-
function __phpunit_run_isolated_test()
37+
function __phpunit_run_isolated_class()
3538
{
3639
$dispatcher = Facade::instance()->initForIsolation(
3740
PHPUnit\Event\Telemetry\HRTime::fromSecondsAndNanoseconds(
@@ -68,52 +71,67 @@ function __phpunit_run_isolated_test()
6871

6972
ErrorHandler::instance()->useDeprecationTriggers($deprecationTriggers);
7073

71-
$test = new {className}('{name}');
74+
ini_set('xdebug.scream', '0');
7275

73-
$test->setData('{dataName}', unserialize('{data}'));
74-
$test->setDependencyInput(unserialize('{dependencyInput}'));
75-
$test->setInIsolation(true);
76+
try {
77+
$testClass = (new TestSuiteLoader)->load('{filename}');
78+
} catch (Exception $e) {
79+
print $e->getMessage() . PHP_EOL;
80+
exit(1);
81+
}
7682

77-
ob_end_clean();
83+
$output = '';
84+
$results = [];
7885

79-
$test->run();
86+
$suite = TestSuite::fromClassReflector($testClass);
87+
$suite->setIsInSeparatedProcess(false);
8088

81-
$output = '';
89+
$testSuiteValueObjectForEvents = Event\TestSuite\TestSuiteBuilder::from($suite);
8290

83-
if (!$test->expectsOutput()) {
84-
$output = $test->output();
91+
if (!$suite->invokeMethodsBeforeFirstTest(Facade::emitter(), $testSuiteValueObjectForEvents)) {
92+
return;
8593
}
8694

87-
ini_set('xdebug.scream', '0');
95+
foreach($suite->tests() as $test) {
96+
$test->setRunClassInSeparateProcess(false);
97+
$test->run();
98+
99+
$testOutput = '';
88100
89-
// Not every STDOUT target stream is rewindable
90-
@rewind(STDOUT);
101+
if (!$test->expectsOutput()) {
102+
$testOutput = $test->output();
103+
}
91104

92-
if ($stdout = @stream_get_contents(STDOUT)) {
93-
$output = $stdout . $output;
94-
$streamMetaData = stream_get_meta_data(STDOUT);
105+
// Not every STDOUT target stream is rewindable
106+
@rewind(STDOUT);
95107

96-
if (!empty($streamMetaData['stream_type']) && 'STDIO' === $streamMetaData['stream_type']) {
97-
@ftruncate(STDOUT, 0);
98-
@rewind(STDOUT);
108+
if ($stdout = @stream_get_contents(STDOUT)) {
109+
$testOutput = $stdout . $testOutput;
110+
$streamMetaData = stream_get_meta_data(STDOUT);
111+
112+
if (!empty($streamMetaData['stream_type']) && 'STDIO' === $streamMetaData['stream_type']) {
113+
@ftruncate(STDOUT, 0);
114+
@rewind(STDOUT);
115+
}
99116
}
117+
118+
$results[] = (object)[
119+
'testResult' => $test->result(),
120+
'codeCoverage' => {collectCodeCoverageInformation} ? CodeCoverage::instance()->codeCoverage() : null,
121+
'numAssertions' => $test->numberOfAssertionsPerformed(),
122+
'output' => $testOutput,
123+
'events' => $dispatcher->flush(),
124+
'passedTests' => PassedTests::instance()
125+
];
126+
127+
$output .= $testOutput;
100128
}
101129

130+
$suite->invokeMethodsAfterLastTest(Facade::emitter());
131+
102132
Facade::emitter()->testRunnerFinishedChildProcess($output, '');
103133

104-
file_put_contents(
105-
'{processResultFile}',
106-
serialize(
107-
(object)[
108-
'testResult' => $test->result(),
109-
'codeCoverage' => {collectCodeCoverageInformation} ? CodeCoverage::instance()->codeCoverage() : null,
110-
'numAssertions' => $test->numberOfAssertionsPerformed(),
111-
'output' => $output,
112-
'events' => $dispatcher->flush(),
113-
'passedTests' => PassedTests::instance()
114-
]
115-
)
116-
);
134+
file_put_contents('{processResultFile}', serialize($results));
117135
}
118136

119137
function __phpunit_error_handler($errno, $errstr, $errfile, $errline)
@@ -136,4 +154,4 @@ if ('{bootstrap}' !== '') {
136154
require_once '{bootstrap}';
137155
}
138156

139-
__phpunit_run_isolated_test();
157+
__phpunit_run_isolated_class();

0 commit comments

Comments
 (0)