Completed
Push — master ( 1f7fc9...50ad35 )
by Jakub
01:38
created

TestCase::getJobName()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 6
rs 10
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 suite
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_SUITE = "testSuite";
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 suite
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($this, $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 suite
90
   */
91
  protected function getSuiteName(): string {
92
    $annotation = $this->annotationsReader->getAnnotation(static::ANNOTATION_TEST_SUITE, static::class);
93
    if($annotation !== null) {
94
      return $annotation;
95
    }
96
    $annotation = $this->annotationsReader->getAnnotation("testSuit", static::class);
97
    if($annotation !== null) {
98
      return $annotation;
99
    }
100
    return static::class;
101
  }
102
  
103
  /**
104
   * Get name for a job
105
   * @param string|object $class
106
   */
107
  protected function getJobName($class, string $method): string {
108
    $annotation = $this->annotationsReader->getAnnotation(static::ANNOTATION_TEST, $class, $method);
109
    if($annotation !== null) {
110
      return $annotation;
111
    }
112
    return $this->getSuiteName() . "::" . $method;
113
  }
114
  
115
  /**
116
   * Called at start of the suite
117
   */
118
  public function startUp(): void {
119
  }
120
  
121
  /**
122
   * Called at end of the suite
123
   */
124
  public function shutDown(): void {
125
  }
126
  
127
  /**
128
   * Called before each job
129
   */
130
  public function setUp(): void {
131
  }
132
  
133
  /**
134
   * Called after each job
135
   */
136
  public function tearDown(): void {
137
  }
138
  
139
  protected function runJob(Job $job): string {
140
    Environment::$currentJob = $job->name;
141
    $this->resetCounter();
142
    if(!$job->skip) {
143
      $this->setUp();
144
    }
145
    $this->shouldFail = $job->shouldFail;
146
    $job->execute();
147
    if(!$job->skip) {
148
      $this->tearDown();
149
    }
150
    $this->shouldFail = false;
151
    Environment::$currentJob = "";
152
    $this->resetCounter();
153
    switch($job->result) {
154
      case Job::RESULT_PASSED:
155
        return static::RESULT_PASSED;
156
      case Job::RESULT_SKIPPED:
157
        return static::RESULT_SKIPPED;
158
      case Job::RESULT_FAILED:
159
        return static::RESULT_FAILED;
160
    }
161
    return "";
162
  }
163
  
164
  /**
165
   * Runs the test suite
166
   */
167
  public function run(): bool {
168
    $this->startUp();
169
    $jobs = $this->getJobs();
170
    $passed = true;
171
    foreach($jobs as $job) {
172
      $result = $this->runJob($job);
173
      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

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