Complex classes like PropertyTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use PropertyTest, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 30 | class PropertyTest extends PHPUnit_Framework_TestCase { |
||
| 31 | |||
| 32 | private function getNewEmpty() { |
||
| 35 | |||
| 36 | public function testConstructorWithAllParameters() { |
||
| 37 | $property = new Property( |
||
| 38 | new PropertyId( 'P42' ), |
||
| 39 | new Fingerprint(), |
||
| 40 | 'string', |
||
| 41 | new StatementList() |
||
| 42 | ); |
||
| 43 | $this->assertInstanceOf( 'Wikibase\DataModel\Entity\Property', $property ); |
||
| 44 | $this->assertEquals( new PropertyId( 'P42' ), $property->getId() ); |
||
| 45 | $this->assertEquals( new Fingerprint(), $property->getFingerprint() ); |
||
| 46 | $this->assertEquals( 'string', $property->getDataTypeId() ); |
||
| 47 | $this->assertEquals( new StatementList(), $property->getStatements() ); |
||
| 48 | } |
||
| 49 | |||
| 50 | public function testConstructorWithMinimalParameters() { |
||
| 51 | $property = new Property( null, null, '' ); |
||
| 52 | $this->assertInstanceOf( 'Wikibase\DataModel\Entity\Property', $property ); |
||
| 53 | $this->assertNull( $property->getId() ); |
||
| 54 | $this->assertEquals( new Fingerprint(), $property->getFingerprint() ); |
||
| 55 | $this->assertEquals( '', $property->getDataTypeId() ); |
||
| 56 | $this->assertEquals( new StatementList(), $property->getStatements() ); |
||
| 57 | } |
||
| 58 | |||
| 59 | /** |
||
| 60 | * @expectedException InvalidArgumentException |
||
| 61 | */ |
||
| 62 | public function testGivenInvalidType_ConstructorThrowsException() { |
||
| 63 | new Property( null, null, null ); |
||
| 64 | } |
||
| 65 | |||
| 66 | public function testNewFromType() { |
||
| 67 | $property = Property::newFromType( 'string' ); |
||
| 68 | $this->assertInstanceOf( 'Wikibase\DataModel\Entity\Property', $property ); |
||
| 69 | $this->assertEquals( 'string', $property->getDataTypeId() ); |
||
| 70 | } |
||
| 71 | |||
| 72 | public function testSetAndGetDataTypeId() { |
||
| 73 | $property = Property::newFromType( 'string' ); |
||
| 74 | |||
| 75 | foreach ( array( 'string', 'foobar', 'nyan', 'string' ) as $typeId ) { |
||
| 76 | $property->setDataTypeId( $typeId ); |
||
| 77 | $this->assertEquals( $typeId, $property->getDataTypeId() ); |
||
| 78 | } |
||
| 79 | } |
||
| 80 | |||
| 81 | public function testWhenIdSetWithNumber_GetIdReturnsPropertyId() { |
||
| 82 | $property = Property::newFromType( 'string' ); |
||
| 83 | $property->setId( 42 ); |
||
| 84 | |||
| 85 | $this->assertHasCorrectIdType( $property ); |
||
| 86 | } |
||
| 87 | |||
| 88 | protected function assertHasCorrectIdType( Property $property ) { |
||
| 89 | $this->assertInstanceOf( 'Wikibase\DataModel\Entity\PropertyId', $property->getId() ); |
||
| 90 | } |
||
| 91 | |||
| 92 | public function testWhenIdSetWithPropertyId_GetIdReturnsPropertyId() { |
||
| 93 | $property = Property::newFromType( 'string' ); |
||
| 94 | $property->setId( new PropertyId( 'P42' ) ); |
||
| 95 | |||
| 96 | $this->assertHasCorrectIdType( $property ); |
||
| 97 | } |
||
| 98 | |||
| 99 | public function testPropertyWithTypeIsEmpty() { |
||
| 100 | $this->assertTrue( Property::newFromType( 'string' )->isEmpty() ); |
||
| 101 | } |
||
| 102 | |||
| 103 | public function testPropertyWithIdIsEmpty() { |
||
| 104 | $property = Property::newFromType( 'string' ); |
||
| 105 | $property->setId( 1337 ); |
||
| 106 | $this->assertTrue( $property->isEmpty() ); |
||
| 107 | } |
||
| 108 | |||
| 109 | public function testPropertyWithFingerprintIsNotEmpty() { |
||
| 110 | $property = Property::newFromType( 'string' ); |
||
| 111 | $property->getFingerprint()->setAliasGroup( 'en', array( 'foo' ) ); |
||
| 112 | $this->assertFalse( $property->isEmpty() ); |
||
| 113 | } |
||
| 114 | |||
| 115 | public function testGetStatementsReturnsEmptyListForEmptyProperty() { |
||
| 120 | |||
| 121 | public function testSetAndGetStatements() { |
||
| 129 | |||
| 130 | private function newNonEmptyStatementList() { |
||
| 131 | $statementList = new StatementList(); |
||
| 132 | $statementList->addNewStatement( new PropertyNoValueSnak( 42 ) ); |
||
| 133 | $statementList->addNewStatement( new PropertyNoValueSnak( 1337 ) ); |
||
| 134 | |||
| 135 | return $statementList; |
||
| 136 | } |
||
| 137 | |||
| 138 | public function equalsProvider() { |
||
| 139 | $firstProperty = Property::newFromType( 'string' ); |
||
| 140 | $firstProperty->setStatements( $this->newNonEmptyStatementList() ); |
||
| 141 | |||
| 142 | $secondProperty = Property::newFromType( 'string' ); |
||
| 143 | $secondProperty->setStatements( $this->newNonEmptyStatementList() ); |
||
| 144 | |||
| 145 | $secondPropertyWithId = $secondProperty->copy(); |
||
| 146 | $secondPropertyWithId->setId( 42 ); |
||
| 147 | |||
| 148 | $differentId = $secondPropertyWithId->copy(); |
||
| 149 | $differentId->setId( 43 ); |
||
| 150 | |||
| 151 | return array( |
||
| 152 | array( Property::newFromType( 'string' ), Property::newFromType( 'string' ) ), |
||
| 153 | array( $firstProperty, $secondProperty ), |
||
| 154 | array( $secondProperty, $secondPropertyWithId ), |
||
| 155 | array( $secondPropertyWithId, $differentId ), |
||
| 156 | ); |
||
| 157 | } |
||
| 158 | |||
| 159 | /** |
||
| 160 | * @dataProvider equalsProvider |
||
| 161 | */ |
||
| 162 | public function testEquals( Property $firstProperty, Property $secondProperty ) { |
||
| 163 | $this->assertTrue( $firstProperty->equals( $secondProperty ) ); |
||
| 164 | $this->assertTrue( $secondProperty->equals( $firstProperty ) ); |
||
| 165 | } |
||
| 166 | |||
| 167 | private function getBaseProperty() { |
||
| 168 | $property = Property::newFromType( 'string' ); |
||
| 169 | |||
| 170 | $property->setId( 42 ); |
||
| 171 | $property->getFingerprint()->setLabel( 'en', 'Same' ); |
||
| 172 | $property->getFingerprint()->setDescription( 'en', 'Same' ); |
||
| 173 | $property->getFingerprint()->setAliasGroup( 'en', array( 'Same' ) ); |
||
| 174 | $property->setStatements( $this->newNonEmptyStatementList() ); |
||
| 175 | |||
| 176 | return $property; |
||
| 177 | } |
||
| 178 | |||
| 179 | public function notEqualsProvider() { |
||
| 180 | $differentLabel = $this->getBaseProperty(); |
||
| 181 | $differentLabel->getFingerprint()->setLabel( 'en', 'Different' ); |
||
| 182 | |||
| 183 | $differentDescription = $this->getBaseProperty(); |
||
| 184 | $differentDescription->getFingerprint()->setDescription( 'en', 'Different' ); |
||
| 185 | |||
| 186 | $differentAlias = $this->getBaseProperty(); |
||
| 187 | $differentAlias->getFingerprint()->setAliasGroup( 'en', array( 'Different' ) ); |
||
| 188 | |||
| 189 | $differentStatement = $this->getBaseProperty(); |
||
| 190 | $differentStatement->setStatements( new StatementList() ); |
||
| 191 | |||
| 192 | $property = $this->getBaseProperty(); |
||
| 193 | |||
| 194 | return array( |
||
| 195 | 'empty' => array( $property, Property::newFromType( 'string' ) ), |
||
| 196 | 'label' => array( $property, $differentLabel ), |
||
| 197 | 'description' => array( $property, $differentDescription ), |
||
| 198 | 'alias' => array( $property, $differentAlias ), |
||
| 199 | 'dataType' => array( Property::newFromType( 'string' ), Property::newFromType( 'foo' ) ), |
||
| 200 | 'statement' => array( $property, $differentStatement ), |
||
| 201 | ); |
||
| 202 | } |
||
| 203 | |||
| 204 | /** |
||
| 205 | * @dataProvider notEqualsProvider |
||
| 206 | */ |
||
| 207 | public function testNotEquals( Property $firstProperty, Property $secondProperty ) { |
||
| 208 | $this->assertFalse( $firstProperty->equals( $secondProperty ) ); |
||
| 209 | $this->assertFalse( $secondProperty->equals( $firstProperty ) ); |
||
| 210 | } |
||
| 211 | |||
| 212 | public function testPropertyWithStatementsIsNotEmpty() { |
||
| 213 | $property = Property::newFromType( 'string' ); |
||
| 214 | $property->setStatements( $this->newNonEmptyStatementList() ); |
||
| 215 | |||
| 216 | $this->assertFalse( $property->isEmpty() ); |
||
| 217 | } |
||
| 218 | |||
| 219 | public function cloneProvider() { |
||
| 229 | |||
| 230 | /** |
||
| 231 | * @dataProvider cloneProvider |
||
| 232 | */ |
||
| 233 | public function testCloneIsEqualButNotIdentical( Property $original, Property $clone ) { |
||
| 250 | |||
| 251 | /** |
||
| 252 | * @dataProvider cloneProvider |
||
| 253 | */ |
||
| 254 | public function testOriginalDoesNotChangeWithClone( Property $original, Property $clone ) { |
||
| 276 | |||
| 277 | // Below are tests copied from EntityTest |
||
| 278 | |||
| 279 | public function labelProvider() { |
||
| 286 | |||
| 287 | /** |
||
| 288 | * @dataProvider labelProvider |
||
| 289 | * @param string $languageCode |
||
| 290 | * @param string $labelText |
||
| 291 | * @param string $moarText |
||
| 292 | */ |
||
| 293 | public function testSetLabel( $languageCode, $labelText, $moarText = 'ohi there' ) { |
||
| 304 | |||
| 305 | public function descriptionProvider() { |
||
| 312 | |||
| 313 | /** |
||
| 314 | * @dataProvider descriptionProvider |
||
| 315 | * @param string $languageCode |
||
| 316 | * @param string $description |
||
| 317 | * @param string $moarText |
||
| 318 | */ |
||
| 319 | public function testSetDescription( $languageCode, $description, $moarText = 'ohi there' ) { |
||
| 330 | |||
| 331 | public function aliasesProvider() { |
||
| 355 | |||
| 356 | /** |
||
| 357 | * @dataProvider aliasesProvider |
||
| 358 | */ |
||
| 359 | public function testSetAliases( array $aliasesLists ) { |
||
| 378 | |||
| 379 | /** |
||
| 380 | * @dataProvider aliasesProvider |
||
| 381 | */ |
||
| 382 | public function testSetEmptyAlias( array $aliasesLists ) { |
||
| 403 | |||
| 404 | public function instanceProvider() { |
||
| 439 | |||
| 440 | /** |
||
| 441 | * @dataProvider instanceProvider |
||
| 442 | * @param Property $entity |
||
| 443 | */ |
||
| 444 | public function testCopy( Property $entity ) { |
||
| 453 | |||
| 454 | public function testCopyRetainsLabels() { |
||
| 465 | |||
| 466 | /** |
||
| 467 | * @dataProvider instanceProvider |
||
| 468 | * @param Property $entity |
||
| 469 | */ |
||
| 470 | public function testSerialize( Property $entity ) { |
||
| 480 | |||
| 481 | public function testWhenNoStuffIsSet_getFingerprintReturnsEmptyFingerprint() { |
||
| 489 | |||
| 490 | public function testWhenLabelsAreSet_getFingerprintReturnsFingerprintWithLabels() { |
||
| 506 | |||
| 507 | public function testWhenTermsAreSet_getFingerprintReturnsFingerprintWithTerms() { |
||
| 529 | |||
| 530 | public function testGivenEmptyFingerprint_noTermsAreSet() { |
||
| 536 | |||
| 537 | public function testGivenEmptyFingerprint_existingTermsAreRemoved() { |
||
| 548 | |||
| 549 | public function testWhenSettingFingerprint_getFingerprintReturnsIt() { |
||
| 568 | |||
| 569 | public function testGetLabels() { |
||
| 580 | |||
| 581 | public function testGetDescriptions() { |
||
| 592 | |||
| 593 | public function testGetAliasGroups() { |
||
| 604 | |||
| 605 | public function testGetLabels_sameListAsFingerprint() { |
||
| 613 | |||
| 614 | public function testGetDescriptions_sameListAsFingerprint() { |
||
| 622 | |||
| 623 | public function testGetAliasGroups_sameListAsFingerprint() { |
||
| 631 | |||
| 632 | } |
||
| 633 |