Passed
Push — master ( 11230f...5f5cdb )
by Jakub
12:32
created

TestCase::shutDown()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 0
c 1
b 0
f 0
dl 0
loc 2
ccs 0
cts 0
cp 0
rs 10
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace MyTester;
6
7
use MyTester\Annotations\PhpAttributesEngine;
8
use MyTester\Annotations\Reader;
9
use ReflectionClass;
10
use ReflectionMethod;
11
12
/**
13
 * One test suite
14
 *
15
 * @author Jakub Konečný
16
 * @property-read Job[] $jobs @internal
17
 */
18
abstract class TestCase
19
{
20
    use \Nette\SmartObject;
21
    use TAssertions;
22
23
    public const RESULT_PASSED = ".";
24
    public const RESULT_SKIPPED = "s";
25
    public const RESULT_FAILED = "F";
26
    public const RESULT_PASSED_WITH_WARNINGS = "W";
27
28
    public const METHOD_PATTERN = '#^test[A-Z0-9_]#';
29
30
    /** @internal */
31
    public const ANNOTATION_TEST = "test";
32
    /** @internal */
33
    public const ANNOTATION_TEST_SUITE = "testSuite";
34
35
    protected SkipChecker $skipChecker;
36
    protected DataProvider $dataProvider;
37
    protected Reader $annotationsReader;
38
39
    /** @var Job[] */
40
    private array $jobs = [];
41
42 1
    public function __construct()
43
    {
44 1
        $this->annotationsReader = new Reader();
45 1
        $this->annotationsReader->registerEngine(new PhpAttributesEngine());
46 1
        $this->skipChecker = new SkipChecker($this->annotationsReader);
47 1
        $this->dataProvider = new DataProvider($this->annotationsReader);
48
    }
49
50
    /**
51
     * Get list of jobs with parameters for current test suite
52
     *
53
     * @return Job[]
54
     */
55 1
    protected function getJobs(): array
56
    {
57 1
        if (count($this->jobs) === 0) {
58 1
            $r = new ReflectionClass(static::class);
59 1
            $methods = array_values((array) preg_grep(static::METHOD_PATTERN, array_map(function (ReflectionMethod $rm) {
0 ignored issues
show
introduced by
Line exceeds 120 characters; contains 121 characters
Loading history...
60 1
                return $rm->getName();
61 1
            }, $r->getMethods(ReflectionMethod::IS_PUBLIC))));
62 1
            foreach ($methods as $method) {
63
                /** @var callable $callback */
64 1
                $callback = [$this, $method];
65 1
                $job = [
66 1
                    "name" => $this->getJobName(static::class, $method),
67
                    "callback" => $callback,
68
                    "params" => [],
69 1
                    "skip" => $this->skipChecker->shouldSkip(static::class, $method),
70
                    "onAfterExecute" => [
71 1
                        function (): void {
72 1
                            if ($this->getCounter() === 0) {
73 1
                                echo "Warning: No assertions were performed.\n";
74
                            }
75
                        },
76
                    ],
77
                ];
78 1
                $data = $this->dataProvider->getData($this, $method);
79 1
                if (count($data) > 0) {
80 1
                    foreach ($data as $value) {
81 1
                        $job["params"][0] = $value;
82 1
                        $this->jobs[] = new Job(... $job);
83 1
                        $job["params"] = [];
84
                    }
85
                } else {
86 1
                    $rm = new ReflectionMethod($this, $method);
87 1
                    if ($rm->getNumberOfParameters() > 0) {
88 1
                        $job["skip"] = "Method requires at least 1 parameter but data provider does not provide any.";
89
                    }
90 1
                    $this->jobs[] = new Job(... $job);
91
                }
92
            }
93
        }
94 1
        return $this->jobs;
95
    }
96
97
    /**
98
     * Get name of current test suite
99
     */
100 1
    protected function getSuiteName(): string
101
    {
102 1
        $annotation = $this->annotationsReader->getAnnotation(static::ANNOTATION_TEST_SUITE, static::class);
103 1
        if ($annotation !== null) {
104 1
            return $annotation;
105
        }
106 1
        return static::class;
107
    }
108
109
    /**
110
     * Get name for a job
111
     */
112 1
    protected function getJobName(string|object $class, string $method): string
113
    {
114 1
        $annotation = $this->annotationsReader->getAnnotation(static::ANNOTATION_TEST, $class, $method);
115 1
        if ($annotation !== null) {
116 1
            return $annotation;
117
        }
118 1
        return $this->getSuiteName() . "::" . $method;
119
    }
120
121
    /**
122
     * Called at start of the suite
123
     */
124
    public function startUp(): void
125
    {
126
    }
127
128
    /**
129
     * Called at end of the suite
130
     */
131
    public function shutDown(): void
132
    {
133
    }
134
135
    /**
136
     * Called before each job
137
     */
138
    public function setUp(): void
139
    {
140
    }
141
142
    /**
143
     * Called after each job
144
     */
145
    public function tearDown(): void
146
    {
147
    }
148
149 1
    protected function runJob(Job $job): string
150
    {
151 1
        $this->resetCounter();
152 1
        if (!$job->skip) {
153 1
            $this->setUp();
154
        }
155 1
        $job->execute();
156 1
        if (!$job->skip) {
157 1
            $this->tearDown();
158
        }
159 1
        $this->resetCounter();
160 1
        return match ($job->result) {
161 1
            Job::RESULT_PASSED => static::RESULT_PASSED,
162 1
            Job::RESULT_SKIPPED => static::RESULT_SKIPPED,
163 1
            Job::RESULT_FAILED => static::RESULT_FAILED,
164 1
            default => "",
165
        };
166
    }
167
168
    /**
169
     * Runs the test suite
170
     */
171 1
    public function run(): bool
172
    {
173 1
        $this->startUp();
174 1
        $jobs = $this->getJobs();
175 1
        $passed = true;
176 1
        foreach ($jobs as $job) {
177 1
            $this->runJob($job);
178 1
            if ($job->result === Job::RESULT_FAILED) {
179
                $passed = false;
180
            }
181
        }
182 1
        $this->shutDown();
183 1
        return $passed;
184
    }
185
}
186