Passed
Push — master ( 85f9d4...f6c128 )
by Jakub
12:52
created

TestCase::getJobs()   B

Complexity

Conditions 7
Paths 2

Size

Total Lines 40
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 31
CRAP Score 7

Importance

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