Completed
Push — master ( c8c0c1...47af09 )
by Jakub
01:44
created

Tester   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 160
Duplicated Lines 0 %

Test Coverage

Coverage 76.74%

Importance

Changes 36
Bugs 6 Features 7
Metric Value
wmc 25
eloc 84
c 36
b 6
f 7
dl 0
loc 160
ccs 66
cts 86
cp 0.7674
rs 10

19 Methods

Rating   Name   Duplication   Size   Complexity  
setup() 0 3 ?
A hp$0 ➔ getSuites() 0 6 2
A hp$0 ➔ create() 0 3 1
printFailed() 0 8 ?
A hp$0 ➔ __construct() 0 16 1
A hp$0 ➔ printFailed() 0 8 2
A hp$0 ➔ printInfo() 0 6 1
A hp$0 ➔ setup() 0 3 1
getSuites() 0 6 ?
printInfo() 0 6 ?
__construct() 0 16 ?
A hp$0 ➔ printResults() 0 25 4
A hp$0 ➔ execute() 0 13 3
B hp$0 ➔ saveResults() 0 24 7
A hp$0 ➔ printSkipped() 0 8 3
saveResults() 0 24 ?
printResults() 0 25 ?
printSkipped() 0 8 ?
execute() 0 13 ?
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\Utils\Finder;
11
12
/**
13
 * Automated tests runner
14
 *
15
 * @author Jakub Konečný
16
 * @property-read string[] $suites
17
 * @method void onExecute()
18
 */
19
final class Tester
20
{
21
    use \Nette\SmartObject;
22
23
    private const PACKAGE_NAME = "konecnyjakub/mytester";
24
    private const TIMER_NAME = "My Tester";
25
26
    /** @var string[] */
27
    private array $suites = [];
28
    /** @var callable[] */
29
    public array $onExecute = [];
30
    public ITestSuiteFactory $testSuiteFactory;
31
    public ITestsSuitesFinder $testsSuitesFinder;
32
    private string $folder;
33
    /** @var SkippedTest[] */
34
    private array $skipped = [];
35
    private string $results = "";
36
37 1
    public function __construct(
38
        string $folder = null,
39
        ITestsSuitesFinder $testsSuitesFinder = null,
40
        ITestSuiteFactory $testSuiteFactory = null
41
    ) {
42 1
        $this->onExecute[] = [$this, "setup"];
43 1
        $this->onExecute[] = [$this, "printInfo"];
44 1
        $this->testsSuitesFinder = $testsSuitesFinder ?? new TestSuitesFinder();
45 1
        $this->testSuiteFactory = $testSuiteFactory ?? new class implements ITestSuiteFactory
46
        {
47
            public function create(string $className): TestCase
48
            {
49 1
                return new $className();
50
            }
51
        };
52 1
        $this->folder = $folder ?? \getTestsDirectory();
53 1
    }
54
55
    /**
56
     * @return string[]
57
     */
58 1
    protected function getSuites(): array
59
    {
60 1
        if (count($this->suites) === 0) {
61 1
            $this->suites = $this->testsSuitesFinder->getSuites($this->folder);
62
        }
63 1
        return $this->suites;
64
    }
65
66
    /**
67
     * Execute all tests
68
     */
69 1
    public function execute(): void
70
    {
71 1
        $this->onExecute();
72 1
        $failed = false;
73 1
        foreach ($this->getSuites() as $suite) {
74 1
            $suite = $this->testSuiteFactory->create($suite);
75 1
            if (!$suite->run()) {
76
                $failed = true;
77
            }
78 1
            $this->saveResults($suite);
79
        }
80 1
        $this->printResults();
81 1
        exit((int) $failed);
82
    }
83
84 1
    private function setup(): void
85
    {
86 1
        Timer::start(static::TIMER_NAME);
87 1
    }
88
89
    /**
90
     * Print version of My Tester and PHP
91
     */
92 1
    private function printInfo(): void
93
    {
94 1
        echo "My Tester " . PrettyVersions::getVersion(static::PACKAGE_NAME) . "\n";
95 1
        echo "\n";
96 1
        echo "PHP " . PHP_VERSION . "(" . PHP_SAPI . ")\n";
97 1
        echo "\n";
98 1
    }
99
100 1
    private function printResults(): void
101
    {
102 1
        $results = $this->results;
103 1
        echo $results . "\n";
104 1
        $this->printSkipped();
105 1
        $failed = str_contains($results, TestCase::RESULT_FAILED);
106 1
        if (!$failed) {
107 1
            echo "\n";
108 1
            echo "OK";
109
        } else {
110
            $this->printFailed();
111
            echo "\n";
112
            echo "Failed";
113
        }
114 1
        $resultsLine = " (" . strlen($results) . " tests";
115 1
        if ($failed) {
116
            $resultsLine .= ", " . substr_count($results, TestCase::RESULT_FAILED) . " failed";
117
        }
118 1
        if (str_contains($results, TestCase::RESULT_SKIPPED)) {
119 1
            $resultsLine .= ", " . substr_count($results, TestCase::RESULT_SKIPPED) . " skipped";
120
        }
121 1
        Timer::stop(static::TIMER_NAME);
122 1
        $time = Timer::read(static::TIMER_NAME, Timer::FORMAT_HUMAN);
123 1
        $resultsLine .= ", $time)";
124 1
        echo $resultsLine . "\n";
125 1
    }
126
127
    /**
128
     * Print info about skipped tests
129
     */
130 1
    private function printSkipped(): void
131
    {
132 1
        foreach ($this->skipped as $skipped) {
133 1
            $reason = "";
134 1
            if ($skipped->reason) {
135 1
                $reason = ": {$skipped->reason}";
136
            }
137 1
            echo "Skipped $skipped->name$reason\n";
138
        }
139 1
    }
140
141
    /**
142
     * Print info about failed tests
143
     */
144
    private function printFailed(): void
145
    {
146
        $filenameSuffix = ".errors";
147
        $files = Finder::findFiles("*$filenameSuffix")->in($this->folder);
148
        /** @var \SplFileInfo $file */
149
        foreach ($files as $name => $file) {
150
            echo "--- " . $file->getBasename($filenameSuffix) . "\n";
151
            echo file_get_contents($name);
152
        }
153
    }
154
155 1
    private function saveResults(TestCase $testCase): void
156
    {
157 1
        $jobs = $testCase->jobs;
158 1
        foreach ($jobs as $job) {
159 1
            switch ($job->result) {
160 1
                case Job::RESULT_PASSED:
161 1
                    $result = TestCase::RESULT_PASSED;
162 1
                    break;
163 1
                case Job::RESULT_SKIPPED:
164 1
                    $result = TestCase::RESULT_SKIPPED;
165 1
                    $this->skipped[] = new SkippedTest($job->name, (is_string($job->skip) ? $job->skip : ""));
166 1
                    break;
167
                case Job::RESULT_FAILED:
168
                    $result = TestCase::RESULT_FAILED;
169
                    $output = $job->output;
170
                    if (strlen($output) > 0) {
171
                        file_put_contents("$this->folder/$job->name.errors", $output);
172
                    }
173
                    break;
174
                default:
175
                    $result = "";
176
                    break;
177
            }
178 1
            $this->results .= $result;
179
        }
180 1
    }
181
}
182