Completed
Push — master ( 25d5ca...cee559 )
by Nicolas
04:59
created

ArrangeListener::getAnnotationReader()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 14
ccs 0
cts 8
cp 0
rs 9.4285
cc 2
eloc 7
nc 2
nop 0
crap 6
1
<?php
2
3
namespace Nikoms\PhpUnit\Listener;
4
5
use Doctrine\Common\Annotations\AnnotationReader;
6
use Doctrine\Common\Annotations\AnnotationRegistry;
7
use Doctrine\Common\Annotations\DocParser;
8
use Nikoms\PhpUnit\Annotation\Arrange;
9
use PHPUnit_Framework_Test;
10
11
class ArrangeListener extends \PHPUnit_Framework_BaseTestListener
12
{
13
    /**
14
     * @var array
15
     */
16
    private $ignoredAnnotationNames;
17
18
    /**
19
     * ArrangeListener constructor.
20
     * @param array $ignoredAnnotationNames
21
     */
22
    public function __construct(array $ignoredAnnotationNames = null)
23
    {
24
        AnnotationRegistry::registerFile(__DIR__.'/../Annotation/Arrange.php');
25
26
        //For old AnnotationReader (<=1.2.7)
27
        if ($ignoredAnnotationNames === null) {
28
            $ignoredAnnotationNames = array(
29
                'author',
30
                'after',
31
                'afterClass',
32
                'backupGlobals',
33
                'backupStaticAttributes',
34
                'before',
35
                'beforeClass',
36
                'codeCoverageIgnore',
37
                'codeCoverageIgnoreStart',
38
                'codeCoverageIgnoreEnd',
39
                'covers',
40
                'coversDefaultClass',
41
                'coversNothing',
42
                'dataProvider',
43
                'depends',
44
                'expectedException',
45
                'expectedExceptionCode',
46
                'expectedExceptionMessage',
47
                'expectedExceptionMessageRegExp',
48
                'group',
49
                'large',
50
                'medium',
51
                'preserveGlobalState',
52
                'requires',
53
                'runTestsInSeparateProcesses',
54
                'runInSeparateProcess',
55
                'small',
56
                'test',
57
                'testdox',
58
                'ticket',
59
                'uses',
60
            );
61
        }
62
        $this->ignoredAnnotationNames = $ignoredAnnotationNames;
63
    }
64
65
    /**
66
     * @param  PHPUnit_Framework_Test $test
67
     */
68
    public function startTest(PHPUnit_Framework_Test $test)
69
    {
70
        if ($test instanceof \PHPUnit_Framework_TestCase) {
71
            $this->setUpContext($test);
72
        }
73
    }
74
75
    /**
76
     * @param \PHPUnit_Framework_TestCase $testCase
77
     */
78
    private function setUpContext(\PHPUnit_Framework_TestCase $testCase)
79
    {
80
        $testMethodArguments = array();
81
        $reflectionMethod = new \ReflectionMethod($testCase, $testCase->getName(false));
82
83
        $annotationReader = $this->getAnnotationReader();
84
        $annotations = $annotationReader->getMethodAnnotations($reflectionMethod);
85
        foreach ($annotations as $annotation) {
86
            if ($annotation instanceof Arrange) {
87
                $arrangeOutput = $this->runAnnotations($testCase, $annotation);
88
                if ($arrangeOutput !== null) {
89
                    $testMethodArguments[] = $arrangeOutput;
90
                }
91
            }
92
        }
93
        $testCase->setDependencyInput($testMethodArguments);
94
    }
95
96
    /**
97
     * @param \PHPUnit_Framework_TestCase $testCase
98
     * @param Arrange $annotation
99
     * @return mixed
100
     */
101
    private function runAnnotations(\PHPUnit_Framework_TestCase $testCase, Arrange $annotation)
102
    {
103
        $dataProviderArguments = $testCase->readAttribute($testCase, 'data');
104
        $arrangeOutput = null;
105
        foreach ($annotation->getMethods() as $method => $annotationArguments) {
106
            if (method_exists($testCase, $method)) {
107
                $givenArgument = array();
108
109
                if ($arrangeOutput !== null) {
110
                    $givenArgument[] = $arrangeOutput;
111
                }
112
113
                if (!empty($dataProviderArguments)) {
114
                    $givenArgument = array_merge($givenArgument, $dataProviderArguments);
115
                }
116
117
                if ($annotationArguments !== null) {
118
                    $givenArgument[] = $annotationArguments;
119
                }
120
                $arrangeOutput = call_user_func_array(array($testCase, $method), $givenArgument);
121
            } else {
122
                trigger_error(
123
                    sprintf('Error on @Arrange annotation: Impossible to call "%s" method', $method),
124
                    E_USER_NOTICE
125
                );
126
            }
127
        }
128
129
        return $arrangeOutput;
130
    }
131
132
    /**
133
     * @return AnnotationReader
134
     */
135
    private function getAnnotationReader()
136
    {
137
        //For new (>1.2.7) version of AnnotationReader, we can give a DocParser since a3c2928912eeb5dc5678352f22c378173def16b6
138
        $parser = new DocParser();
139
        $parser->setIgnoreNotImportedAnnotations(true);
140
        $annotationReader = new AnnotationReader($parser);
0 ignored issues
show
Unused Code introduced by
The call to AnnotationReader::__construct() has too many arguments starting with $parser.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
141
142
        //For old version of AnnotationReader (<=1.2.7) , we have to specify manually all ignored annotations
143
        foreach ($this->ignoredAnnotationNames as $ignoredAnnotationName) {
144
            $annotationReader->addGlobalIgnoredName($ignoredAnnotationName);
145
        }
146
147
        return $annotationReader;
148
    }
149
}
150