Completed
Push — master ( d43f38...58ec5f )
by Jakub
01:47
created

Tester::setUseColors()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 2
c 0
b 0
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace MyTester;
6
7
use Ayesh\PHP_Timer\Timer;
8
use Jean85\PrettyVersions;
9
use MyTester\Bridges\NetteRobotLoader\TestSuitesFinder;
10
use Nette\CommandLine\Console;
11
use Nette\Utils\Finder;
12
13
/**
14
 * Automated tests runner
15
 *
16
 * @author Jakub Konečný
17
 * @property-read string[] $suites
18
 * @property bool $useColors
19
 * @method void onExecute()
20
 */
21
final class Tester
22
{
23
    use \Nette\SmartObject;
24
25
    private const PACKAGE_NAME = "konecnyjakub/mytester";
26
    private const TIMER_NAME = "My Tester";
27
28
    /** @var string[] */
29
    private array $suites = [];
30
    /** @var callable[] */
31
    public array $onExecute = [];
32
    public ITestSuiteFactory $testSuiteFactory;
33
    public ITestSuitesFinder $testSuitesFinder;
34
    private Console $console;
35
    private string $folder;
36
    private bool $useColors = false;
37
    /** @var SkippedTest[] */
38
    private array $skipped = [];
39
    private string $results = "";
40
41 1
    public function __construct(
42
        string $folder,
43
        ITestSuitesFinder $testSuitesFinder = null,
44
        ITestSuiteFactory $testSuiteFactory = null
45
    ) {
46 1
        $this->onExecute[] = [$this, "setup"];
47 1
        $this->onExecute[] = [$this, "printInfo"];
48 1
        if ($testSuitesFinder === null) {
49 1
            $testSuitesFinder = new ChainTestSuitesFinder();
50 1
            $testSuitesFinder->registerFinder(new ComposerTestSuitesFinder());
51 1
            $testSuitesFinder->registerFinder(new TestSuitesFinder());
52
        }
53 1
        $this->testSuitesFinder = $testSuitesFinder;
54 1
        $this->testSuiteFactory = $testSuiteFactory ?? new TestSuiteFactory();
55 1
        $this->folder = $folder;
56 1
        $this->console = new Console();
57 1
    }
58
59
    /**
60
     * @return string[]
61
     */
62 1
    protected function getSuites(): array
63
    {
64 1
        if (count($this->suites) === 0) {
65 1
            $this->suites = $this->testSuitesFinder->getSuites($this->folder);
66
        }
67 1
        return $this->suites;
68
    }
69
70
    protected function isUseColors(): bool
71
    {
72
        return $this->useColors;
73
    }
74
75 1
    protected function setUseColors(bool $useColors): void
76
    {
77 1
        $this->useColors = $useColors;
78 1
        $this->console->useColors($useColors);
79 1
    }
80
81
    /**
82
     * Execute all tests
83
     */
84 1
    public function execute(): void
85
    {
86 1
        $this->onExecute();
87 1
        $failed = false;
88 1
        foreach ($this->getSuites() as $suite) {
89 1
            $suite = $this->testSuiteFactory->create($suite);
90 1
            if (!$suite->run()) {
91
                $failed = true;
92
            }
93 1
            $this->saveResults($suite);
94
        }
95 1
        $this->printResults();
96 1
        exit((int) $failed);
97
    }
98
99 1
    private function setup(): void
100
    {
101 1
        Timer::start(static::TIMER_NAME);
102 1
    }
103
104
    /**
105
     * Print version of My Tester and PHP
106
     */
107 1
    private function printInfo(): void
108
    {
109 1
        $version = PrettyVersions::getVersion(static::PACKAGE_NAME);
110 1
        echo $this->console->color("silver", "My Tester $version\n");
111 1
        echo "\n";
112 1
        echo $this->console->color("silver", "PHP " . PHP_VERSION . "(" . PHP_SAPI . ")\n");
113 1
        echo "\n";
114 1
    }
115
116 1
    private function printResults(): void
117
    {
118 1
        $results = $this->results;
119 1
        $rf = TestCase::RESULT_FAILED;
120 1
        $rs = TestCase::RESULT_SKIPPED;
121 1
        $results = str_replace($rf, $this->console->color("red", $rf), $results);
122 1
        $results = str_replace($rs, $this->console->color("yellow", $rs), $results);
123 1
        echo $results . "\n";
124 1
        $results = $this->results;
125 1
        $this->printSkipped();
126 1
        $failed = str_contains($results, TestCase::RESULT_FAILED);
127 1
        if (!$failed) {
128 1
            echo "\n";
129 1
            $resultsLine = "OK";
130
        } else {
131
            $this->printFailed();
132
            echo "\n";
133
            $resultsLine = "Failed";
134
        }
135 1
        $resultsLine .= " (" . strlen($results) . " tests";
136 1
        if ($failed) {
137
            $resultsLine .= ", " . substr_count($results, TestCase::RESULT_FAILED) . " failed";
138
        }
139 1
        if (str_contains($results, TestCase::RESULT_SKIPPED)) {
140 1
            $resultsLine .= ", " . substr_count($results, TestCase::RESULT_SKIPPED) . " skipped";
141
        }
142 1
        Timer::stop(static::TIMER_NAME);
143 1
        $time = Timer::read(static::TIMER_NAME, Timer::FORMAT_HUMAN);
144 1
        $resultsLine .= ", $time)";
145 1
        $resultsLine = $this->console->color((!$failed) ? "green" : "red", $resultsLine);
146 1
        echo $resultsLine . "\n";
147 1
    }
148
149
    /**
150
     * Print info about skipped tests
151
     */
152 1
    private function printSkipped(): void
153
    {
154 1
        foreach ($this->skipped as $skipped) {
155 1
            $reason = "";
156 1
            if ($skipped->reason) {
157 1
                $reason = ": {$skipped->reason}";
158
            }
159 1
            echo "Skipped $skipped->name$reason\n";
160
        }
161 1
    }
162
163
    /**
164
     * Print info about failed tests
165
     */
166
    private function printFailed(): void
167
    {
168
        $filenameSuffix = ".errors";
169
        $files = Finder::findFiles("*$filenameSuffix")->in($this->folder);
170
        /** @var \SplFileInfo $file */
171
        foreach ($files as $name => $file) {
172
            echo "--- " . $file->getBasename($filenameSuffix) . "\n";
173
            echo file_get_contents($name);
174
        }
175
    }
176
177 1
    private function saveResults(TestCase $testCase): void
178
    {
179 1
        $jobs = $testCase->jobs;
180 1
        foreach ($jobs as $job) {
181 1
            switch ($job->result) {
182 1
                case Job::RESULT_PASSED:
183 1
                    $result = TestCase::RESULT_PASSED;
184 1
                    break;
185 1
                case Job::RESULT_SKIPPED:
186 1
                    $result = TestCase::RESULT_SKIPPED;
187 1
                    $this->skipped[] = new SkippedTest($job->name, (is_string($job->skip) ? $job->skip : ""));
188 1
                    break;
189
                case Job::RESULT_FAILED:
190
                    $result = TestCase::RESULT_FAILED;
191
                    $output = $job->output;
192
                    if (strlen($output) > 0) {
193
                        file_put_contents("$this->folder/$job->name.errors", $output);
194
                    }
195
                    break;
196
                default:
197
                    $result = "";
198
                    break;
199
            }
200 1
            $this->results .= $result;
201
        }
202 1
    }
203
}
204