审查视图

simplewind/vendor/mindplay/annotations/test/lib/xTestRunner.php 3.6 KB
1  
潘浩文 authored
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
<?php
namespace mindplay\test\lib;


use mindplay\test\lib\ResultPrinter\CliResultPrinter;
use mindplay\test\lib\ResultPrinter\ResultPrinter;
use mindplay\test\lib\ResultPrinter\WebResultPrinter;

/**
 * This class implements a very simple test suite runner and code
 * coverage benchmarking (where supported by the xdebug extension).
 */
class xTestRunner
{
    protected $rootPath;

    /**
     * Code coverage information tracker.
     *
     * @var \PHP_CodeCoverage
     */
    protected $coverage;

    /**
     * Result printer.
     *
     * @var ResultPrinter
     */
    protected $resultPrinter;

    /**
     * Creates result printer based on environment.
     *
     * @return ResultPrinter
     */
    public static function createResultPrinter()
    {
        if (PHP_SAPI == 'cli') {
            return new CliResultPrinter(new Colors());
        }

        return new WebResultPrinter();
    }

    /**
     * Creates test runner instance.
     *
     * @param string        $rootPath      The absolute path to the root folder of the test suite.
     * @param ResultPrinter $resultPrinter Result printer.
     * @throws \Exception
     */
    public function __construct($rootPath, ResultPrinter $resultPrinter)
    {
        if (!is_dir($rootPath)) {
            throw new \Exception("{$rootPath} is not a directory");
        }

        $this->rootPath = $rootPath;
        $this->resultPrinter = $resultPrinter;

        try {
            $this->coverage = new \PHP_CodeCoverage();
            $this->coverage->filter()->addDirectoryToWhitelist($rootPath);
        } catch (\PHP_CodeCoverage_Exception $e) {
            // can't collect coverage
        }
    }

    /**
     * Returns library root path.
     *
     * @return string
     */
    public function getRootPath()
    {
        return $this->rootPath;
    }

    /**
     * Starts coverage information collection for a test.
     *
     * @param string $testName Test name.
     * @return void
     */
    public function startCoverageCollector($testName)
    {
        if (isset($this->coverage)) {
            $this->coverage->start($testName);
        }
    }

    /**
     * Stops coverage information collection.
     *
     * @return void
     */
    public function stopCoverageCollector()
    {
        if (isset($this->coverage)) {
            $this->coverage->stop();
        }
    }

    /**
     * Runs a suite of unit tests
     *
     * @param string $directory Directory with tests.
     * @param string $suffix    Test file suffix.
     * @throws \Exception When invalid test found.
     * @return boolean
     */
    public function run($directory, $suffix)
    {
        $this->resultPrinter->suiteHeader($this, $directory . '/*' . $suffix);

        $passed = true;
        $facade = new \File_Iterator_Facade;

        $old_handler = set_error_handler(array($this, 'handlePHPErrors'));

        foreach ($facade->getFilesAsArray($directory, $suffix) as $path) {
            $test = require($path);

            if (!$test instanceof xTest) {
                throw new \Exception("'{$path}' is not a valid unit test");
            }

            $test->setResultPrinter($this->resultPrinter);
            $passed = $passed && $test->run($this);
        }

        if ($old_handler) {
            set_error_handler($old_handler);
        } else {
            restore_error_handler();
        }

        $this->resultPrinter->createCodeCoverageReport($this->coverage);
        $this->resultPrinter->suiteFooter($this);

        return $passed;
    }

    public function handlePHPErrors($errno, $errstr)
    {
        throw new xTestException($errstr, xTestException::PHP_ERROR);
    }
}