Completed
Push — master ( 70f161...72dc5f )
by Julian
10s
created

Reader::init()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 8
cts 8
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 0
crap 2
1
<?php
2
namespace ParaTest\Logging\JUnit;
3
4
use ParaTest\Logging\MetaProvider;
5
6
class Reader extends MetaProvider
7
{
8
    /**
9
     * @var \SimpleXMLElement
10
     */
11
    protected $xml;
12
13
    /**
14
     * @var bool
15
     */
16
    protected $isSingle = false;
17
18
    /**
19
     * @var array
20
     */
21
    protected $suites = array();
22
23
    /**
24
     * @var string
25
     */
26
    protected $logFile;
27
28
    /**
29
     * @var array
30
     */
31
    protected static $defaultSuite = array('name' => '',
32
                                           'file' => '',
33
                                           'tests' => 0,
34
                                           'assertions' => 0,
35
                                           'failures' => 0,
36
                                           'errors' => 0,
37
                                           'time' => 0);
38
39 54
    public function __construct($logFile)
40
    {
41 54
        if (!file_exists($logFile)) {
42 1
            throw new \InvalidArgumentException("Log file $logFile does not exist");
43
        }
44
45 54
        $this->logFile = $logFile;
46 54
        if (filesize($logFile) == 0) {
47
            throw new \InvalidArgumentException("Log file $logFile is empty. This means a PHPUnit process has crashed.");
48
        }
49 54
        $logFileContents = file_get_contents($this->logFile);
50 54
        $this->xml = new \SimpleXMLElement($logFileContents);
51 54
        $this->init();
52 54
    }
53
54
    /**
55
     * Returns whether or not this reader contains only
56
     * a single suite
57
     *
58
     * @return bool
59
     */
60 2
    public function isSingleSuite()
61
    {
62 2
        return $this->isSingle;
63
    }
64
65
    /**
66
     * Return the Reader's collection
67
     * of test suites
68
     *
69
     * @return array
70
     */
71 15
    public function getSuites()
72
    {
73 15
        return $this->suites;
74
    }
75
76
    /**
77
     * Return an array that contains
78
     * each suite's instant feedback. Since
79
     * logs do not contain skipped or incomplete
80
     * tests this array will contain any number of the following
81
     * characters: .,F,E
82
     *
83
     * @return array
84
     */
85 12
    public function getFeedback()
86
    {
87 12
        $feedback = array();
88 12
        $suites = $this->isSingle ? $this->suites : $this->suites[0]->suites;
89 12
        foreach ($suites as $suite) {
90 12
            foreach ($suite->cases as $case) {
91 12
                if ($case->failures) {
92 8
                    $feedback[] = 'F';
93 12
                } elseif ($case->errors) {
94 9
                    $feedback[] = 'E';
95 9
                } else {
96 12
                    $feedback[] = '.';
97
                }
98 12
            }
99 12
        }
100 12
        return $feedback;
101
    }
102
103
    /**
104
     * Remove the JUnit xml file
105
     */
106 3
    public function removeLog()
107
    {
108 3
        unlink($this->logFile);
109 3
    }
110
111
    /**
112
     * Initialize the suite collection
113
     * from the JUnit xml document
114
     */
115 54
    protected function init()
116 54
    {
117 54
        $this->initSuite();
118 54
        $cases = $this->getCaseNodes();
119 54
        foreach ($cases as $file => $nodeArray) {
120 54
            $this->initSuiteFromCases($nodeArray);
121 54
        }
122 54
    }
123
124
    /**
125
     * Uses an array of testcase nodes to build a suite
126
     * @param array $nodeArray an array of SimpleXMLElement nodes representing testcase elements
127
     */
128 54
    protected function initSuiteFromCases($nodeArray)
129
    {
130 54
        $testCases = array();
131 54
        $properties = $this->caseNodesToSuiteProperties($nodeArray, $testCases);
132 54
        if (!$this->isSingle) {
133 44
            $this->addSuite($properties, $testCases);
134 44
        } else {
135 50
            $this->suites[0]->cases = $testCases;
136
        }
137 54
    }
138
139
    /**
140
     * Creates and adds a TestSuite based on the given
141
     * suite properties and collection of test cases
142
     *
143
     * @param $properties
144
     * @param $testCases
145
     */
146 44
    protected function addSuite($properties, $testCases)
147
    {
148 44
        $suite = TestSuite::suiteFromArray($properties);
149 44
        $suite->cases = $testCases;
150 44
        $this->suites[0]->suites[] = $suite;
151 44
    }
152
153
    /**
154
     * Fold an array of testcase nodes into a suite array
155
     * @param array $nodeArray an array of testcase nodes
156
     * @param array $testCases an array reference. Individual testcases will be placed here.
157
     * @return mixed
158
     */
159 54
    protected function caseNodesToSuiteProperties($nodeArray, &$testCases = array())
160
    {
161 54
        $cb = array('ParaTest\\Logging\\JUnit\\TestCase', 'caseFromNode');
162
        return array_reduce($nodeArray, function ($result, $c) use (&$testCases, $cb) {
163 54
            $testCases[] = call_user_func_array($cb, array($c));
164 54
            $result['name'] = (string)$c['class'];
165 54
            $result['file'] = (string)$c['file'];
166 54
            $result['tests'] = $result['tests'] + 1;
167 54
            $result['assertions'] += (int)$c['assertions'];
168 54
            $result['failures'] += sizeof($c->xpath('failure'));
169 54
            $result['errors'] += sizeof($c->xpath('error'));
170 54
            $result['time'] += floatval($c['time']);
171 54
            return $result;
172 54
        }, static::$defaultSuite);
173
    }
174
175
    /**
176
     * Return a collection of testcase nodes
177
     * from the xml document
178
     *
179
     * @return array
180
     */
181 54
    protected function getCaseNodes()
182
    {
183 54
        $caseNodes = $this->xml->xpath('//testcase');
184 54
        $cases = array();
185 54
        while (list( , $node) = each($caseNodes)) {
186 54
            $case = $node;
0 ignored issues
show
Unused Code introduced by
$case is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
187 54
            if (!isset($cases[(string)$node['file']])) {
188 54
                $cases[(string)$node['file']] = array();
189 54
            }
190 54
            $cases[(string)$node['file']][] = $node;
191 54
        }
192 54
        return $cases;
193
    }
194
195
    /**
196
     * Determine if this reader is a single suite
197
     * and initialize the suite collection with the first
198
     * suite
199
     */
200 54
    protected function initSuite()
201
    {
202 54
        $suiteNodes = $this->xml->xpath('/testsuites/testsuite/testsuite');
203 54
        $this->isSingle = sizeof($suiteNodes) === 0;
204 54
        $node = current($this->xml->xpath("/testsuites/testsuite"));
205
206 54
        if ($node !== false) {
207 54
            $this->suites[] = TestSuite::suiteFromNode($node);
208 54
        } else {
209 21
            $this->suites[] = TestSuite::suiteFromArray(self::$defaultSuite);
210
        }
211 54
    }
212
}
213