/** * @param \PHPUnit_Framework_TestCase $testCase */ private function setUpContext(\PHPUnit_Framework_TestCase $testCase) { $annotations = $testCase->getAnnotations(); if (isset($annotations['method'][$this->annotationName])) { $this->callMethods($testCase, $annotations['method'][$this->annotationName]); } }
/** * Register fixture components * * @param \PHPUnit_Framework_TestCase $test */ private function registerComponents(\PHPUnit_Framework_TestCase $test) { $annotations = $test->getAnnotations(); $componentAnnotations = []; if (isset($annotations['class'][self::ANNOTATION_NAME])) { $componentAnnotations = array_merge($componentAnnotations, $annotations['class'][self::ANNOTATION_NAME]); } if (isset($annotations['method'][self::ANNOTATION_NAME])) { $componentAnnotations = array_merge($componentAnnotations, $annotations['method'][self::ANNOTATION_NAME]); } if (empty($componentAnnotations)) { return; } $componentAnnotations = array_unique($componentAnnotations); $reflection = new \ReflectionClass(self::REGISTRAR_CLASS); $paths = $reflection->getProperty(self::PATHS_FIELD); $paths->setAccessible(true); $this->origComponents = $paths->getValue(); $paths->setAccessible(false); foreach ($componentAnnotations as $fixturePath) { $fixturesDir = $this->fixtureBaseDir . '/' . $fixturePath; if (!file_exists($fixturesDir)) { throw new \InvalidArgumentException(self::ANNOTATION_NAME . " fixture '{$fixturePath}' does not exist"); } $iterator = new RegexIterator(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($fixturesDir, \FilesystemIterator::SKIP_DOTS)), '/^.+\\/registration\\.php$/'); /** * @var \SplFileInfo $registrationFile */ foreach ($iterator as $registrationFile) { require $registrationFile->getRealPath(); } } }
/** * Start test case event observer * * @param \PHPUnit_Framework_TestCase $test */ public function startTest(\PHPUnit_Framework_TestCase $test) { $area = $this->_getTestAppArea($test->getAnnotations()); if ($this->_application->getArea() !== $area) { $this->_application->reinitialize(); if ($this->_application->getArea() !== $area) { $this->_application->loadArea($area); } } }
/** * Handler for 'startTest' event * * @param \PHPUnit_Framework_TestCase $test * @return void */ public function startTest(\PHPUnit_Framework_TestCase $test) { $source = $test->getAnnotations(); if (isset($source['method']['magentoCache'])) { $annotations = $source['method']['magentoCache']; } elseif (isset($source['class']['magentoCache'])) { $annotations = $source['class']['magentoCache']; } else { return; } $this->setValues($this->parseValues($annotations, $test), $test); }
/** * Assign required config values and save original ones * * @param \PHPUnit_Framework_TestCase $test */ protected function _assignConfigData(\PHPUnit_Framework_TestCase $test) { $annotations = $test->getAnnotations(); if (!isset($annotations['method']['magentoAdminConfigFixture'])) { return; } foreach ($annotations['method']['magentoAdminConfigFixture'] as $configPathAndValue) { list($configPath, $requiredValue) = preg_split('/\\s+/', $configPathAndValue, 2); $originalValue = $this->_getConfigValue($configPath); $this->_configValues[$configPath] = $originalValue; $this->_setConfigValue($configPath, $requiredValue); } }
/** * Handler for 'endTest' event * * @param \PHPUnit_Framework_TestCase $test * @throws \Magento\Framework\Exception */ public function endTest(\PHPUnit_Framework_TestCase $test) { $this->_hasNonIsolatedTests = true; /* Determine an isolation from doc comment */ $annotations = $test->getAnnotations(); if (isset($annotations['method']['magentoAppIsolation'])) { $isolation = $annotations['method']['magentoAppIsolation']; if ($isolation !== array('enabled') && $isolation !== array('disabled')) { throw new \Magento\Framework\Exception('Invalid "@magentoAppIsolation" annotation, can be "enabled" or "disabled" only.'); } $isIsolationEnabled = $isolation === array('enabled'); } else { /* Controller tests should be isolated by default */ $isIsolationEnabled = $test instanceof \Magento\TestFramework\TestCase\AbstractController; } if ($isIsolationEnabled) { $this->_isolateApp(); } }
/** * Retrieve fixtures from annotation * * @param string $scope 'class' or 'method' * @param \PHPUnit_Framework_TestCase $test * @return array * @throws \Magento\Framework\Exception */ protected function _getFixtures($scope, \PHPUnit_Framework_TestCase $test) { $annotations = $test->getAnnotations(); $result = []; if (!empty($annotations[$scope]['magentoApiDataFixture'])) { foreach ($annotations[$scope]['magentoApiDataFixture'] as $fixture) { if (strpos($fixture, '\\') !== false) { // usage of a single directory separator symbol streamlines search across the source code throw new \Magento\Framework\Exception('Directory separator "\\" is prohibited in fixture declaration.'); } $fixtureMethod = [get_class($test), $fixture]; if (is_callable($fixtureMethod)) { $result[] = $fixtureMethod; } else { $result[] = $this->_fixtureBaseDir . '/' . $fixture; } } } return $result; }
/** * Handler for 'endTest' event * * @param PHPUnit_Framework_TestCase $test * @throws Magento_Exception */ public function endTest(PHPUnit_Framework_TestCase $test) { $this->_hasNonIsolatedTests = true; /* Determine an isolation from doc comment */ $annotations = $test->getAnnotations(); if (isset($annotations['method']['magentoAppIsolation'])) { $isolation = $annotations['method']['magentoAppIsolation']; if ($isolation !== array('enabled') && $isolation !== array('disabled')) { throw new Magento_Exception('Invalid "@magentoAppIsolation" annotation, can be "enabled" or "disabled" only.'); } $isIsolationEnabled = $isolation === array('enabled'); } else { /* Controller tests should be isolated by default */ $isIsolationEnabled = $test instanceof Magento_Test_TestCase_ControllerAbstract; } if ($isIsolationEnabled) { $this->_isolateApp(); } /* Forced garbage collection to avoid process non-zero exit code (exec returned: 139) caused by PHP bug */ gc_collect_cycles(); }
/** * Assign required config values and save original ones * * @param \PHPUnit_Framework_TestCase $test */ protected function _assignConfigData(\PHPUnit_Framework_TestCase $test) { $annotations = $test->getAnnotations(); if (!isset($annotations['method']['magentoConfigFixture'])) { return; } foreach ($annotations['method']['magentoConfigFixture'] as $configPathAndValue) { if (preg_match('/^.+?(?=_store\\s)/', $configPathAndValue, $matches)) { /* Store-scoped config value */ $storeCode = $matches[0] != 'current' ? $matches[0] : null; $parts = preg_split('/\\s+/', $configPathAndValue, 3); list(, $configPath, $requiredValue) = $parts + ['', '', '']; $originalValue = $this->_getConfigValue($configPath, $storeCode); $this->_storeConfigValues[$storeCode][$configPath] = $originalValue; $this->_setConfigValue($configPath, $requiredValue, $storeCode); } else { /* Global config value */ list($configPath, $requiredValue) = preg_split('/\\s+/', $configPathAndValue, 2); $originalValue = $this->_getConfigValue($configPath); $this->_globalConfigValues[$configPath] = $originalValue; $this->_setConfigValue($configPath, $requiredValue); } } }
/** * Get slow test threshold for given test. A TestCase can override the * suite-wide slow threshold by using the annotation @slowThreshold with * the threshold value in milliseconds. * * The following test will only be considered slow when its execution time * reaches 5000ms (5 seconds): * * <code> * @slowThreshold 5000 * public function testLongRunningProcess() {} * </code> * * @param PHPUnit_Framework_TestCase $test * @return int */ protected function getSlowThreshold(PHPUnit_Framework_TestCase $test) { $ann = $test->getAnnotations(); return isset($ann['method']['slowThreshold'][0]) ? $ann['method']['slowThreshold'][0] : $this->slowThreshold; }
/** * Check an individual test run for valid @covers annotation. * * This method is called from $this::endTest(). * * @param \PHPUnit_Framework_TestCase $test * The test to examine. */ public function checkValidCoversForTest(\PHPUnit_Framework_TestCase $test) { // If we're generating a coverage report already, don't do anything here. if ($test->getTestResultObject() && $test->getTestResultObject()->getCollectCodeCoverageInformation()) { return; } // Gather our annotations. $annotations = $test->getAnnotations(); // Glean the @coversDefaultClass annotation. $default_class = ''; $valid_default_class = FALSE; if (isset($annotations['class']['coversDefaultClass'])) { if (count($annotations['class']['coversDefaultClass']) > 1) { $this->fail($test, '@coversDefaultClass has too many values'); } // Grab the first one. $default_class = reset($annotations['class']['coversDefaultClass']); // Check whether the default class exists. $valid_default_class = $this->classExists($default_class); if (!$valid_default_class) { $this->fail($test, "@coversDefaultClass does not exist '{$default_class}'"); } } // Glean @covers annotation. if (isset($annotations['method']['covers'])) { // Drupal allows multiple @covers per test method, so we have to check // them all. foreach ($annotations['method']['covers'] as $covers) { // Ensure the annotation isn't empty. if (trim($covers) === '') { $this->fail($test, '@covers should not be empty'); // If @covers is empty, we can't proceed. return; } // Ensure we don't have (). if (strpos($covers, '()') !== FALSE) { $this->fail($test, "@covers invalid syntax: Do not use '()'"); } // Glean the class and method from @covers. $class = $covers; $method = ''; if (strpos($covers, '::') !== FALSE) { list($class, $method) = explode('::', $covers); } // Check for the existence of the class if it's specified by @covers. if (!empty($class)) { // If the class doesn't exist we have either a bad classname or // are missing the :: for a method. Either way we can't proceed. if (!$this->classExists($class)) { if (empty($method)) { $this->fail($test, "@covers invalid syntax: Needs '::' or class does not exist in {$covers}"); return; } else { $this->fail($test, '@covers class does not exist ' . $class); return; } } } else { // The class isn't specified and we have the ::, so therefore this // test either covers a function, or relies on a default class. if (empty($default_class)) { // If there's no default class, then we need to check if the global // function exists. Since this listener should always be listening // for endTest(), the function should have already been loaded from // its .module or .inc file. if (!function_exists($method)) { $this->fail($test, '@covers global method does not exist ' . $method); } } else { // We have a default class and this annotation doesn't act like a // global function, so we should use the default class if it's // valid. if ($valid_default_class) { $class = $default_class; } } } // Finally, after all that, let's see if the method exists. if (!empty($class) && !empty($method)) { $ref_class = new \ReflectionClass($class); if (!$ref_class->hasMethod($method)) { $this->fail($test, '@covers method does not exist ' . $class . '::' . $method); } } } } }
/** * @param \PHPUnit_Framework_TestCase $test * @return array */ private function getAnnotations(\PHPUnit_Framework_TestCase $test) { $annotations = $test->getAnnotations(); return array_replace($annotations['class'], $annotations['method']); }
/** * Retrieve database isolation annotation value for the current scope. * Possible results: * NULL - annotation is not defined * TRUE - annotation is defined as 'enabled' * FALSE - annotation is defined as 'disabled' * * @param string $scope 'class' or 'method' * @param PHPUnit_Framework_TestCase $test * @return bool|null Returns NULL, if isolation is not defined for the current scope * @throws Magento_Exception */ protected function _getIsolation($scope, PHPUnit_Framework_TestCase $test) { $annotations = $test->getAnnotations(); if (isset($annotations[$scope]['magentoDbIsolation'])) { $isolation = $annotations[$scope]['magentoDbIsolation']; if ($isolation !== array('enabled') && $isolation !== array('disabled')) { throw new Magento_Exception('Invalid "@magentoDbIsolation" annotation, can be "enabled" or "disabled" only.'); } return $isolation === array('enabled'); } return null; }
/** * Determines, if there is a data provider defined for the current test case. * * @param \PHPUnit_Framework_Test $test * * @return boolean */ protected function hasDataprovider(\PHPUnit_Framework_TestCase $test) { $annotations = $test->getAnnotations(); return !empty($annotations['method']['dataProvider']); }