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:
Complex classes like PaymentSlipTest 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 PaymentSlipTest, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
20 | class PaymentSlipTest extends PaymentSlipTestCase |
||
21 | { |
||
22 | /** |
||
23 | * Setup a slip to test and some default and set attributes to test |
||
24 | * |
||
25 | * @return void |
||
26 | */ |
||
27 | protected function setUp() |
||
60 | |||
61 | /** |
||
62 | * Tests the constructor when setting the position |
||
63 | * |
||
64 | * @return void |
||
65 | * @covers ::__construct |
||
66 | */ |
||
67 | public function testConstructSetPosition() |
||
89 | |||
90 | /** |
||
91 | * Tests the getPaymentSlipData method |
||
92 | * |
||
93 | * @return void |
||
94 | * @covers ::getPaymentSlipData |
||
95 | */ |
||
96 | public function testGetPaymentSlipDataIsInstanceOf() |
||
103 | |||
104 | /** |
||
105 | * Tests setting the slip position |
||
106 | * |
||
107 | * @return void |
||
108 | * @covers ::setSlipPosition |
||
109 | * @covers ::setSlipPosX |
||
110 | * @covers ::setSlipPosY |
||
111 | * @covers ::getSlipPosX |
||
112 | * @covers ::getSlipPosY |
||
113 | */ |
||
114 | View Code Duplication | public function testSetSlipPosition() |
|
126 | |||
127 | /** |
||
128 | * Tests the setSlipPosition method with an invalid first parameter |
||
129 | * |
||
130 | * @return void |
||
131 | * @expectedException \InvalidArgumentException |
||
132 | * @expectedExceptionMessage $slipPosX is neither an integer nor a float. |
||
133 | * @covers ::setSlipPosition |
||
134 | * @covers ::isIntOrFloat |
||
135 | */ |
||
136 | public function testSetSlipPositionFirstParameterInvalid() |
||
140 | |||
141 | /** |
||
142 | * Tests the setSlipPosition method with an invalid second parameter |
||
143 | * |
||
144 | * @return void |
||
145 | * @expectedException \InvalidArgumentException |
||
146 | * @expectedExceptionMessage $slipPosY is neither an integer nor a float. |
||
147 | * @covers ::setSlipPosition |
||
148 | * @covers ::isIntOrFloat |
||
149 | */ |
||
150 | public function testSetSlipPositionSecondParameterInvalid() |
||
154 | |||
155 | /** |
||
156 | * Tests setting the slip size |
||
157 | * |
||
158 | * @return void |
||
159 | * @covers ::setSlipSize |
||
160 | * @covers ::setSlipWidth |
||
161 | * @covers ::setSlipHeight |
||
162 | * @covers ::getSlipWidth |
||
163 | * @covers ::getSlipHeight |
||
164 | */ |
||
165 | View Code Duplication | public function testSetSlipSize() |
|
176 | |||
177 | /** |
||
178 | * Tests the setSlipSize method with an invalid first parameter |
||
179 | * |
||
180 | * @return void |
||
181 | * @expectedException \InvalidArgumentException |
||
182 | * @expectedExceptionMessage $slipWidth is neither an integer nor a float. |
||
183 | * @covers ::setSlipSize |
||
184 | * @covers ::isIntOrFloat |
||
185 | */ |
||
186 | public function testSetSlipSizeFirstParameterInvalid() |
||
190 | |||
191 | /** |
||
192 | * Tests the setSlipSize method with an invalid second parameter |
||
193 | * |
||
194 | * @return void |
||
195 | * @expectedException \InvalidArgumentException |
||
196 | * @expectedExceptionMessage $slipHeight is neither an integer nor a float. |
||
197 | * @covers ::setSlipSize |
||
198 | * @covers ::isIntOrFloat |
||
199 | */ |
||
200 | public function testSetSlipSizeSecondParameterInvalid() |
||
204 | |||
205 | /** |
||
206 | * Tests setting the slip background |
||
207 | * |
||
208 | * @return void |
||
209 | * @covers ::setSlipBackground |
||
210 | * @covers ::getSlipBackground |
||
211 | */ |
||
212 | public function testSetSlipBackground() |
||
223 | |||
224 | /** |
||
225 | * Tests the default attributes of the left bank element |
||
226 | * |
||
227 | * @return void |
||
228 | * @covers ::setDefaults |
||
229 | */ |
||
230 | View Code Duplication | public function testBankLeftAttrDefaultValues() |
|
243 | |||
244 | /** |
||
245 | * Tests the default attributes of the right bank element |
||
246 | * |
||
247 | * @return void |
||
248 | * @covers ::setDefaults |
||
249 | */ |
||
250 | View Code Duplication | public function testBankRightAttrDefaultValues() |
|
263 | |||
264 | /** |
||
265 | * Tests the default attributes of the left recipient element |
||
266 | * |
||
267 | * @return void |
||
268 | * @covers ::setDefaults |
||
269 | */ |
||
270 | View Code Duplication | public function testRecipientLeftAttrDefaultValues() |
|
283 | |||
284 | /** |
||
285 | * Tests the default attributes of the right recipient element |
||
286 | * |
||
287 | * @return void |
||
288 | * @covers ::setDefaults |
||
289 | */ |
||
290 | View Code Duplication | public function testRecipientRightAttrDefaultValues() |
|
303 | |||
304 | /** |
||
305 | * Tests the default attributes of the left account element |
||
306 | * |
||
307 | * @return void |
||
308 | * @covers ::setDefaults |
||
309 | */ |
||
310 | View Code Duplication | public function testAccountLeftAttrDefaultValues() |
|
323 | |||
324 | /** |
||
325 | * Tests the default attributes of the right account element |
||
326 | * |
||
327 | * @return void |
||
328 | * @covers ::setDefaults |
||
329 | */ |
||
330 | View Code Duplication | public function testAccountRightAttrDefaultValues() |
|
343 | |||
344 | /** |
||
345 | * Tests the default attributes of the left francs amount element |
||
346 | * |
||
347 | * @return void |
||
348 | * @covers ::setDefaults |
||
349 | */ |
||
350 | View Code Duplication | public function testAmountFrancsLeftAttrDefaultValues() |
|
364 | |||
365 | /** |
||
366 | * Tests the default attributes of the right francs amount element |
||
367 | * |
||
368 | * @return void |
||
369 | * @covers ::setDefaults |
||
370 | */ |
||
371 | View Code Duplication | public function testAmountFrancsRightAttrDefaultValues() |
|
385 | |||
386 | /** |
||
387 | * Tests the default attributes of the left cents amount element |
||
388 | * |
||
389 | * @return void |
||
390 | * @covers ::setDefaults |
||
391 | */ |
||
392 | View Code Duplication | public function testAmountCentsLeftAttrDefaultValues() |
|
405 | |||
406 | /** |
||
407 | * Tests the default attributes of the right cents amount element |
||
408 | * |
||
409 | * @return void |
||
410 | * @covers ::setDefaults |
||
411 | */ |
||
412 | View Code Duplication | public function testAmountCentsRightAttrDefaultValues() |
|
425 | |||
426 | /** |
||
427 | * Tests the default attributes of the left payer element |
||
428 | * |
||
429 | * @return void |
||
430 | * @covers ::setDefaults |
||
431 | */ |
||
432 | View Code Duplication | public function testPayerLeftAttrDefaultValues() |
|
445 | |||
446 | /** |
||
447 | * Tests the default attributes of the right payer element |
||
448 | * |
||
449 | * @return void |
||
450 | * @covers ::setDefaults |
||
451 | */ |
||
452 | View Code Duplication | public function testPayerRightAttrDefaultValues() |
|
465 | |||
466 | /** |
||
467 | * Tests the default background |
||
468 | * |
||
469 | * @return void |
||
470 | * @covers ::setDefaults |
||
471 | */ |
||
472 | public function testSlipBackgroundDefaultValues() |
||
476 | |||
477 | /** |
||
478 | * Tests the setBankLeftAttr method |
||
479 | * |
||
480 | * @return void |
||
481 | * @covers ::setBankLeftAttr |
||
482 | * @covers ::setAttributes |
||
483 | * @covers ::getBankLeftAttr |
||
484 | */ |
||
485 | public function testSetBankLeftAttr() |
||
491 | |||
492 | /** |
||
493 | * Tests the setBankRightAttr method |
||
494 | * |
||
495 | * @return void |
||
496 | * @covers ::setBankRightAttr |
||
497 | * @covers ::setAttributes |
||
498 | * @covers ::getBankRightAttr |
||
499 | */ |
||
500 | public function testSetBankRightAttr() |
||
506 | |||
507 | /** |
||
508 | * Tests the setRecipientLeftAttr method |
||
509 | * |
||
510 | * @return void |
||
511 | * @covers ::setRecipientLeftAttr |
||
512 | * @covers ::setAttributes |
||
513 | * @covers ::getRecipientLeftAttr |
||
514 | */ |
||
515 | public function testSetRecipientLeftAttr() |
||
521 | |||
522 | /** |
||
523 | * Tests the setRecipientRightAttr method |
||
524 | * |
||
525 | * @return void |
||
526 | * @covers ::setRecipientRightAttr |
||
527 | * @covers ::setAttributes |
||
528 | * @covers ::getRecipientRightAttr |
||
529 | */ |
||
530 | public function testSetRecipientRightAttr() |
||
536 | |||
537 | /** |
||
538 | * Tests the setAccountLeftAttr method |
||
539 | * |
||
540 | * @return void |
||
541 | * @covers ::setAccountLeftAttr |
||
542 | * @covers ::setAttributes |
||
543 | * @covers ::getAccountLeftAttr |
||
544 | */ |
||
545 | public function testSetAccountLeftAttr() |
||
551 | |||
552 | /** |
||
553 | * Tests the setAccountRightAttr method |
||
554 | * |
||
555 | * @return void |
||
556 | * @covers ::setAccountRightAttr |
||
557 | * @covers ::setAttributes |
||
558 | * @covers ::getAccountRightAttr |
||
559 | */ |
||
560 | public function testSetAccountRightAttr() |
||
566 | |||
567 | /** |
||
568 | * Tests the setAmountFrancsLeftAttr method |
||
569 | * |
||
570 | * @return void |
||
571 | * @covers ::setAmountFrancsLeftAttr |
||
572 | * @covers ::setAttributes |
||
573 | * @covers ::getAmountFrancsLeftAttr |
||
574 | */ |
||
575 | public function testSetAmountFrancsLeftAttr() |
||
581 | |||
582 | /** |
||
583 | * Tests the setAmountCentsLeftAttr method |
||
584 | * |
||
585 | * @return void |
||
586 | * @covers ::setAmountCentsLeftAttr |
||
587 | * @covers ::setAttributes |
||
588 | * @covers ::getAmountCentsLeftAttr |
||
589 | */ |
||
590 | public function testSetAmountCentsLeftAttr() |
||
596 | |||
597 | /** |
||
598 | * Tests the setAmountCentsRightAttr method |
||
599 | * |
||
600 | * @return void |
||
601 | * @covers ::setAmountCentsRightAttr |
||
602 | * @covers ::setAttributes |
||
603 | * @covers ::getAmountCentsRightAttr |
||
604 | */ |
||
605 | public function testSetAmountCentsRightAttr() |
||
611 | |||
612 | /** |
||
613 | * Tests the setAmountFrancsRightAttr method |
||
614 | * |
||
615 | * @return void |
||
616 | * @covers ::setAmountFrancsRightAttr |
||
617 | * @covers ::setAttributes |
||
618 | * @covers ::getAmountFrancsRightAttr |
||
619 | */ |
||
620 | public function testSetAmountFrancsRightAttr() |
||
626 | |||
627 | /** |
||
628 | * Tests the setPayerLeftAttr method |
||
629 | * |
||
630 | * @return void |
||
631 | * @covers ::setPayerLeftAttr |
||
632 | * @covers ::setAttributes |
||
633 | * @covers ::getPayerLeftAttr |
||
634 | */ |
||
635 | public function testSetPayerLeftAttr() |
||
641 | |||
642 | /** |
||
643 | * Tests the setPayerRightAttr method |
||
644 | * |
||
645 | * @return void |
||
646 | * @covers ::setPayerRightAttr |
||
647 | * @covers ::setAttributes |
||
648 | * @covers ::getPayerRightAttr |
||
649 | */ |
||
650 | public function testSetPayerRightAttr() |
||
656 | |||
657 | /** |
||
658 | * Tests the setDisplayBackground method |
||
659 | * |
||
660 | * @return void |
||
661 | * @covers ::setDisplayBackground |
||
662 | * @covers ::getDisplayBackground |
||
663 | * @covers ::isBool |
||
664 | */ |
||
665 | public function testSetDisplayBackground() |
||
679 | |||
680 | /** |
||
681 | * Tests the setDisplayBackground method with an invalid parameter |
||
682 | * |
||
683 | * @return void |
||
684 | * @expectedException \InvalidArgumentException |
||
685 | * @expectedExceptionMessage $displayBackground is not a boolean. |
||
686 | * @covers ::setDisplayBackground |
||
687 | * @covers ::isBool |
||
688 | */ |
||
689 | public function testSetDisplayBackgroundInvalidParameter() |
||
693 | |||
694 | /** |
||
695 | * Tests the setDisplayBank method |
||
696 | * |
||
697 | * @return void |
||
698 | * @covers ::setDisplayBank |
||
699 | * @covers ::getDisplayBank |
||
700 | * @covers ::isBool |
||
701 | */ |
||
702 | View Code Duplication | public function testSetDisplayBank() |
|
703 | { |
||
704 | // Test the default value |
||
705 | $this->assertTrue($this->paymentSlip->getDisplayBank()); |
||
706 | |||
707 | // Disable feature, also check for returned instance |
||
708 | $returned = $this->paymentSlip->setDisplayBank(false); |
||
709 | $this->assertInstanceOf('SwissPaymentSlip\SwissPaymentSlip\Tests\TestablePaymentSlip', $returned); |
||
710 | $this->assertFalse($this->paymentSlip->getDisplayBank()); |
||
711 | |||
712 | // Re-enable the feature |
||
713 | $this->paymentSlip->setDisplayBank(); |
||
714 | $this->assertTrue($this->paymentSlip->getDisplayBank()); |
||
715 | |||
716 | // Check if the data is disabled |
||
717 | $this->paymentSlip->getPaymentSlipData()->setWithBank(false); |
||
718 | $this->assertFalse($this->paymentSlip->getDisplayBank()); |
||
719 | } |
||
720 | |||
721 | /** |
||
722 | * Tests the setDisplayBank method with an invalid parameter |
||
723 | * |
||
724 | * @return void |
||
725 | * @expectedException \InvalidArgumentException |
||
726 | * @expectedExceptionMessage $displayBank is not a boolean. |
||
727 | * @covers ::setDisplayBank |
||
728 | * @covers ::isBool |
||
729 | */ |
||
730 | public function testSetDisplayBankInvalidParameter() |
||
734 | |||
735 | /** |
||
736 | * Tests the setDisplayAccount method |
||
737 | * |
||
738 | * @return void |
||
739 | * @covers ::setDisplayAccount |
||
740 | * @covers ::getDisplayAccount |
||
741 | * @covers ::isBool |
||
742 | */ |
||
743 | View Code Duplication | public function testSetDisplayAccount() |
|
744 | { |
||
745 | // Test the default value |
||
746 | $this->assertTrue($this->paymentSlip->getDisplayAccount()); |
||
747 | |||
748 | // Disable feature, also check for returned instance |
||
749 | $returned = $this->paymentSlip->setDisplayAccount(false); |
||
750 | $this->assertInstanceOf('SwissPaymentSlip\SwissPaymentSlip\Tests\TestablePaymentSlip', $returned); |
||
751 | $this->assertFalse($this->paymentSlip->getDisplayAccount()); |
||
752 | |||
753 | // Re-enable the feature |
||
754 | $this->paymentSlip->setDisplayAccount(); |
||
755 | $this->assertTrue($this->paymentSlip->getDisplayAccount()); |
||
756 | |||
757 | // Check if the data is disabled |
||
758 | $this->paymentSlip->getPaymentSlipData()->setWithAccountNumber(false); |
||
759 | $this->assertFalse($this->paymentSlip->getDisplayAccount()); |
||
760 | } |
||
761 | |||
762 | /** |
||
763 | * Tests the setDisplayAccount method with an invalid parameter |
||
764 | * |
||
765 | * @return void |
||
766 | * @expectedException \InvalidArgumentException |
||
767 | * @expectedExceptionMessage $displayAccount is not a boolean. |
||
768 | * @covers ::setDisplayAccount |
||
769 | * @covers ::isBool |
||
770 | */ |
||
771 | public function testSetDisplayAccountInvalidParameter() |
||
775 | |||
776 | /** |
||
777 | * Tests the setDisplayRecipient method |
||
778 | * |
||
779 | * @return void |
||
780 | * @covers ::setDisplayRecipient |
||
781 | * @covers ::getDisplayRecipient |
||
782 | * @covers ::isBool |
||
783 | */ |
||
784 | View Code Duplication | public function testSetDisplayRecipient() |
|
785 | { |
||
786 | // Test the default value |
||
787 | $this->assertTrue($this->paymentSlip->getDisplayRecipient()); |
||
788 | |||
789 | // Disable feature, also check for returned instance |
||
790 | $returned = $this->paymentSlip->setDisplayRecipient(false); |
||
791 | $this->assertInstanceOf('SwissPaymentSlip\SwissPaymentSlip\Tests\TestablePaymentSlip', $returned); |
||
792 | $this->assertFalse($this->paymentSlip->getDisplayRecipient()); |
||
793 | |||
794 | // Re-enable the feature |
||
795 | $this->paymentSlip->setDisplayRecipient(); |
||
796 | $this->assertTrue($this->paymentSlip->getDisplayRecipient()); |
||
797 | |||
798 | // Check if the data is disabled |
||
799 | $this->paymentSlip->getPaymentSlipData()->setWithRecipient(false); |
||
800 | $this->assertFalse($this->paymentSlip->getDisplayRecipient()); |
||
801 | } |
||
802 | |||
803 | /** |
||
804 | * Tests the setDisplayRecipient method with an invalid parameter |
||
805 | * |
||
806 | * @return void |
||
807 | * @expectedException \InvalidArgumentException |
||
808 | * @expectedExceptionMessage $displayRecipient is not a boolean. |
||
809 | * @covers ::setDisplayRecipient |
||
810 | * @covers ::isBool |
||
811 | */ |
||
812 | public function testSetDisplayRecipientInvalidParameter() |
||
816 | |||
817 | /** |
||
818 | * Tests the setDisplayAmount method |
||
819 | * |
||
820 | * @return void |
||
821 | * @covers ::setDisplayAmount |
||
822 | * @covers ::getDisplayAmount |
||
823 | * @covers ::isBool |
||
824 | */ |
||
825 | View Code Duplication | public function testSetDisplayAmount() |
|
826 | { |
||
827 | // Test the default value |
||
828 | $this->assertTrue($this->paymentSlip->getDisplayAmount()); |
||
829 | |||
830 | // Disable feature, also check for returned instance |
||
831 | $returned = $this->paymentSlip->setDisplayAmount(false); |
||
832 | $this->assertInstanceOf('SwissPaymentSlip\SwissPaymentSlip\Tests\TestablePaymentSlip', $returned); |
||
833 | $this->assertFalse($this->paymentSlip->getDisplayAmount()); |
||
834 | |||
835 | // Re-enable the feature |
||
836 | $this->paymentSlip->setDisplayAmount(); |
||
837 | $this->assertTrue($this->paymentSlip->getDisplayAmount()); |
||
838 | |||
839 | // Check if the data is disabled |
||
840 | $this->paymentSlip->getPaymentSlipData()->setWithAmount(false); |
||
841 | $this->assertFalse($this->paymentSlip->getDisplayAmount()); |
||
842 | } |
||
843 | |||
844 | /** |
||
845 | * Tests the setDisplayAmount method with an invalid parameter |
||
846 | * |
||
847 | * @return void |
||
848 | * @expectedException \InvalidArgumentException |
||
849 | * @expectedExceptionMessage $displayAmount is not a boolean. |
||
850 | * @covers ::setDisplayAmount |
||
851 | * @covers ::isBool |
||
852 | */ |
||
853 | public function testSetDisplayAmountInvalidParameter() |
||
857 | |||
858 | /** |
||
859 | * Tests the setDisplayPayer method |
||
860 | * |
||
861 | * @return void |
||
862 | * @covers ::setDisplayPayer |
||
863 | * @covers ::getDisplayPayer |
||
864 | * @covers ::isBool |
||
865 | */ |
||
866 | View Code Duplication | public function testSetDisplayPayer() |
|
867 | { |
||
868 | // Test the default value |
||
869 | $this->assertTrue($this->paymentSlip->getDisplayPayer()); |
||
870 | |||
871 | // Disable feature, also check for returned instance |
||
872 | $returned = $this->paymentSlip->setDisplayPayer(false); |
||
873 | $this->assertInstanceOf('SwissPaymentSlip\SwissPaymentSlip\Tests\TestablePaymentSlip', $returned); |
||
874 | $this->assertFalse($this->paymentSlip->getDisplayPayer()); |
||
875 | |||
876 | // Re-enable the feature |
||
877 | $this->paymentSlip->setDisplayPayer(); |
||
878 | $this->assertTrue($this->paymentSlip->getDisplayPayer()); |
||
879 | |||
880 | // Check if the data is disabled |
||
881 | $this->paymentSlip->getPaymentSlipData()->setWithPayer(false); |
||
882 | $this->assertFalse($this->paymentSlip->getDisplayPayer()); |
||
883 | } |
||
884 | |||
885 | /** |
||
886 | * Tests the setDisplayPayer method with an invalid parameter |
||
887 | * |
||
888 | * @return void |
||
889 | * @expectedException \InvalidArgumentException |
||
890 | * @expectedExceptionMessage $displayPayer is not a boolean. |
||
891 | * @covers ::setDisplayPayer |
||
892 | * @covers ::isBool |
||
893 | */ |
||
894 | public function testSetDisplayPayerInvalidParameter() |
||
898 | |||
899 | /** |
||
900 | * Tests the getAllElements method |
||
901 | * |
||
902 | * @return void |
||
903 | * @covers ::getAllElements |
||
904 | */ |
||
905 | public function testGetAllElements() |
||
926 | |||
927 | /** |
||
928 | * Tests the getAllElements method when no elements are shown |
||
929 | * |
||
930 | * @return void |
||
931 | * @covers ::getAllElements |
||
932 | */ |
||
933 | public function testGetAllElementsNoElementsShown() |
||
947 | |||
948 | /** |
||
949 | * Tests the getAllElements method when all data is disabled |
||
950 | * |
||
951 | * @return void |
||
952 | * @covers ::getAllElements |
||
953 | */ |
||
954 | public function testGetAllElementsDisabledData() |
||
969 | } |
||
970 |
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.