Completed
Push — master ( dbb439...8abb49 )
by Jakub
01:34
created

Tester.php$0 ➔ saveResults()   B

Complexity

Conditions 7

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 10.1359

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 8.6186
c 0
b 0
f 0
ccs 12
cts 20
cp 0.6
cc 7
crap 10.1359
1
<?php
2
declare(strict_types=1);
3
4
namespace MyTester;
5
6
use Ayesh\PHP_Timer\Timer;
7
use Jean85\PrettyVersions;
8
use MyTester\Bridges\NetteRobotLoader\TestSuitesFinder;
9
use Nette\Utils\Finder;
10
11
/**
12
 * Automated tests runner
13
 * 
14
 * @author Jakub Konečný
15
 * @property-read string[] $suites
16
 * @method void onExecute()
17
 */
18
final class Tester {
19
  use \Nette\SmartObject;
20
21
  private const PACKAGE_NAME = "konecnyjakub/mytester";
22
  private const TIMER_NAME = "My Tester";
23
24
  /** @var string[] */
25
  private array $suites = [];
26
  /** @var callable[] */
27
  public array $onExecute = [];
28
  public ITestSuiteFactory $testSuiteFactory;
29
  public ITestsSuitesFinder $testsSuitesFinder;
30
  private string $folder;
31
  /** @var SkippedTest[] */
32
  private array $skipped = [];
33
  private string $results = "";
34
35 1
  public function __construct(string $folder = null, ITestsSuitesFinder $testsSuitesFinder = null, ITestSuiteFactory $testSuiteFactory = null) {
0 ignored issues
show
introduced by
Line exceeds 120 characters; contains 144 characters
Loading history...
36 1
    $this->onExecute[] = [$this, "setup"];
37 1
    $this->onExecute[] = [$this, "printInfo"];
38 1
    $this->testsSuitesFinder = $testsSuitesFinder ?? new TestSuitesFinder();
39 1
    $this->testSuiteFactory = $testSuiteFactory ?? new class implements ITestSuiteFactory {
40
      public function create(string $className): TestCase {
41 1
        return new $className();
42
      }
43
    };
44 1
    $this->folder = $folder ?? \getTestsDirectory();
45 1
  }
46
  
47
  /**
48
   * @return string[]
49
   */
50 1
  protected function getSuites(): array {
51 1
    if(count($this->suites) === 0) {
52 1
      $this->suites = $this->testsSuitesFinder->getSuites($this->folder);
53
    }
54 1
    return $this->suites;
55
  }
56
  
57
  /**
58
   * Execute all tests
59
   */
60 1
  public function execute(): void {
61 1
    $this->onExecute();
62 1
    $failed = false;
63 1
    foreach($this->getSuites() as $suite) {
64 1
      $suite = $this->testSuiteFactory->create($suite);
65 1
      if(!$suite->run()) {
66
        $failed = true;
67
      }
68 1
      $this->saveResults($suite);
69
    }
70 1
    $this->printResults();
71 1
    exit((int) $failed);
72
  }
73
74 1
  private function setup(): void {
75 1
    Timer::start(static::TIMER_NAME);
76 1
  }
77
78
  /**
79
   * Print version of My Tester and PHP
80
   */
81 1
  private function printInfo(): void {
82 1
    echo "My Tester " . PrettyVersions::getVersion(static::PACKAGE_NAME) . "\n";
83 1
    echo "\n";
84 1
    echo "PHP " . PHP_VERSION . "(" . PHP_SAPI . ")\n";
85 1
    echo "\n";
86 1
  }
87
88 1
  private function printResults(): void {
89 1
    $results = $this->results;
90 1
    echo $results . "\n";
91 1
    $this->printSkipped();
92 1
    $failed = str_contains($results, TestCase::RESULT_FAILED);
93 1
    if(!$failed) {
94 1
      echo "\n";
95 1
      echo "OK";
96
    } else {
97
      $this->printFailed();
98
      echo "\n";
99
      echo "Failed";
100
    }
101 1
    $resultsLine = " (" . strlen($results) . " tests";
102 1
    if($failed) {
103
      $resultsLine .= ", " . substr_count($results, TestCase::RESULT_FAILED) . " failed";
104
    }
105 1
    if(str_contains($results, TestCase::RESULT_SKIPPED)) {
106 1
      $resultsLine .= ", " . substr_count($results, TestCase::RESULT_SKIPPED) . " skipped";
107
    }
108 1
    Timer::stop(static::TIMER_NAME);
109 1
    $time = Timer::read(static::TIMER_NAME, Timer::FORMAT_HUMAN);
110 1
    $resultsLine .= ", $time)";
111 1
    echo $resultsLine . "\n";
112 1
  }
113
114
  /**
115
   * Print info about skipped tests
116
   */
117 1
  private function printSkipped(): void {
118 1
    foreach($this->skipped as $skipped) {
119 1
      $reason = "";
120 1
      if($skipped->reason) {
121 1
        $reason = ": {$skipped->reason}";
122
      }
123 1
      echo "Skipped $skipped->name$reason\n";
124
    }
125 1
  }
126
127
  /**
128
   * Print info about failed tests
129
   */
130
  private function printFailed(): void {
131
    $filenameSuffix = ".errors";
132
    $files = Finder::findFiles("*$filenameSuffix")->in($this->folder);
133
    /** @var \SplFileInfo $file */
134
    foreach($files as $name => $file) {
135
      echo "--- " . $file->getBasename($filenameSuffix) . "\n";
136
      echo file_get_contents($name);
137
    }
138
  }
139
140 1
  private function saveResults(TestCase $testCase): void {
141 1
    $jobs = $testCase->jobs;
142 1
    foreach($jobs as $job) {
143 1
      switch($job->result) {
144 1
        case Job::RESULT_PASSED:
145 1
          $result = TestCase::RESULT_PASSED;
146 1
          break;
147 1
        case Job::RESULT_SKIPPED:
148 1
          $result = TestCase::RESULT_SKIPPED;
149 1
          $this->skipped[] = new SkippedTest($job->name, (is_string($job->skip) ? $job->skip : ""));
150 1
          break;
151
        case Job::RESULT_FAILED:
152
          $result = TestCase::RESULT_FAILED;
153
          $output = $job->output;
154
          if(strlen($output) > 0) {
155
            file_put_contents("$this->folder/$job->name.errors", $output);
156
          }
157
          break;
158
        default:
159
          $result = "";
160
          break;
161
      }
162 1
      $this->results .= $result;
163
    }
164 1
  }
165
}
166
?>