exampleDir = rtrim($exampleDir, '/\\') . DIRECTORY_SEPARATOR; } /** * @param TestExecutor $testExecutor * @return $this */ public function withTestExecutor(TestExecutor $testExecutor) { $this->testExecutor = $testExecutor; return $this; } /** * @param bool $preserve * @return $this */ public function preserveOutputFiles($preserve = true) { $this->preserveFiles = (bool)$preserve; return $this; } /** * @param array $excluded * @return $this */ public function excludeTests(array $excluded) { $this->excludedFiles = $excluded; return $this; } /** * @param array $files * @return $this */ public function only(array $files) { $this->onlyFiles = empty($files) ? null : $files; return $this; } /** * @param array $groups * @return $this */ public function filterByGroup(array $groups) { $this->groups = (empty($groups)) ? null : $groups; return $this; } /** * @param string[] $conditions * @return $this */ public function stopOn(array $conditions) { $this->stopOn = $conditions; return $this; } /** * @param string $condition * @return bool */ private function shouldStopOn($condition) { if (in_array('defect', $this->stopOn, true)) { return true; } if (in_array($condition, $this->stopOn, true)) { return true; } return false; } /** * @return string[] */ public function getTestFiles() { chdir($this->exampleDir); $exampleFiles = array_flip(glob('example*.php')); $exampleFiles = array_flip($exampleFiles); $exampleBarcodeFiles = glob('barcodes/example*.php'); $files = array(); foreach ($exampleFiles as $exampleFile) { $files[$exampleFile] = 'PDF'; } foreach ($exampleBarcodeFiles as $exampleFile) { $type = preg_replace('/^.+(html|png|svgi?)$/', '\1', basename($exampleFile, '.php')); if ('svgi' === $type) { $files[$exampleFile] = 'SVG'; } else { $files[$exampleFile] = strtoupper($type); } } if (null !== $this->onlyFiles) { foreach ($files as $file => $type) { if (!in_array($file, $this->onlyFiles, true)) { unset($files[$file]); } } } if (null !== $this->groups) { $regExp = '/\*\s*@group\s+(' . implode('|', $this->groups) . ')\s/'; foreach ($files as $file => $type) { $source = file_get_contents($file); if (!preg_match($regExp, $source)) { unset($files[$file]); } } } return $files; } /** * @param string $outputDir Path to output folder * @return bool TRUE if all tests passed, FALSE otherwise */ public function runTests($outputDir) { if (!isset($this->testExecutor)) { throw new \RuntimeException("Test executor is missing. Did you forget to call withTestExecutor()?"); } $this->runTime = null; $startTime = time(); $outputFolder = rtrim($outputDir, '/\\') . DIRECTORY_SEPARATOR; chdir($this->exampleDir); $this->failed = array(); $this->ignored = array(); $this->generatedFiles = array(); $this->count = 0; foreach ($this->getTestFiles() as $file => $type) { ++$this->count; echo 'File: ' . $file . PHP_EOL; if (in_array($file, $this->excludedFiles, true)) { echo ' Run: SKIPPED' . PHP_EOL; $this->ignored[] = $file; continue; } if (!$this->testExecutor->assertIsPhpValidFile($this->exampleDir . $file)) { echo ' Lint: FAILED' . PHP_EOL; $this->failed[] = $file; if ($this->shouldStopOn('failure')) { break; } continue; } echo ' Lint: PASSED' . PHP_EOL; if (!$this->preserveFiles) { $outputFile = $outputFolder . 'output.pdf'; $outputFileError = $outputFolder . 'errors.txt'; } else { $baseName = $outputFolder . basename($file, '.php'); $outputFile = $baseName . '.output.' . strtolower($type); $outputFileError = $baseName . '.errors.txt'; } $this->generatedFiles[$outputFile] = $file; $this->generatedFiles[$outputFileError] = $file; $isSuccess = $this->testExecutor->execute( $this->exampleDir . $file, $outputFile, $outputFileError ); if (!$isSuccess) { echo ' Run: FAILED' . PHP_EOL; $this->failed[] = $file; $this->testExecutor->assertIsFileType( $outputFile, $outputFileError, $type, $this->preserveFiles ); if ($this->shouldStopOn('failure')) { break; } } else { echo ' Run: PASSED' . PHP_EOL; $isFileType = $this->testExecutor->assertIsFileType( $outputFile, $outputFileError, $type, $this->preserveFiles ); if (!$isFileType) { $this->failed[] = $file; if ($this->shouldStopOn('failure')) { break; } } } } $this->runTime = time() - $startTime; $this->cleanUp(); return empty($this->failed); } /** * @return string[] */ public function getFailedTests() { return $this->failed; } /** * @return string[] */ public function getGeneratedFiles() { return array_keys($this->generatedFiles); } /** * @return string[] */ public function getSkippedTests() { return $this->ignored; } /** * @return int */ public function getTotalTestCount() { return $this->count; } /** * Get last run time in seconds * @return int|null */ public function getRunTime() { return $this->runTime; } /** * @return void */ private function cleanUp() { if ($this->preserveFiles) { echo 'Generated files remaining on disk: ' . count($this->generatedFiles) . PHP_EOL; return; } foreach ($this->getGeneratedFiles() as $generatedFile) { if (file_exists($generatedFile)) { unlink($generatedFile); } } } /** * Outputs a summary of the last test suite run * @return $this */ public function printSummary() { $failed = $this->getFailedTests(); $ignored = $this->getSkippedTests(); $failedCount = count($failed); $ignoredCount = count($ignored); if ($failedCount === 0) { echo 'Test suite: PASSED' . PHP_EOL; } else { echo 'Test suite: FAILED' . PHP_EOL; } echo ' Runtime: ' . $this->getRunTime() . 's' . PHP_EOL; echo ' Total tests: ' . $this->getTotalTestCount() . PHP_EOL; if ($ignoredCount > 0) { echo ' SKipped tests: ' . $ignoredCount . PHP_EOL; foreach ($ignored as $ignoredFile) { echo ' ' . $ignoredFile . PHP_EOL; } } if ($failedCount > 0) { echo ' Failed tests: ' . $failedCount . PHP_EOL; foreach ($failed as $failedFile) { echo ' ' . $failedFile . PHP_EOL; } } return $this; } }