1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Rmiller\ErrorExtension\Tester; |
4
|
|
|
|
5
|
|
|
use Behat\Testwork\Environment\Environment; |
6
|
|
|
use Behat\Testwork\Output\Printer\OutputPrinter; |
7
|
|
|
use Behat\Testwork\Specification\SpecificationIterator; |
8
|
|
|
use Behat\Testwork\Tester\Result\TestResult; |
9
|
|
|
use Behat\Testwork\Tester\Setup\Setup; |
10
|
|
|
use Behat\Testwork\Tester\Setup\Teardown; |
11
|
|
|
use Behat\Testwork\Tester\SuiteTester; |
12
|
|
|
use RMiller\ErrorExtension\Observer\ErrorObservers; |
13
|
|
|
use Symfony\Component\Console\Helper\FormatterHelper; |
14
|
|
|
use Symfony\Component\Console\Output\OutputInterface; |
15
|
|
|
|
16
|
|
|
class ErrorTester implements SuiteTester |
17
|
|
|
{ |
18
|
|
|
private $baseTester; |
19
|
|
|
private $observers; |
20
|
|
|
private $output; |
21
|
|
|
|
22
|
|
|
public function __construct( |
23
|
|
|
SuiteTester $baseTester, |
24
|
|
|
OutputInterface $output, |
25
|
|
|
array $observers = null |
26
|
|
|
) { |
27
|
|
|
$this->baseTester = $baseTester; |
28
|
|
|
$this->output = $output; |
29
|
|
|
$this->observers = new ErrorObservers($observers); |
|
|
|
|
30
|
|
|
} |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* Tests provided suite specifications. |
34
|
|
|
* |
35
|
|
|
* @param Environment $env |
36
|
|
|
* @param SpecificationIterator $iterator |
37
|
|
|
* @param Boolean $skip |
38
|
|
|
* |
39
|
|
|
* @return TestResult |
40
|
|
|
*/ |
41
|
|
|
public function test(Environment $env, SpecificationIterator $iterator, $skip) |
42
|
|
|
{ |
43
|
|
|
return $this->baseTester->test($env, $iterator, $skip); |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* Tears down suite after a test. |
48
|
|
|
* |
49
|
|
|
* @param Environment $env |
50
|
|
|
* @param SpecificationIterator $iterator |
51
|
|
|
* @param Boolean $skip |
52
|
|
|
* @param TestResult $result |
53
|
|
|
* |
54
|
|
|
* @return Teardown |
55
|
|
|
*/ |
56
|
|
|
public function tearDown(Environment $env, SpecificationIterator $iterator, $skip, TestResult $result) |
57
|
|
|
{ |
58
|
|
|
return $this->baseTester->tearDown($env, $iterator, $skip, $result); |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* Sets up suite for a test. |
63
|
|
|
* |
64
|
|
|
* @param Environment $env |
65
|
|
|
* @param SpecificationIterator $iterator |
66
|
|
|
* @param Boolean $skip |
67
|
|
|
* |
68
|
|
|
* @return Setup |
69
|
|
|
*/ |
70
|
|
|
public function setUp(Environment $env, SpecificationIterator $iterator, $skip) |
71
|
|
|
{ |
72
|
|
|
$this->turnOffErrorDisplayingIfNotVerbose(); |
73
|
|
|
$this->registerShutdownFunction(); |
74
|
|
|
|
75
|
|
|
return $this->baseTester->setUp($env, $iterator, $skip); |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
private function turnOffErrorDisplayingIfNotVerbose() |
79
|
|
|
{ |
80
|
|
|
if ($this->output->getVerbosity() == OutputPrinter::VERBOSITY_NORMAL) { |
|
|
|
|
81
|
|
|
error_reporting(E_ALL & ~E_ERROR); |
82
|
|
|
} |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
private function registerShutdownFunction() |
86
|
|
|
{ |
87
|
|
|
register_shutdown_function(function () { |
88
|
|
|
if ($error = error_get_last()) { |
89
|
|
|
|
90
|
|
|
$errorMessages = [ |
91
|
|
|
sprintf('The error "%s"', $error['message']), |
92
|
|
|
sprintf('occurred in file %s', $error['file']), |
93
|
|
|
sprintf('at line %s', $error['line']), |
94
|
|
|
]; |
95
|
|
|
|
96
|
|
|
$formatter = new FormatterHelper(); |
97
|
|
|
$formattedBlock = $formatter->formatBlock($errorMessages, 'error', true); |
98
|
|
|
$this->output->writeln(''); |
99
|
|
|
$this->output->writeln($formattedBlock); |
100
|
|
|
$this->output->writeln(''); |
101
|
|
|
|
102
|
|
|
foreach ($this->observers as $observer) { |
103
|
|
|
$observer->notify($error); |
104
|
|
|
} |
105
|
|
|
} |
106
|
|
|
}); |
107
|
|
|
} |
108
|
|
|
} |
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.