PK 6ETk README.mdnu ٘ # PHPUnit Wrapper Builds: * 9.0 ![Build Status](https://github.com/Codeception/phpunit-wrapper/workflows/CI/badge.svg?branch=9.0) * 8.0 ![Build Status](https://github.com/Codeception/phpunit-wrapper/workflows/CI/badge.svg?branch=8.0) * 7.1 ![Build Status](https://github.com/Codeception/phpunit-wrapper/workflows/CI/badge.svg?branch=7.1) * 6.5 ![Build Status](https://github.com/Codeception/phpunit-wrapper/workflows/CI/badge.svg?branch=6.5) * 6.0 ![Build Status](https://github.com/Codeception/phpunit-wrapper/workflows/CI/badge.svg?branch=6.0) Codeception heavily relies on PHPUnit for running and managing tests. Not all PHPUnit classes fit the needs of Codeception, that's why they were extended or redefined. Releases follow major PHPUnit versions. PK 6ETߤeX .gitignorenu ٘ .idea composer.lock vendorPK 6ETAxa6 6 RoboFile.phpnu ٘ '*']; file_put_contents(__DIR__ . '/composer.json', json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); } public function prepareDependencies() { $config = json_decode(file_get_contents(__DIR__ . '/composer.json'), true); $config['name'] = 'codeception/phpunit-wrapper-test'; $config['require-dev']['codeception/codeception'] = getenv('CODECEPTION_VERSION'); $config['require-dev']['codeception/module-asserts'] = '^1.0'; $config['require-dev']['codeception/module-cli'] = '^1.0'; $config['require-dev']['codeception/module-db'] = '^1.0'; $config['require-dev']['codeception/module-filesystem'] = '^1.0'; $config['require-dev']['codeception/module-phpbrowser'] = '^1.0.3'; $config['require-dev']['codeception/util-universalframework'] = '*'; $config['replace'] = ['codeception/phpunit-wrapper' => '*']; file_put_contents(__DIR__ . '/composer.json', json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); } public function prepareTests() { $this->_copyDir(__DIR__ . '/vendor/codeception/codeception/tests', __DIR__ . '/tests'); $this->_copy(__DIR__ . '/vendor/codeception/codeception/codeception.yml', __DIR__ .'/codeception.yml'); $this->_symlink(__DIR__ . '/vendor/bin/codecept', __DIR__ . '/codecept'); } public function prepareTestAutoloading() { $config = json_decode(file_get_contents(__DIR__ . '/composer.json'), true); $config['autoload-dev'] = [ 'classmap' => [ 'tests/cli/_steps', 'tests/data/DummyClass.php', 'tests/data/claypit/tests/_data' ] ]; file_put_contents(__DIR__ . '/composer.json', json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); } public function test($params) { return $this->taskExec(__DIR__ . '/vendor/bin/codecept run ' . $params) ->dir(__DIR__ .'/vendor/codeception/codeception') ->run(); } }PK 6ET* src/phpunit7-interfaces.phpnu ٘ false, 'phpunit-xml' => false, 'html' => false, 'tap' => false, 'json' => false, 'report' => false ]; protected $config = []; protected $logDir = null; public function __construct() { $this->config = Configuration::config(); $this->logDir = Configuration::outputDir(); // prepare log dir $this->phpUnitOverriders(); parent::__construct(); } public function phpUnitOverriders() { require_once __DIR__ . DIRECTORY_SEPARATOR . 'Overrides/Filter.php'; } /** * @return null|\PHPUnit\TextUI\ResultPrinter */ public function getPrinter() { return $this->printer; } public function prepareSuite(\PHPUnit\Framework\Test $suite, array &$arguments) { $this->handleConfiguration($arguments); $filterAdded = false; $filterFactory = new \PHPUnit\Runner\Filter\Factory(); if ($arguments['groups']) { $filterAdded = true; $filterFactory->addFilter( new \ReflectionClass('PHPUnit\Runner\Filter\IncludeGroupFilterIterator'), $arguments['groups'] ); } if ($arguments['excludeGroups']) { $filterAdded = true; $filterFactory->addFilter( new \ReflectionClass('PHPUnit\Runner\Filter\ExcludeGroupFilterIterator'), $arguments['excludeGroups'] ); } if ($arguments['filter']) { $filterAdded = true; $filterFactory->addFilter( new \ReflectionClass('Codeception\PHPUnit\FilterTest'), $arguments['filter'] ); } if ($filterAdded) { $suite->injectFilter($filterFactory); } } public function doEnhancedRun( \PHPUnit\Framework\Test $suite, \PHPUnit\Framework\TestResult $result, array $arguments = [] ) { unset($GLOBALS['app']); // hook for not to serialize globals $result->convertErrorsToExceptions(false); if (isset($arguments['report_useless_tests'])) { $result->beStrictAboutTestsThatDoNotTestAnything((bool)$arguments['report_useless_tests']); } if (isset($arguments['disallow_test_output'])) { $result->beStrictAboutOutputDuringTests((bool)$arguments['disallow_test_output']); } if (empty(self::$persistentListeners)) { $this->applyReporters($result, $arguments); } if (class_exists('\Symfony\Bridge\PhpUnit\SymfonyTestsListener')) { $arguments['listeners'] = isset($arguments['listeners']) ? $arguments['listeners'] : []; $listener = new \Symfony\Bridge\PhpUnit\SymfonyTestsListener(); $listener->globalListenerDisabled(); $arguments['listeners'][] = $listener; } $arguments['listeners'][] = $this->printer; // clean up listeners between suites foreach ($arguments['listeners'] as $listener) { $result->addListener($listener); } $suite->run($result); unset($suite); foreach ($arguments['listeners'] as $listener) { $result->removeListener($listener); } return $result; } /** * @param \PHPUnit\Framework\TestResult $result * @param array $arguments * * @return array */ protected function applyReporters(\PHPUnit\Framework\TestResult $result, array $arguments) { foreach ($this->defaultListeners as $listener => $value) { if (!isset($arguments[$listener])) { $arguments[$listener] = $value; } } if ($arguments['report']) { self::$persistentListeners[] = $this->instantiateReporter('report'); } if ($arguments['html']) { codecept_debug('Printing HTML report into ' . $arguments['html']); self::$persistentListeners[] = $this->instantiateReporter( 'html', [$this->absolutePath($arguments['html'])] ); } if ($arguments['xml']) { codecept_debug('Printing JUNIT report into ' . $arguments['xml']); self::$persistentListeners[] = $this->instantiateReporter( 'xml', [$this->absolutePath($arguments['xml']), (bool)$arguments['log_incomplete_skipped']] ); } if ($arguments['phpunit-xml']) { codecept_debug('Printing PHPUNIT report into ' . $arguments['phpunit-xml']); self::$persistentListeners[] = $this->instantiateReporter( 'phpunit-xml', [$this->absolutePath($arguments['phpunit-xml']), (bool)$arguments['log_incomplete_skipped']] ); } if ($arguments['tap']) { codecept_debug('Printing TAP report into ' . $arguments['tap']); self::$persistentListeners[] = $this->instantiateReporter('tap', [$this->absolutePath($arguments['tap'])]); } if ($arguments['json']) { codecept_debug('Printing JSON report into ' . $arguments['json']); self::$persistentListeners[] = $this->instantiateReporter( 'json', [$this->absolutePath($arguments['json'])] ); } foreach (self::$persistentListeners as $listener) { if ($listener instanceof ConsolePrinter) { $this->printer = $listener; continue; } $result->addListener($listener); } } protected function instantiateReporter($name, $args = []) { if (!isset($this->config['reporters'][$name])) { throw new ConfigurationException("Reporter $name not defined"); } return (new \ReflectionClass($this->config['reporters'][$name]))->newInstanceArgs($args); } private function absolutePath($path) { if ((strpos($path, '/') === 0) or (strpos($path, ':') === 1)) { // absolute path return $path; } return $this->logDir . $path; } } PK 6ET97MPv v src/ConsolePrinter.phpnu ٘ testStatus = \PHPUnit\Runner\BaseTestRunner::STATUS_ERROR; $this->failed++; } /** * A failure occurred. * * @param \PHPUnit\Framework\Test $test * @param \PHPUnit\Framework\AssertionFailedError $e * @param float $time */ public function addFailure(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\AssertionFailedError $e, float $time) : void { $this->testStatus = \PHPUnit\Runner\BaseTestRunner::STATUS_FAILURE; $this->failed++; } /** * A warning occurred. * * @param \PHPUnit\Framework\Test $test * @param \PHPUnit\Framework\Warning $e * @param float $time */ public function addWarning(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\Warning $e, float $time): void { $this->testStatus = \PHPUnit\Runner\BaseTestRunner::STATUS_WARNING; $this->warned++; } /** * Incomplete test. * * @param \PHPUnit\Framework\Test $test * @param \Throwable $e * @param float $time */ public function addIncompleteTest(\PHPUnit\Framework\Test $test, \Throwable $e, float $time) : void { $this->testStatus = \PHPUnit\Runner\BaseTestRunner::STATUS_INCOMPLETE; $this->incomplete++; } /** * Risky test. * * @param \PHPUnit\Framework\Test $test * @param \Throwable $e * @param float $time * * @since Method available since Release 4.0.0 */ public function addRiskyTest(\PHPUnit\Framework\Test $test, \Throwable $e, float $time) : void { $this->testStatus = \PHPUnit\Runner\BaseTestRunner::STATUS_RISKY; $this->risky++; } /** * Skipped test. * * @param \PHPUnit\Framework\Test $test * @param \Throwable $e * @param float $time * * @since Method available since Release 3.0.0 */ public function addSkippedTest(\PHPUnit\Framework\Test $test, \Throwable $e, float $time) : void { $this->testStatus = \PHPUnit\Runner\BaseTestRunner::STATUS_SKIPPED; $this->skipped++; } public function startTest(\PHPUnit\Framework\Test $test) : void { $this->testStatus = \PHPUnit\Runner\BaseTestRunner::STATUS_PASSED; } } PK 6ET7> src/Listener.phpnu ٘ dispatcher = $dispatcher; } /** * Risky test. * * @param PHPUnit\Framework\Test $test * @param \Throwable $e * @param float $time * @since Method available since Release 4.0.0 */ public function addRiskyTest(\PHPUnit\Framework\Test $test, \Throwable $e, float $time) : void { $this->unsuccessfulTests[] = spl_object_hash($test); $this->fire('test.useless', new FailEvent($test, $time, $e)); } public function addFailure(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\AssertionFailedError $e, float $time) : void { $this->unsuccessfulTests[] = spl_object_hash($test); $this->fire(Events::TEST_FAIL, new FailEvent($test, $time, $e)); } public function addError(\PHPUnit\Framework\Test $test, \Throwable $e, float $time) : void { $this->unsuccessfulTests[] = spl_object_hash($test); $this->fire(Events::TEST_ERROR, new FailEvent($test, $time, $e)); } // This method was added in PHPUnit 6 public function addWarning(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\Warning $e, float $time) : void { $this->unsuccessfulTests[] = spl_object_hash($test); $this->fire(Events::TEST_WARNING, new FailEvent($test, $time, $e)); } public function addIncompleteTest(\PHPUnit\Framework\Test $test, \Throwable $e, float $time) : void { if (in_array(spl_object_hash($test), $this->skippedTests)) { return; } $this->unsuccessfulTests[] = spl_object_hash($test); $this->fire(Events::TEST_INCOMPLETE, new FailEvent($test, $time, $e)); $this->skippedTests[] = spl_object_hash($test); } public function addSkippedTest(\PHPUnit\Framework\Test $test, \Throwable $e, float $time) : void { if (in_array(spl_object_hash($test), $this->skippedTests)) { return; } $this->unsuccessfulTests[] = spl_object_hash($test); $this->fire(Events::TEST_SKIPPED, new FailEvent($test, $time, $e)); $this->skippedTests[] = spl_object_hash($test); } public function startTestSuite(\PHPUnit\Framework\TestSuite $suite) : void { $this->dispatch($this->dispatcher, 'suite.start', new SuiteEvent($suite)); } public function endTestSuite(\PHPUnit\Framework\TestSuite $suite) : void { $this->dispatch($this->dispatcher, 'suite.end', new SuiteEvent($suite)); } public function startTest(\PHPUnit\Framework\Test $test) : void { $this->dispatch($this->dispatcher, Events::TEST_START, new TestEvent($test)); if (!$test instanceof TestInterface) { return; } if ($test->getMetadata()->isBlocked()) { return; } try { $this->startedTests[] = spl_object_hash($test); $this->fire(Events::TEST_BEFORE, new TestEvent($test)); } catch (\PHPUnit\Framework\IncompleteTestError $e) { $test->getTestResultObject()->addFailure($test, $e, 0); } catch (\PHPUnit\Framework\SkippedTestError $e) { $test->getTestResultObject()->addFailure($test, $e, 0); } catch (\Throwable $e) { $test->getTestResultObject()->addError($test, $e, 0); } } public function endTest(\PHPUnit\Framework\Test $test, float $time) : void { $hash = spl_object_hash($test); if (!in_array($hash, $this->unsuccessfulTests)) { $this->fire(Events::TEST_SUCCESS, new TestEvent($test, $time)); } if (in_array($hash, $this->startedTests)) { $this->fire(Events::TEST_AFTER, new TestEvent($test, $time)); } $this->dispatch($this->dispatcher, Events::TEST_END, new TestEvent($test, $time)); } protected function fire($event, TestEvent $eventType) { $test = $eventType->getTest(); if ($test instanceof TestInterface) { foreach ($test->getMetadata()->getGroups() as $group) { $this->dispatch($this->dispatcher, $event . '.' . $group, $eventType); } } $this->dispatch($this->dispatcher, $event, $eventType); } } PK 6ETzK K src/Constraint/CrawlerNot.phpnu ٘ string) { throw new \PHPUnit\Framework\ExpectationFailedException( "Element '$selector' was found", $comparisonFailure ); } /** @var $nodes DomCrawler * */ $output = "There was '$selector' element"; $output .= $this->uriMessage('on page'); $output .= $this->nodesList($nodes, $this->string); $output .= "\ncontaining '{$this->string}'"; throw new \PHPUnit\Framework\ExpectationFailedException( $output, $comparisonFailure ); } public function toString() : string { if ($this->string) { return 'that contains text "' . $this->string . '"'; } } } PK 6ET G3 3 src/Constraint/JsonContains.phpnu ٘ expected = $expected; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) : bool { $jsonResponseArray = new JsonArray($other); if (!is_array($jsonResponseArray->toArray())) { throw new \PHPUnit\Framework\AssertionFailedError('JSON response is not an array: ' . $other); } if ($jsonResponseArray->containsArray($this->expected)) { return true; } $comparator = new ArrayComparator(); $comparator->setFactory(new Factory); try { $comparator->assertEquals($this->expected, $jsonResponseArray->toArray()); } catch (ComparisonFailure $failure) { throw new \PHPUnit\Framework\ExpectationFailedException( "Response JSON does not contain the provided JSON\n", $failure ); } return false; } /** * Returns a string representation of the constraint. * * @return string */ public function toString() : string { //unused return ''; } protected function failureDescription($other) : string { //unused return ''; } } PK 6ET,1 1 src/Constraint/Crawler.phpnu ٘ count()) { return false; } if ($this->string === '') { return true; } foreach ($nodes as $node) { if (parent::matches($node->nodeValue)) { return true; } } return false; } protected function fail($nodes, $selector, ComparisonFailure $comparisonFailure = null):void { /** @var $nodes DomCrawler * */ if (!$nodes->count()) { throw new ElementNotFound($selector, 'Element located either by name, CSS or XPath'); } $output = "Failed asserting that any element by '$selector'"; $output .= $this->uriMessage('on page'); $output .= " "; if ($nodes->count() < 10) { $output .= $this->nodesList($nodes); } else { $message = new Message("[total %s elements]"); $output .= $message->with($nodes->count())->getMessage(); } $output .= "\ncontains text '{$this->string}'"; throw new \PHPUnit\Framework\ExpectationFailedException( $output, $comparisonFailure ); } protected function failureDescription($other) : string { $desc = ''; foreach ($other as $o) { $desc .= parent::failureDescription($o->textContent); } return $desc; } protected function nodesList(DomCrawler $nodes, $contains = null) { $output = ""; foreach ($nodes as $node) { if ($contains && strpos($node->nodeValue, $contains) === false) { continue; } $output .= "\n+ " . $node->C14N(); } return $output; } } PK 6ET)4 4 src/Constraint/JsonType.phpnu ٘ jsonType = $jsonType; $this->match = $match; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $jsonArray Value or object to evaluate. * * @return bool */ protected function matches($jsonArray) : bool { if ($jsonArray instanceof JsonArray) { $jsonArray = $jsonArray->toArray(); } $matched = (new JsonTypeUtil($jsonArray))->matches($this->jsonType); if ($this->match) { if ($matched !== true) { throw new \PHPUnit\Framework\ExpectationFailedException($matched); } } else { if ($matched === true) { throw new \PHPUnit\Framework\ExpectationFailedException('Unexpectedly response matched: ' . json_encode($jsonArray)); } } return true; } /** * Returns a string representation of the constraint. * * @return string */ public function toString() : string { //unused return ''; } protected function failureDescription($other) : string { //unused return ''; } } PK 6ETۄ src/Constraint/WebDriver.phpnu ٘ string === '') { return true; } foreach ($nodes as $node) { /** @var $node \WebDriverElement * */ if (!$node->isDisplayed()) { continue; } if (parent::matches(htmlspecialchars_decode($node->getText()))) { return true; } } return false; } protected function fail($nodes, $selector, ComparisonFailure $comparisonFailure = null) : void { if (!count($nodes)) { throw new ElementNotFound($selector, 'Element located either by name, CSS or XPath'); } $output = "Failed asserting that any element by " . Locator::humanReadableString($selector); $output .= $this->uriMessage('on page'); if (count($nodes) < 5) { $output .= "\nElements: "; $output .= $this->nodesList($nodes); } else { $message = new Message("[total %s elements]"); $output .= $message->with(count($nodes)); } $output .= "\ncontains text '" . $this->string . "'"; throw new \PHPUnit\Framework\ExpectationFailedException( $output, $comparisonFailure ); } protected function failureDescription($nodes) : string { $desc = ''; foreach ($nodes as $node) { $desc .= parent::failureDescription($node->getText()); } return $desc; } protected function nodesList($nodes, $contains = null) { $output = ""; foreach ($nodes as $node) { if ($contains && strpos($node->getText(), $contains) === false) { continue; } /** @var $node \WebDriverElement * */ $message = new Message("\n+ <%s> %s"); $output .= $message->with($node->getTagName(), $node->getText()); } return $output; } } PK 6ETO? ? src/Constraint/Page.phpnu ٘ string = $this->normalizeText((string)$string); $this->uri = $uri; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) : bool { $other = $this->normalizeText($other); return mb_stripos($other, $this->string, null, 'UTF-8') !== false; } /** * @param $text * @return string */ private function normalizeText($text) { $text = strtr($text, "\r\n", " "); return trim(preg_replace('/\\s{2,}/', ' ', $text)); } /** * Returns a string representation of the constraint. * * @return string */ public function toString() : string { return sprintf( 'contains "%s"', $this->string ); } protected function failureDescription($pageContent) : string { $message = $this->uriMessage('on page'); $message->append("\n--> "); $message->append(mb_substr($pageContent, 0, 300, 'utf-8')); if (mb_strlen($pageContent, 'utf-8') > 300) { $debugMessage = new Message( "[Content too long to display. See complete response in '" . codecept_output_dir() . "' directory]" ); $message->append("\n")->append($debugMessage); } $message->append("\n--> "); return $message->getMessage() . $this->toString(); } protected function uriMessage($onPage = "") { if (!$this->uri) { return new Message(''); } $message = new Message($this->uri); $message->prepend(" $onPage "); return $message; } } PK 6ET N src/Constraint/WebDriverNot.phpnu ٘ string) { throw new \PHPUnit\Framework\ExpectationFailedException( "Element $selector was found", $comparisonFailure ); } $output = "There was $selector element"; $output .= $this->uriMessage("on page"); $output .= $this->nodesList($nodes, $this->string); $output .= "\ncontaining '{$this->string}'"; throw new \PHPUnit\Framework\ExpectationFailedException( $output, $comparisonFailure ); } public function toString() : string { if ($this->string) { return 'that contains text "' . $this->string . '"'; } } } PK 6ET, src/DispatcherWrapper.phpnu ٘ dispatch($eventObject, $eventType); } else { //Symfony 4.2 or lower $dispatcher->dispatch($eventType, $eventObject); } } } PK 6ETRh src/TestCase.phpnu ٘ _setUp(); } } protected function tearDown() { if (method_exists($this, '_tearDown')) { $this->_tearDown(); } } public static function setUpBeforeClass() { if (method_exists(get_called_class(), '_setUpBeforeClass')) { static::_setUpBeforeClass(); } } public static function tearDownAfterClass() { if (method_exists(get_called_class(), '_tearDownAfterClass')) { static::_tearDownAfterClass(); } } } PK 6ET src/Init.phpnu ٘ getFileName(); } else { $reflector = new \ReflectionClass($test); $filename = $reflector->getFileName(); } if ($filename !== $this->currentFile) { if ($this->currentFile !== null) { parent::endTestSuite(new TestSuite()); } //initialize all values to avoid warnings $this->testSuiteAssertions[self::FILE_LEVEL] = 0; $this->testSuiteTests[self::FILE_LEVEL] = 0; $this->testSuiteTimes[self::FILE_LEVEL] = 0; $this->testSuiteErrors[self::FILE_LEVEL] = 0; $this->testSuiteFailures[self::FILE_LEVEL] = 0; $this->testSuiteSkipped[self::FILE_LEVEL] = 0; $this->testSuiteLevel = self::FILE_LEVEL; $this->currentFile = $filename; $this->currentFileSuite = $this->document->createElement('testsuite'); if ($test instanceof Reported) { $reportFields = $test->getReportFields(); $class = isset($reportFields['class']) ? $reportFields['class'] : $reportFields['name']; $this->currentFileSuite->setAttribute('name', $class); } else { $this->currentFileSuite->setAttribute('name', get_class($test)); } $this->currentFileSuite->setAttribute('file', $filename); $this->testSuites[self::SUITE_LEVEL]->appendChild($this->currentFileSuite); $this->testSuites[self::FILE_LEVEL] = $this->currentFileSuite; } if (!$test instanceof Reported) { parent::startTest($test); return; } $this->currentTestCase = $this->document->createElement('testcase'); $isStrict = Configuration::config()['settings']['strict_xml']; foreach ($test->getReportFields() as $attr => $value) { if ($isStrict and !in_array($attr, $this->strictAttributes)) { continue; } $this->currentTestCase->setAttribute($attr, $value); } } public function endTest(\PHPUnit\Framework\Test $test, float $time):void { if ($this->currentTestCase !== null && $test instanceof Test) { $numAssertions = $test->getNumAssertions(); $this->testSuiteAssertions[$this->testSuiteLevel] += $numAssertions; $this->currentTestCase->setAttribute( 'assertions', $numAssertions ); } if ($test instanceof TestCase) { parent::endTest($test, $time); return; } // In PhpUnit 7.4.*, parent::endTest ignores tests that aren't instances of TestCase // so I copied this code from PhpUnit 7.3.5 $this->currentTestCase->setAttribute( 'time', \sprintf('%F', $time) ); $this->testSuites[$this->testSuiteLevel]->appendChild( $this->currentTestCase ); $this->testSuiteTests[$this->testSuiteLevel]++; $this->testSuiteTimes[$this->testSuiteLevel] += $time; $this->currentTestCase = null; } /** * Cleans the mess caused by test suite manipulation in startTest */ public function endTestSuite(TestSuite $suite): void { if ($suite->getName()) { if ($this->currentFile) { //close last file in the test suite parent::endTestSuite(new TestSuite()); $this->currentFile = null; } $this->testSuiteLevel = self::SUITE_LEVEL; } parent::endTestSuite($suite); } } PK 6ET src/Log/JUnit.phpnu [y currentTestCase = $this->document->createElement('testcase'); $isStrict = Configuration::config()['settings']['strict_xml']; foreach ($test->getReportFields() as $attr => $value) { if ($isStrict and !in_array($attr, $this->strictAttributes)) { continue; } $this->currentTestCase->setAttribute($attr, $value); } } public function endTest(\PHPUnit\Framework\Test $test, float $time):void { if ($this->currentTestCase !== null and $test instanceof Test) { $numAssertions = $test->getNumAssertions(); $this->testSuiteAssertions[$this->testSuiteLevel] += $numAssertions; $this->currentTestCase->setAttribute( 'assertions', $numAssertions ); } if ($test instanceof TestCase) { parent::endTest($test, $time); return; } // since PhpUnit 7.4.0, parent::endTest ignores tests that aren't instances of TestCase // so I copied this code from PhpUnit 7.3.5 $this->currentTestCase->setAttribute( 'time', \sprintf('%F', $time) ); $this->testSuites[$this->testSuiteLevel]->appendChild( $this->currentTestCase ); $this->testSuiteTests[$this->testSuiteLevel]++; $this->testSuiteTimes[$this->testSuiteLevel] += $time; $this->currentTestCase = null; } } PK 6ETVaY src/shim.phpnu ٘ getPrevious() ? $e->getPrevious()->getTrace() : $e->getTrace(); if ($e instanceof \PHPUnit\Framework\ExceptionWrapper) { $trace = $e->getSerializableTrace(); } $eFile = $e->getFile(); $eLine = $e->getLine(); if (!self::frameExists($trace, $eFile, $eLine)) { array_unshift( $trace, ['file' => $eFile, 'line' => $eLine] ); } foreach ($trace as $step) { if (self::classIsFiltered($step) and $filter) { continue; } if (self::fileIsFiltered($step) and $filter) { continue; } if (!$asString) { $stackTrace[] = $step; continue; } if (!isset($step['file'])) { continue; } $stackTrace .= $step['file'] . ':' . $step['line'] . "\n"; } return $stackTrace; } protected static function classIsFiltered($step) { if (!isset($step['class'])) { return false; } $className = $step['class']; foreach (self::$filteredClassesPattern as $filteredClassName) { if (strpos($className, $filteredClassName) === 0) { return true; } } return false; } protected static function fileIsFiltered($step) { if (!isset($step['file'])) { return false; } if (strpos($step['file'], 'codecept.phar/') !== false) { return true; } if (strpos($step['file'], 'vendor' . DIRECTORY_SEPARATOR . 'phpunit') !== false) { return true; } if (strpos($step['file'], 'vendor' . DIRECTORY_SEPARATOR . 'codeception') !== false) { return true; } $modulePath = 'src' . DIRECTORY_SEPARATOR . 'Codeception' . DIRECTORY_SEPARATOR . 'Module'; if (strpos($step['file'], $modulePath) !== false) { return false; // don`t filter modules } if (strpos($step['file'], 'src' . DIRECTORY_SEPARATOR . 'Codeception' . DIRECTORY_SEPARATOR) !== false) { return true; } return false; } /** * @param array $trace * @param string $file * @param int $line * * @return bool */ private static function frameExists(array $trace, $file, $line) { foreach ($trace as $frame) { if (isset($frame['file']) && $frame['file'] == $file && isset($frame['line']) && $frame['line'] == $line) { return true; } } return false; } } PK 6ET)=G G src/ResultPrinter/Report.phpnu ٘ testStatus == \PHPUnit\Runner\BaseTestRunner::STATUS_PASSED); if ($success) { $this->successful++; } if ($this->testStatus == \PHPUnit\Runner\BaseTestRunner::STATUS_FAILURE) { $status = "\033[41;37mFAIL\033[0m"; } elseif ($this->testStatus == \PHPUnit\Runner\BaseTestRunner::STATUS_SKIPPED) { $status = 'Skipped'; } elseif ($this->testStatus == \PHPUnit\Runner\BaseTestRunner::STATUS_INCOMPLETE) { $status = 'Incomplete'; } elseif ($this->testStatus == \PHPUnit\Runner\BaseTestRunner::STATUS_RISKY) { $status = 'Useless'; } elseif ($this->testStatus == \PHPUnit\Runner\BaseTestRunner::STATUS_ERROR) { $status = 'ERROR'; } else { $status = 'Ok'; } if (strlen($name) > 75) { $name = substr($name, 0, 70); } $line = $name . str_repeat('.', 75 - strlen($name)); $line .= $status; $this->write($line . "\n"); } protected function endRun() : void { } public function printResult(\PHPUnit\Framework\TestResult $result) { $this->write("\nCodeception Results\n"); $this->write(sprintf( "Successful: %d. Failed: %d. Incomplete: %d. Skipped: %d. Useless: %d", $this->successful, $this->failed, $this->incomplete, $this->skipped, $this->risky ) . "\n"); } public function write(string $buffer) : void { parent::write($buffer); } } PK 6ETDa% % src/ResultPrinter/HTML.phpnu ٘ templatePath = sprintf( '%s%stemplate%s', __DIR__, DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR ); } /** * Handler for 'start class' event. * * @param string $name */ protected function startClass(string $name):void { } public function endTest(\PHPUnit\Framework\Test $test, float $time) : void { $steps = []; $success = ($this->testStatus == \PHPUnit\Runner\BaseTestRunner::STATUS_PASSED); if ($success) { $this->successful++; } if ($test instanceof ScenarioDriven) { $steps = $test->getScenario()->getSteps(); } $this->timeTaken += $time; switch ($this->testStatus) { case \PHPUnit\Runner\BaseTestRunner::STATUS_FAILURE: $scenarioStatus = 'scenarioFailed'; break; case \PHPUnit\Runner\BaseTestRunner::STATUS_SKIPPED: $scenarioStatus = 'scenarioSkipped'; break; case \PHPUnit\Runner\BaseTestRunner::STATUS_INCOMPLETE: $scenarioStatus = 'scenarioIncomplete'; break; case \PHPUnit\Runner\BaseTestRunner::STATUS_ERROR: $scenarioStatus = 'scenarioFailed'; break; default: $scenarioStatus = 'scenarioSuccess'; } $stepsBuffer = ''; $subStepsRendered = []; foreach ($steps as $step) { if ($step->getMetaStep()) { $key = $step->getMetaStep()->getLine() . $step->getMetaStep()->getAction(); $subStepsRendered[$key][] = $this->renderStep($step); } } foreach ($steps as $step) { if ($step->getMetaStep()) { $key = $step->getMetaStep()->getLine() . $step->getMetaStep()->getAction(); if (! empty($subStepsRendered[$key])) { $subStepsBuffer = implode('', $subStepsRendered[$key]); unset($subStepsRendered[$key]); $stepsBuffer .= $this->renderSubsteps($step->getMetaStep(), $subStepsBuffer); } } else { $stepsBuffer .= $this->renderStep($step); } } $scenarioTemplate = new \Text_Template( $this->templatePath . 'scenario.html' ); $failures = ''; $name = Descriptor::getTestSignatureUnique($test); if (isset($this->failures[$name])) { $failTemplate = new \Text_Template( $this->templatePath . 'fail.html' ); foreach ($this->failures[$name] as $failure) { $failTemplate->setVar(['fail' => nl2br($failure)]); $failures .= $failTemplate->render() . PHP_EOL; } $this->failures[$name] = []; } $png = ''; $html = ''; if ($test instanceof TestInterface) { $reports = $test->getMetadata()->getReports(); if (isset($reports['png'])) { $localPath = PathResolver::getRelativeDir($reports['png'], codecept_output_dir()); $png = "
Summary
|
{toggle} {name} {time}s
+ {metaStep}