Completed
Push — master ( 446f2e...32b2c3 )
by Nelson
11:26
created

VersionComponentTest   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 147
Duplicated Lines 10.2 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 15
loc 147
rs 10
c 0
b 0
f 0
wmc 10
lcom 1
cbo 4

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getTargetClassName() 0 4 1
A testParseMethod() 0 16 1
A testParseMethodWithInvalidArguments() 0 4 1
A testPerformsConversionToString() 15 15 1
A testPerformsImplicitConversionToString() 0 7 1
B testCanCheckIfVersionComponentIsInDefaultOrNullState() 0 62 5

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * PHP: Nelson Martell Library file
4
 *
5
 * Content:
6
 * - Test case for: [NelsonMartell] Version
7
 *
8
 * Copyright © 2016 Nelson Martell (http://nelson6e65.github.io)
9
 *
10
 * Licensed under The MIT License (MIT)
11
 * For full copyright and license information, please see the LICENSE
12
 * Redistributions of files must retain the above copyright notice.
13
 *
14
 * @copyright 2016 Nelson Martell
15
 * @link      http://nelson6e65.github.io/php_nml/
16
 * @since     v0.6.0
17
 * @license   http://www.opensource.org/licenses/mit-license.php The MIT License (MIT)
18
 * */
19
20
namespace NelsonMartell\Test\TestCase;
21
22
use NelsonMartell as NML;
23
use NelsonMartell\VersionComponent;
24
use NelsonMartell\Extensions\String;
25
use NelsonMartell\Test\DataProviders\VersionComponentTestProvider;
26
use \PHPUnit_Framework_TestCase as TestCase;
27
use \InvalidArgumentException;
28
29
/**
30
 *
31
 * @author Nelson Martell <[email protected]>
32
 * @internal
33
 * */
34
class VersionComponentTest extends TestCase
35
{
36
    use VersionComponentTestProvider;
37
38
    public function getTargetClassName()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
39
    {
40
        return VersionComponent::class;
41
    }
42
43
    /**
44
     * @testdox Performs conversion from compatible objects
45
     * @coverage VersionComponent::parse
46
     * @dataProvider goodVersionComponentParseMethodArgumentsProvider
47
     */
48
    public function testParseMethod(VersionComponent $expected, $obj)
49
    {
50
        $actual = VersionComponent::parse($obj);
51
52
        $message = String::format(
53
            '{class}::{method}({obj}); // {actual}',
54
            [
55
                'class'  => VersionComponent::class,
56
                'method' => 'isValid',
57
                'obj'    => static::export($obj),
58
                'actual' => static::export($actual)
59
            ]
60
        );
61
62
        $this->assertEquals($expected, $actual, $message);
63
    }
64
65
    /**
66
     * @testdox Informs if error occurs on parsing incompatible objects
67
     * @coverage VersionComponent::parse
68
     * @dataProvider badVersionComponentParseMethodArgumentsProvider
69
     * @expectedException \InvalidArgumentException
70
     */
71
    public function testParseMethodWithInvalidArguments($obj)
72
    {
73
        $actual = VersionComponent::parse($obj);
0 ignored issues
show
Unused Code introduced by
$actual 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...
74
    }
75
76
    /**
77
     * @coverage VersionComponent::__toString
78
     * @coverage VersionComponent::toString
79
     * @dataProvider versionComponentToStringMethodArgumentsProvider
80
     */
81 View Code Duplication
    public function testPerformsConversionToString($expected, VersionComponent $versionComponent)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
82
    {
83
        $actual = $versionComponent->toString();
84
85
        $message = String::format(
86
            '$versionComponent->{method}(); // {actual}',
87
            [
88
                'method' => 'toString',
89
                'actual' => static::export($actual)
90
            ]
91
        );
92
93
        $this->assertInternalType('string', $actual, $message.' # Should return a string #');
94
        $this->assertEquals($expected, $actual, $message);
95
    }
96
97
    /**
98
     * @coverage VersionComponent::__toString
99
     * @coverage VersionComponent::toString
100
     * @depends testPerformsConversionToString
101
     * @dataProvider versionComponentToStringMethodArgumentsProvider
102
     */
103
    public function testPerformsImplicitConversionToString($str, VersionComponent $obj)
104
    {
105
        $expected = "<VersionComponent>$str</VersionComponent>";
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $str instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
106
        $actual   = "<VersionComponent>$obj</VersionComponent>";
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $obj instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
107
108
        $this->assertEquals($expected, $actual);
109
    }
110
111
    /**
112
     * @coverage VersionComponent::isNull
113
     * @coverage VersionComponent::isNotNull
114
     * @coverage VersionComponent::isDefault
115
     * @coverage VersionComponent::isNotDefault
116
     * @dataProvider nullOrDefaultStatesProvider
117
     */
118
    public function testCanCheckIfVersionComponentIsInDefaultOrNullState($expected, VersionComponent $versionComponent)
119
    {
120
        static $format = '$versionComponent->{method}(); // {actual}';
121
122
        $actuals['isDefault']    = $versionComponent->isDefault();
0 ignored issues
show
Coding Style Comprehensibility introduced by
$actuals was never initialized. Although not strictly required by PHP, it is generally a good practice to add $actuals = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
123
        $actuals['isNotDefault'] = $versionComponent->isNotDefault();
124
        $actuals['isNull']       = $versionComponent->isNull();
125
        $actuals['isNotNull']    = $versionComponent->isNotNull();
126
127
        $messages = [];
128
129
        foreach ($actuals as $method => $actual) {
130
            $messages[$method] = String::format($format, ['method' => $method, 'actual' => static::export($actual)]);
131
        }
132
133
        foreach ($actuals as $method => $actual) {
134
            // Pre-tests for returning type
135
            $this->assertInternalType('boolean', $actual, $messages[$method].' # Should return a boolean #');
136
        }
137
138
        // Pre-tests for different values
139
        $this->assertNotEquals(
140
            $actuals['isDefault'],
141
            $actuals['isNotDefault'],
142
            $messages['isDefault'].PHP_EOL.$messages['isNotDefault']
143
        );
144
145
        $this->assertNotEquals(
146
            $actuals['isNull'],
147
            $actuals['isNotNull'],
148
            $messages['isNull'].PHP_EOL.$messages['isNotNull']
149
        );
150
151
152
        // Test expected
153
        if ($expected === 'default') {
154
            $this->assertTrue($actuals['isDefault'], $messages['isDefault']);
155
156
            // Can't be null AND default
157
            $this->assertNotEquals(
158
                $actuals['isNull'],
159
                $actuals['isDefault'],
160
                '#Can\'t be both, DEFAULT and NULL, at the same time'.PHP_EOL.
161
                $messages['isDefault'].PHP_EOL.
162
                $messages['isNull']
163
            );
164
        } elseif ($expected === 'null') {
165
            $this->assertTrue($actuals['isNull'], $messages['isNull']);
166
167
            // Can't be null AND default
168
            $this->assertNotEquals(
169
                $actuals['isNull'],
170
                $actuals['isDefault'],
171
                '#Can\'t be both, NULL and DEFAULT, at the same time'.PHP_EOL.
172
                $messages['isNull'].PHP_EOL.
173
                $messages['isDefault']
174
            );
175
        } else {
176
            $this->assertTrue($actuals['isNotDefault'], $messages['isNotDefault']);
177
            $this->assertTrue($actuals['isNotNull'], $messages['isNotNull']);
178
        }
179
    }
180
}
0 ignored issues
show
Coding Style introduced by
As per coding style, files should not end with a newline character.

This check marks files that end in a newline character, i.e. an empy line.

Loading history...
181