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 |
||
31 | final class ResourceTest extends TestCase |
||
32 | { |
||
33 | /** |
||
34 | * @expectedException \Sensorario\Resources\Exceptions\UndefinedMethodException |
||
35 | * @expectedExceptionMessageRegExp #Method `.*::.*()` is not yet implemented# |
||
36 | */ |
||
37 | public function testExceptionIsThrownWhenNotYetImplementedMethodIsCalled() |
||
38 | { |
||
39 | $configurator = new Configurator( |
||
40 | 'empty_resource', |
||
41 | new Container([ |
||
42 | 'resources' => [ |
||
43 | 'empty_resource' => [ |
||
44 | 'constraints' => [], |
||
45 | ], |
||
46 | ], |
||
47 | ]) |
||
48 | ); |
||
49 | |||
50 | $resource = Resource::box([], $configurator); |
||
51 | |||
52 | $resource->notYetImplementedMethod(); |
||
53 | } |
||
54 | |||
55 | /** |
||
56 | * @expectedException Sensorario\Resources\Exceptions\NotAllowedKeyException |
||
57 | * @expectedExceptionMessageRegExp #Key `.*::.*` is not allowed# |
||
58 | */ |
||
59 | View Code Duplication | public function testNotAllowedFieldThroghRuntimeException() |
|
|
|||
60 | { |
||
61 | $configurator = new Configurator( |
||
62 | 'empty_resource', |
||
63 | new Container([ |
||
64 | 'resources' => [ |
||
65 | 'empty_resource' => [ |
||
66 | 'constraints' => [ |
||
67 | 'allowedValues' => [ |
||
68 | 'name', |
||
69 | 'surname', |
||
70 | ], |
||
71 | ], |
||
72 | ], |
||
73 | ], |
||
74 | ]) |
||
75 | ); |
||
76 | |||
77 | $resource = Resource::box([ |
||
78 | 'name' => 'Simone', |
||
79 | 'surname' => 'Gentili', |
||
80 | 'not allowed' => 'foo', |
||
81 | ], $configurator); |
||
82 | } |
||
83 | |||
84 | /** |
||
85 | * @expectedException Sensorario\Resources\Exceptions\PropertyException |
||
86 | * @expectedExceptionMessageRegExp #Property `.*::.*` is mandatory but not set# |
||
87 | */ |
||
88 | public function testMissingMandatoryFieldThroghRuntimeException() |
||
89 | { |
||
90 | $configurator = new Configurator( |
||
91 | 'empty_resource', |
||
92 | new Container([ |
||
93 | 'resources' => [ |
||
94 | 'empty_resource' => [ |
||
95 | 'constraints' => [ |
||
96 | 'mandatory' => [ |
||
97 | 'name', |
||
98 | ], |
||
99 | ], |
||
100 | ], |
||
101 | ], |
||
102 | ]) |
||
103 | ); |
||
104 | |||
105 | $resource = Resource::box([ |
||
106 | 'surname' => 'Gentili', |
||
107 | ], $configurator); |
||
108 | } |
||
109 | |||
110 | public function testMandatoryFieldsAreAuthomaticallyAllowed() |
||
111 | { |
||
112 | $configurator = new Configurator( |
||
113 | 'empty_resource', |
||
114 | new Container([ |
||
115 | 'resources' => [ |
||
116 | 'empty_resource' => [ |
||
117 | 'constraints' => [ |
||
118 | 'mandatory' => [ |
||
119 | 'name', |
||
120 | 'surname', |
||
121 | ], |
||
122 | ], |
||
123 | ], |
||
124 | ], |
||
125 | ]) |
||
126 | ); |
||
127 | |||
128 | $resource = Resource::box([ |
||
129 | 'name' => 'Simone', |
||
130 | 'surname' => 'Gentili', |
||
131 | ], $configurator); |
||
132 | |||
133 | $this->assertEquals( |
||
134 | 'Simone', |
||
135 | $resource->name() |
||
136 | ); |
||
137 | } |
||
138 | |||
139 | /** |
||
140 | * @expectedException Sensorario\Resources\Exceptions\PropertyNameEmptyException |
||
141 | * @expectedExceptionMessage Oops! Property name requested is empty string!! |
||
142 | */ |
||
143 | public function testExceptionMessageInCaseOfEmptyPropertyName() |
||
144 | { |
||
145 | $configurator = new Configurator( |
||
146 | 'empty_resource', |
||
147 | new Container([ |
||
148 | 'resources' => [ |
||
149 | 'empty_resource' => [ |
||
150 | 'constraints' => [ |
||
151 | 'mandatory' => [ |
||
152 | 'name', |
||
153 | 'surname', |
||
154 | ], |
||
155 | ], |
||
156 | ], |
||
157 | ], |
||
158 | ]) |
||
159 | ); |
||
160 | |||
161 | $resource = Resource::box([ |
||
162 | 'name' => 'Simone', |
||
163 | 'surname' => 'Gentili', |
||
164 | ], $configurator); |
||
165 | |||
166 | $this->assertEquals( |
||
167 | 'Simone', |
||
168 | $resource->get('') |
||
169 | ); |
||
170 | } |
||
171 | |||
172 | /** |
||
173 | * @expectedException Sensorario\Resources\Exceptions\FactoryMethodException |
||
174 | * @expectedExceptionMessageRegExp #Invalid factory method# |
||
175 | */ |
||
176 | public function testFactoryMethods() |
||
177 | { |
||
178 | Resource::invalidFactoryName(); |
||
179 | } |
||
180 | |||
181 | public function testCanHaveDefaultValues() |
||
182 | { |
||
183 | $configurator = new Configurator( |
||
184 | 'empty_resource', |
||
185 | new Container([ |
||
186 | 'resources' => [ |
||
187 | 'empty_resource' => [ |
||
188 | 'constraints' => [ |
||
189 | 'mandatory' => [ |
||
190 | 'name', |
||
191 | ], |
||
192 | 'defaults' => [ |
||
193 | 'name' => 'Firefox', |
||
194 | ], |
||
195 | ], |
||
196 | ], |
||
197 | ], |
||
198 | ]) |
||
199 | ); |
||
200 | |||
201 | $resource = Resource::box([], $configurator); |
||
202 | |||
203 | $this->assertEquals( |
||
204 | 'Firefox', |
||
205 | $resource->name() |
||
206 | ); |
||
207 | } |
||
208 | |||
209 | public function testPropertyExists() |
||
217 | |||
218 | /** @dataProvider propertiesProvider */ |
||
219 | public function testHasProperties($result, $properties) |
||
231 | |||
232 | public function propertiesProvider() |
||
239 | |||
240 | public function testAllowAccessToProperties() |
||
251 | |||
252 | public function testAllowAccessToPropertiesThroughDefaultValue() |
||
261 | |||
262 | /** |
||
263 | * @expectedException Sensorario\Resources\Exceptions\NoValuesException |
||
264 | */ |
||
265 | public function testThroughExceptionWhenNoValuesProvided() |
||
270 | |||
271 | /** |
||
272 | * @expectedException Sensorario\Resources\Exceptions\AttributeTypeException |
||
273 | * @expectedExceptionMessageRegExp #Attribute `.*` must be of type `array`# |
||
274 | */ |
||
275 | public function testPropertyCouldBeAScalar() |
||
281 | |||
282 | /** |
||
283 | * @expectedException Sensorario\Resources\Exceptions\NotObjectTypeFoundException |
||
284 | * @expectedExceptionMessageRegExp #Attribute `.*` must be an object of type DateTime# |
||
285 | */ |
||
286 | public function testPropertyCouldBeTheRightnObject() |
||
292 | |||
293 | public function testPropertiesAccessor() |
||
323 | |||
324 | /** |
||
325 | * @expectedException Sensorario\Resources\Exceptions\PropertyNotSetException |
||
326 | * @expectedExceptionMessageRegExp #Property `.*::.*` is mandatory but not set# |
||
327 | */ |
||
328 | public function testWhenCondition() |
||
335 | |||
336 | public function testResourcesComposition() |
||
337 | { |
||
338 | $composition = ComposedResource::box([ |
||
339 | 'credentials' => Foo::box([ |
||
340 | 'name' => 'Sam' |
||
341 | ]), |
||
342 | ]); |
||
352 | |||
353 | /** |
||
354 | * @expectedException Sensorario\Resources\Exceptions\PropertyException |
||
355 | * @expectedExceptionMessageRegExp #When property `.*` has value `.*` also `.*` is mandatory# |
||
356 | */ |
||
357 | public function testMandatoryValuesWhenPropertyAssumeAValue() |
||
363 | |||
364 | /** |
||
365 | * @expectedException Sensorario\Resources\Exceptions\PropertyWithoutRuleException |
||
366 | * @expectedExceptionMessageRegExp #When property `.*` is an object class, must be defined in Resources::rules()# |
||
367 | */ |
||
368 | public function testAnExceptionIsThrownIfAPropertyIsAnObjectButClassInNotDefinedInRuleMethod() |
||
374 | |||
375 | public function testDefaultValuesTwo() |
||
407 | |||
408 | public function testDefaultValues() |
||
438 | |||
439 | public function testResourceShouldBeCreatedViaContainer() |
||
461 | |||
462 | /** |
||
463 | * @expectedException Sensorario\Resources\Exceptions\PropertyNotSetException |
||
464 | * @expectedExceptionMessageRegExp #Property `.*::.*` is mandatory but not set# |
||
465 | */ |
||
466 | View Code Duplication | public function testDependentMandatoryProperties() |
|
502 | |||
503 | View Code Duplication | public function testMandatoryConstraintsAreAutomaticallyAllowed() |
|
520 | |||
521 | /** |
||
522 | * @expectedException Sensorario\Resources\Exceptions\UnexpectedValueException |
||
523 | * @expectedExceptionMessageRegExp #Value `.*` is not allowed for key `.*`. Allowed values are:# |
||
524 | */ |
||
525 | View Code Duplication | public function testAllowedValues() |
|
553 | |||
554 | public function testRewriteRulesWithCondition() |
||
606 | |||
607 | /** |
||
608 | * @expectedException Sensorario\Resources\Exceptions\OutOfRangeException |
||
609 | * @expectedExceptionMessageRegExp #Value `.*` is out of range: `.*`.# |
||
610 | */ |
||
611 | View Code Duplication | public function testAcceptRangeOfValues() |
|
639 | |||
640 | public function testAllResourcesInheritGlobalAllowingConfiguration() |
||
680 | |||
681 | /** |
||
682 | * @expectedException Sensorario\Resources\Exceptions\PropertyException |
||
683 | */ |
||
684 | View Code Duplication | public function testHasMandatoryPropertiesWhenAnotherOneHasAParticularValue() |
|
719 | |||
720 | /** |
||
721 | * @expectedException Sensorario\Resources\Exceptions\EmailException |
||
722 | */ |
||
723 | public function testEmailValidationFails() |
||
749 | |||
750 | /** |
||
751 | * @expectedException Sensorario\Resources\Exceptions\WrongPropertyValueException |
||
752 | * @expectedExceptionMessageRegExp #Property .* must be an integer!# |
||
753 | */ |
||
754 | public function testIntegersCanBeDefinedWithNumberRule() |
||
776 | |||
777 | public function testEmailValidation() |
||
808 | |||
809 | /** @dataProvider rules */ |
||
810 | View Code Duplication | public function testRulesKnowsIfRuleIsDefinedOrNot($expectation, $ruleName) |
|
841 | |||
842 | public function rules() |
||
849 | |||
850 | View Code Duplication | public function testProvideRule() |
|
883 | |||
884 | /** |
||
885 | * @expectedException Sensorario\Resources\Exceptions\PropertyWithoutRuleException |
||
886 | * @expectedExceptionMessage Property date is an object but is not defined in rules |
||
887 | */ |
||
888 | public function testUndefinedObject() |
||
894 | |||
895 | /** |
||
896 | * @expectedException \Sensorario\Resources\Exceptions\InvalidCustomValidatorException |
||
897 | * @expectedExceptionMessage Oops! `custom-validator` custom validator is not available. Only email is. |
||
898 | */ |
||
899 | View Code Duplication | public function testDenyCustomValidatorDifferentFromEmail() |
|
925 | |||
926 | } |
||
927 |
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.