Test Failed
Push — feature/init ( 0ce752...042f0d )
by Yo
02:11
created

TestsStrategyListener   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 90
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 16
c 1
b 0
f 0
lcom 0
cbo 5
dl 0
loc 90
ccs 55
cts 55
cp 1
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A addRiskyTest() 0 20 3
B removeCoverageFor() 0 20 7
B processEvent() 0 31 6
1
<?php
2
namespace Yoanm\PhpUnitExtended\Listener;
3
4
/**
5
 * @see https://github.com/yoanm/Readme/blob/master/TESTS_STRATEGY.md#rules-strict-mode-fails-if-risky-tests
6
 * Will convert a risky test regarding following option to failure
7
 *  =>phpunit process will return a failed result at end
8
 *
9
 * List of managed options :
10
 * - beStrictAboutOutputDuringTests="true" / --report-useless-tests
11
 * - checkForUnintentionallyCoveredCode="true" / --strict-coverage
12
 *      => in case forceCoversAnnotation is used, and the test execute code that are not listed by
13
 *          a @covers or @uses annotations
14
 * - beStrictAboutTestsThatDoNotTestAnything="true" / --disallow-test-output
15
 * - beStrictAboutChangesToGlobalState="true" / --strict-global-state
16
 *
17
 * @see https://github.com/yoanm/Readme/blob/master/strategy/tests/README.md#rules-real-coverage-risky-tests
18
 * Risky tests will be managed as not executed tests and so, code coverage generated by them will be removed
19
 *  => Allow failure based on coverage
20
 */
21
class TestsStrategyListener extends \PHPUnit_Framework_BaseTestListener
22
{
23
    /**
24
     * @param \PHPUnit_Framework_Test $test
25
     * @param \Exception              $e
26
     * @param float                   $time
27
     */
28 9
    public function addRiskyTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
29
    {
30
        /* Must be PHPUnit_Framework_TestCase instance to have access to "getTestResultObject" method */
31 9
        if ($test instanceof \PHPUnit_Framework_TestCase) {
32 9
            $reason = $this->processEvent($test, $e);
33 9
            if (null !== $reason) {
34 9
                $test->getTestResultObject()->addFailure(
35
                    $test,
36 9
                    new \PHPUnit_Framework_AssertionFailedError(
37 4
                        sprintf(
38
                            "Strict mode - %s :\n%s",
39 4
                            $reason,
40
                            $e->getMessage()
41 4
                        )
42
                    ),
43 5
                    $time
44 1
                );
45 1
            }
46 4
        }
47 4
    }
48
49 1
    /**
50 4
     * @param \PHPUnit_Framework_TestCase $test
51
     */
52
    protected function removeCoverageFor(\PHPUnit_Framework_TestCase $test)
53 1
    {
54 3
        $coverage = $test->getTestResultObject()->getCodeCoverage();
55
        if (null !== $coverage) {
56 1
            $id = sprintf('%s::%s', get_class($test), $test->getName());
57 1
            $data = $coverage->getData();
58 4
            foreach ($data as $fileName => $lineData) {
59 4
                foreach ($lineData as $lineNumber => $testIdList) {
60 9
                    if (is_array($testIdList)) {
61 8
                        foreach ($testIdList as $testIdKey => $testId) {
62 8
                            if ($id === $testId) {
63 8
                                unset($data[$fileName][$lineNumber][$testIdKey]);
64 8
                            }
65 8
                        }
66 8
                    }
67 8
                }
68 8
            }
69 8
            $coverage->setData($data);
70
        }
71 8
    }
72 8
73 9
    /**
74 9
     * @param \PHPUnit_Framework_TestCase $test
75
     * @param \Exception                  $e
76
     *
77
     * @return null|string
78
     */
79 4
    protected function processEvent(\PHPUnit_Framework_TestCase $test, \Exception $e)
80
    {
81 4
        $reason = null;
82 4
        switch (true) {
83 3
            /* beStrictAboutOutputDuringTests="true" */
84 3
            case $e instanceof \PHPUnit_Framework_OutputError:
85 3
                $reason = 'No output during test';
86 3
                /** Ack - remove coverage */
87 3
                $this->removeCoverageFor($test);
88 3
                /** END Ack */
89 3
                break;
90 3
            /* checkForUnintentionallyCoveredCode="true" */
91 3
            case $e instanceof \PHPUnit_Framework_UnintentionallyCoveredCodeError:
92 3
                $reason = 'Executed code must be defined with @covers and @uses annotations';
93 3
                break;
94 3
            default:
95 3
                if (preg_match('#\-\-\- Global variables before the test#', $e->getMessage())) {
96 3
                    /* beStrictAboutChangesToGlobalState="true" (no specific exception) for globals */
97 3
                    $reason = 'No global variable manipulation during test';
98 4
                } elseif (preg_match('#\-\-\- Static attributes before the test#', $e->getMessage())) {
99
                    /* beStrictAboutChangesToGlobalState="true" (no specific exception) for static var */
100
                    /* Only when beStrictAboutChangesToGlobalState="true" */
101
                    $reason = 'No static attribute manipulation during test';
102
                } elseif (preg_match('#This test did not perform any assertions#', $e->getMessage())) {
103
                    /* beStrictAboutTestsThatDoNotTestAnything="true" (no specific exception) */
104
                    $reason = 'No test that do not test anything';
105
                }
106
                break;
107
        }
108
        return $reason;
109
    }
110
}
111