Completed
Push — master ( 90f4ed...0dcbda )
by Jakub
03:05
created

TestCase::checkSkip()   B

Complexity

Conditions 11
Paths 7

Size

Total Lines 29
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 7
Bugs 0 Features 1
Metric Value
cc 11
eloc 21
c 7
b 0
f 1
nc 7
nop 1
dl 0
loc 29
rs 7.3166

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
declare(strict_types=1);
3
4
namespace MyTester;
5
6
/**
7
 * One test suit
8
 *
9
 * @author Jakub Konečný
10
 */
11
abstract class TestCase {
12
  use \Nette\SmartObject;
13
  
14
  public const METHOD_PATTERN = '#^test[A-Z0-9_]#';
15
  
16
  /**
17
   * Check whether to skip a test method
18
   *
19
   * @return bool|string
20
   */
21
  protected function checkSkip(\Nette\Reflection\Method $method) {
0 ignored issues
show
introduced by
Function's cyclomatic complexity (11) exceeds 10; consider refactoring the function
Loading history...
22
    if(!$method->hasAnnotation("skip")) {
23
      return false;
24
    }
25
    $value = $method->getAnnotation("skip");
26
    if(is_scalar($value)) {
0 ignored issues
show
introduced by
The condition is_scalar($value) is always false.
Loading history...
27
      return (bool) $value;
28
    } elseif($value instanceof \Nette\Utils\ArrayHash) {
29
      foreach($value as $k => $v) {
30
        switch($k) {
31
          case "php":
32
            if(version_compare(PHP_VERSION, (string) $v, "<")) {
33
              return "PHP version is lesser than $v";
34
            }
35
            break;
36
          case "extension":
37
            if(!extension_loaded($v)) {
38
              return "extension $v is not loaded";
39
            }
40
            break;
41
          case "sapi":
42
            if(PHP_SAPI != $v) {
43
              return "the sapi is not $v";
44
            }
45
            break;
46
        }
47
      }
48
    }
49
    return false;
50
  }
51
  
52
  /**
53
   * Get list of jobs with parameters for current test suit
54
   * 
55
   * @return Job[]
56
   */
57
  protected function getJobs(): array {
58
    $jobs = [];
59
    $r = new \Nette\Reflection\ClassType(get_class($this));
60
    $methods = array_values(preg_grep(static::METHOD_PATTERN, array_map(function(\ReflectionMethod $rm) {
61
      return $rm->getName();
62
    }, $r->getMethods())));
63
    foreach($methods as $method) {
64
      $rm = $r->getMethod($method);
65
      $data = [];
66
      /** @var callable $callback */
67
      $callback = [$this, $method];
68
      $job = [
69
        "name" => $this->getJobName($rm), "callback" => $callback, "params" => [], "skip" => $this->checkSkip($rm), "shouldFail" => $rm->hasAnnotation("fail")
0 ignored issues
show
introduced by
Line exceeds 120 characters; contains 158 characters
Loading history...
70
      ];
71
      if($rm->getNumberOfParameters() && $rm->hasAnnotation("data")) {
72
        $data = (array) $rm->getAnnotation("data");
73
      }
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
    return $jobs;
85
  }
86
  
87
  /**
88
   * Get name of current test suit
89
   */
90
  protected function getSuitName(): string {
91
    $suitName = get_class($this);
92
    $r = new \Nette\Reflection\ClassType($suitName);
93
    if($r->hasAnnotation("testSuit")) {
94
      $suitName = (string) $r->getAnnotation("testSuit");
95
    }
96
    return $suitName;
97
  }
98
  
99
  /**
100
   * Get name for a job
101
   */
102
  protected function getJobName(\Nette\Reflection\Method $method): string {
103
    if($method->hasAnnotation("test")) {
104
      return (string) $method->getAnnotation("test");
105
    }
106
    return $this->getSuitName() . "::" . $method->getName();
107
  }
108
  
109
  /**
110
   * Called at start of the suit
111
   */
112
  public function startUp(): void {
113
  }
114
  
115
  /**
116
   * Called at end of the suit
117
   */
118
  public function shutDown(): void {
119
  }
120
  
121
  /**
122
   * Called before each job
123
   */
124
  public function setUp(): void {
125
  }
126
  
127
  /**
128
   * Called after each job
129
   */
130
  public function tearDown(): void {
131
  }
132
  
133
  protected function runJob(Job $job): string {
134
    /** @var array $callback */
135
    $callback = $job->callback;
136
    $jobName = $this->getJobName(\Nette\Reflection\Method::from($callback[0], $callback[1]));
137
    Environment::$currentJob = $jobName;
138
    if(!$job->skip) {
139
      $this->setUp();
140
    }
141
    $job->execute();
142
    if(!$job->skip) {
143
      $this->tearDown();
144
    }
145
    Environment::$currentJob = "";
146
    switch($job->result) {
147
      case "passed":
148
        return ".";
149
      case "skipped":
150
        return "s";
151
      case "failed":
152
        return "F";
153
    }
154
    return "";
155
  }
156
  
157
  /**
158
   * Runs the test suit
159
   */
160
  public function run(): bool {
161
    $this->startUp();
162
    $jobs = $this->getJobs();
163
    $output = "";
164
    $passed = true;
165
    foreach($jobs as $job) {
166
      $output .= $this->runJob($job);
167
      if($job->result === "failed") {
168
        $passed = false;
169
      }
170
    }
171
    $this->shutDown();
172
    echo $output;
173
    return $passed;
174
  }
175
}
176
?>