Passed
Push — master ( b0030b...d4bf1b )
by Jakub
09:20
created

TestCase   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 158
Duplicated Lines 0 %

Test Coverage

Coverage 97.14%

Importance

Changes 38
Bugs 0 Features 6
Metric Value
wmc 21
eloc 70
c 38
b 0
f 6
dl 0
loc 158
rs 10
ccs 68
cts 70
cp 0.9714

10 Methods

Rating   Name   Duplication   Size   Complexity  
A getJobName() 0 7 2
A run() 0 13 3
A setUp() 0 2 1
A runJob() 0 16 3
A getSuiteName() 0 7 2
A startUp() 0 2 1
A __construct() 0 6 1
A shutDown() 0 2 1
B getJobs() 0 33 6
A tearDown() 0 2 1
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
27
    public const METHOD_PATTERN = '#^test[A-Z0-9_]#';
28
29
    /** @internal */
30
    public const ANNOTATION_TEST = "test";
31
    /** @internal */
32
    public const ANNOTATION_TEST_SUITE = "testSuite";
33
34
    protected SkipChecker $skipChecker;
35
    protected DataProvider $dataProvider;
36
    protected Reader $annotationsReader;
37
38
    /** @var Job[] */
39
    private array $jobs = [];
40
41 1
    public function __construct()
42
    {
43 1
        $this->annotationsReader = new Reader();
44 1
        $this->annotationsReader->registerEngine(new PhpAttributesEngine());
45 1
        $this->skipChecker = new SkipChecker($this->annotationsReader);
46 1
        $this->dataProvider = new DataProvider($this->annotationsReader);
47 1
    }
48
49
    /**
50
     * Get list of jobs with parameters for current test suite
51
     *
52
     * @return Job[]
53
     */
54 1
    protected function getJobs(): array
55
    {
56 1
        if (count($this->jobs) === 0) {
57 1
            $r = new ReflectionClass(static::class);
58 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...
59 1
                return $rm->getName();
60 1
            }, $r->getMethods(ReflectionMethod::IS_PUBLIC))));
61 1
            foreach ($methods as $method) {
62
                /** @var callable $callback */
63 1
                $callback = [$this, $method];
64 1
                $job = [
65 1
                    "name" => $this->getJobName(static::class, $method),
66 1
                    "callback" => $callback,
67
                    "params" => [],
68 1
                    "skip" => $this->skipChecker->shouldSkip(static::class, $method),
69
                ];
70 1
                $data = $this->dataProvider->getData($this, $method);
71 1
                if (count($data) > 0) {
72 1
                    foreach ($data as $value) {
73 1
                        $job["params"][0] = $value;
74 1
                        $this->jobs[] = new Job(... $job);
75 1
                        $job["params"] = [];
76
                    }
77
                } else {
78 1
                    $rm = new ReflectionMethod($this, $method);
79 1
                    if ($rm->getNumberOfParameters() > 0) {
80 1
                        $job["skip"] = "Method requires at least 1 parameter but data provider does not provide any.";
81
                    }
82 1
                    $this->jobs[] = new Job(... $job);
83
                }
84
            }
85
        }
86 1
        return $this->jobs;
87
    }
88
89
    /**
90
     * Get name of current test suite
91
     */
92 1
    protected function getSuiteName(): string
93
    {
94 1
        $annotation = $this->annotationsReader->getAnnotation(static::ANNOTATION_TEST_SUITE, static::class);
95 1
        if ($annotation !== null) {
96 1
            return $annotation;
97
        }
98 1
        return static::class;
99
    }
100
101
    /**
102
     * Get name for a job
103
     */
104 1
    protected function getJobName(string|object $class, string $method): string
105
    {
106 1
        $annotation = $this->annotationsReader->getAnnotation(static::ANNOTATION_TEST, $class, $method);
107 1
        if ($annotation !== null) {
108 1
            return $annotation;
109
        }
110 1
        return $this->getSuiteName() . "::" . $method;
111
    }
112
113
    /**
114
     * Called at start of the suite
115
     */
116 1
    public function startUp(): void
117
    {
118 1
    }
119
120
    /**
121
     * Called at end of the suite
122
     */
123 1
    public function shutDown(): void
124
    {
125 1
    }
126
127
    /**
128
     * Called before each job
129
     */
130 1
    public function setUp(): void
131
    {
132 1
    }
133
134
    /**
135
     * Called after each job
136
     */
137 1
    public function tearDown(): void
138
    {
139 1
    }
140
141 1
    protected function runJob(Job $job): string
142
    {
143 1
        $this->resetCounter();
144 1
        if (!$job->skip) {
145 1
            $this->setUp();
146
        }
147 1
        $job->execute();
148 1
        if (!$job->skip) {
149 1
            $this->tearDown();
150
        }
151 1
        $this->resetCounter();
152 1
        return match ($job->result) {
153 1
            Job::RESULT_PASSED => static::RESULT_PASSED,
154 1
            Job::RESULT_SKIPPED => static::RESULT_SKIPPED,
155
            Job::RESULT_FAILED => static::RESULT_FAILED,
156 1
            default => "",
157
        };
158
    }
159
160
    /**
161
     * Runs the test suite
162
     */
163 1
    public function run(): bool
164
    {
165 1
        $this->startUp();
166 1
        $jobs = $this->getJobs();
167 1
        $passed = true;
168 1
        foreach ($jobs as $job) {
169 1
            $this->runJob($job);
170 1
            if ($job->result === Job::RESULT_FAILED) {
171
                $passed = false;
172
            }
173
        }
174 1
        $this->shutDown();
175 1
        return $passed;
176
    }
177
}
178