Passed
Push — master ( 3cc3ad...47373b )
by Jakub
01:33
created

TestCase::getJobs()   B

Complexity

Conditions 6
Paths 2

Size

Total Lines 34
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

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

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

169
      /** @scrutinizer ignore-deprecated */ Environment::addResult($result);
Loading history...
170
      if($job->result === Job::RESULT_FAILED) {
171
        $passed = false;
172
      }
173
    }
174
    $this->shutDown();
175
    return $passed;
176
  }
177
}
178
?>