TestSuite   A
last analyzed

Complexity

Total Complexity 26

Size/Duplication

Total Lines 237
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 47
c 2
b 0
f 0
dl 0
loc 237
rs 10
ccs 30
cts 30
cp 1
wmc 26

14 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A average() 0 3 2
A detach() 0 4 1
A getTests() 0 3 1
A getContainer() 0 3 1
A setContainer() 0 4 1
A beforeTest() 0 2 1
A reset() 0 7 3
A has() 0 3 1
A getAnswers() 0 10 3
A getScore() 0 3 1
A run() 0 25 3
A afterTest() 0 2 1
A attach() 0 23 6
1
<?php
2
3
/**
4
 * TestSuite.php
5
 *
6
 * This Testsuite allows you to run tests.
7
 *
8
 * PHP version 7.4
9
 *
10
 * @category Core
11
 * @package  RedboxTestSuite
12
 * @author   Johnny Mast <[email protected]>
13
 * @license  https://opensource.org/licenses/MIT MIT
14
 * @link     https://github.com/johnnymast/redbox-testsuite
15
 * @since    1.0
16
 */
17
18
namespace Redbox\Testsuite;
19
20
use Redbox\Testsuite\Interfaces\ContainerInterface;
21
use SplObjectStorage;
22
23
class TestSuite
24
{
25
    /**
26
     * Storage to contain the
27
     * tests.
28
     *
29
     * @var SplObjectStorage|null
30
     */
31
    protected ?SplObjectStorage $tests = null;
32
33
    /**
34
     * Storage container to contain information
35
     * for the tests.
36
     *
37
     * @var ContainerInterface|null
38
     */
39
    protected ?ContainerInterface $container = null;
40
41 18
    /**
42
     * Test Score counter.
43 18
     *
44 18
     * @var int|double
45
     */
46
    protected $score = 0;
47
48
    /**
49
     * TestSuite constructor.
50
     */
51
    public function __construct()
52 10
    {
53
        $this->tests = new SplObjectStorage;
54 10
55 10
        $this->setContainer(new Container());
56
    }
57
58
    /**
59
     * This function will be called before every
60
     * test.
61
     *
62
     * @return void
63
     */
64
    public function beforeTest()
65 18
    {
66
        // Overwrite at will
67 18
    }
68 8
69 8
    /**
70
     * This function will be called after every
71
     * test.
72 18
     *
73
     * @return void
74
     */
75
    public function afterTest()
76
    {
77
        // Overwrite at will
78
    }
79
80
    /**
81 18
     * Set he storage container for the test suite.
82 2
     *
83
     * @param ContainerInterface $container The storage container for the test suite.
84
     *
85 16
     * @return $this
86
     */
87 16
    public function setContainer(ContainerInterface $container): self
88
    {
89
        $this->container = $container;
90
        return $this;
91
    }
92
93
    /**
94
     * Return the storage container.
95
     *
96
     * @return ContainerInterface
97 2
     */
98
    public function getContainer(): ContainerInterface
99 2
    {
100 2
        return $this->container;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->container could return the type null which is incompatible with the type-hinted return Redbox\Testsuite\Interfaces\ContainerInterface. Consider adding an additional type-check to rule them out.
Loading history...
101
    }
102
103
    /**
104
     * Reset the score and rewind
105
     * the tests storage.
106
     *
107
     * @return void
108
     */
109
    public function reset(): void
110 6
    {
111
        $this->score = 0;
112 6
113
        if ($this->tests->count() > 0) {
0 ignored issues
show
Bug introduced by
The method count() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

113
        if ($this->tests->/** @scrutinizer ignore-call */ count() > 0) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
114
            foreach ($this->tests as $test) {
115
                $test->score->reset();
116
            }
117
        }
118
    }
119
120 10
    /**
121
     * Attach a Test or an array of
122 10
     * Tests to the TestSuite.
123
     *
124
     * @param $info The Test to attach.
0 ignored issues
show
Bug introduced by
The type Redbox\Testsuite\The was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
125
     *
126
     * @return $this
127 10
     */
128
    public function attach($info): self
129 10
    {
130 10
        if (is_array($info) === true) {
131 10
            foreach ($info as $test) {
132 10
                $this->attach($test);
133
            }
134
        } else {
135 10
            $test = $info;
136
137
            if (is_string($info) === true && class_exists($info) === true) {
138
                $test = new $info();
139
            }
140
141
            if (is_subclass_of($test, TestCase::class) === false) {
142
                throw new \InvalidArgumentException('This Test does not extend the TestCase abstract class.');
143 6
            }
144
145 6
            $test->setName(get_class($test) . '_' . $this->tests->count());
146
147
            $this->tests->attach($test);
148
        }
149
150
        return $this;
151
    }
152
153
    /**
154
     * Detach a given test from the
155
     * TestSuite.
156
     *
157
     * @param TestCase $test The test to detach.
158
     *
159
     * @return $this
160
     */
161
    public function detach(TestCase $test): self
162
    {
163
        $this->tests->detach($test);
164
        return $this;
165
    }
166
167
    /**
168
     * Check to see if the TestSuite has a given
169
     * test inside.
170
     *
171
     * @param TestCase $test The Test to check for.
172
     *
173
     * @return bool
174
     */
175
    public function has(TestCase $test): bool
176
    {
177
        return $this->tests->contains($test);
178
    }
179
180
    /**
181
     * Run the tests
182
     *
183
     * @param bool $reset Will the tests reset before running.
184
     *
185
     * @return int
186
     */
187
    public function run($reset = true): int
188
    {
189
        $tests_run = 0;
190
191
        /**
192
         * Reset the test results
193
         */
194
        if ($reset === true) {
195
            $this->reset();
196
        }
197
198
        $container = $this->getContainer();
199
200
        foreach ($this->tests as $test) {
201
            $this->beforeTest();
202
203
            $test->run($container);
204
205
            $this->afterTest();
206
207
            $this->score += $test->score->getScore();
208
            $tests_run++;
209
        }
210
211
        return $tests_run;
212
    }
213
214
    /**
215
     * Return the answers/motivations from all tests.
216
     *
217
     * @return array
218
     */
219
    public function getAnswers(): array
220
    {
221
        $info = [];
222
        if ($this->tests->count() > 0) {
223
            foreach ($this->tests as $test) {
224
                $info[$test->getName()] = $test->score->getScoreInfo();
225
            }
226
        }
227
228
        return $info;
229
    }
230
231
    /**
232
     * Return the test suite score.
233
     *
234
     * @return mixed
235
     */
236
    public function getScore()
237
    {
238
        return $this->score;
239
    }
240
241
    /**
242
     * Return all tests.
243
     *
244
     * @return SplObjectStorage
245
     */
246
    public function getTests(): SplObjectStorage
247
    {
248
        return $this->tests;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->tests could return the type null which is incompatible with the type-hinted return SplObjectStorage. Consider adding an additional type-check to rule them out.
Loading history...
249
    }
250
251
    /**
252
     * Return the score average for
253
     * this TestSuite.
254
     *
255
     * @return false|float|int
256
     */
257
    public function average()
258
    {
259
        return ($this->tests->count() > 0) ? ($this->getScore() / $this->tests->count()) : false;
260
    }
261
}
262