1

i am new to PHP testing and trying to build a simple project with TDD.

The simple idea was to make a simple Card/Deck setup of some kind.

I started writting tests and quickly started mashing up a CardDeck class and CardStack class from my failling tests. They both implemented some of the same methods, like getTop(), getTopStack().. so i decided implement a CardDeckInterface, a abstract class BaseCardStack, to dry it up.

After refactoring. CardDeck and CardStack extends BaseCardStack which implements the CardStackInterface.

The CardDeck and CardStack only differences is the construct and a few added functions to the CardStack. Else none of the implemented functions from BaseCardStack are overwritten.

This is where my troubles being. In my CardDeckTest i had tests tied to the implemented methods, that have been to moved the BaseCardDeck.

Should i keep my current tests in my CardDeckTest ( they still pass as before ) and write a extra set of tests for CardStackTest? This seems like the wrong solution as the methods are already tested and in no way differ (not overwritten), as i mentioned, the implemented methods from the BaseCardStack are not overwritten.

Instead i think that i should move/write tests for my abstract class.

Basicly i want to test the functions in my abstract class which i know will be implemented without being overwritten.

But how do i do this? Should i mock? Should i change my patterns?

Ronni Skansing
  • 1,494
  • 1
  • 17
  • 33

1 Answers1

1

Instead i think that i should move/write tests for my abstract class

Actually that and you perhaps want to apply the same set of unit tests on any other class implementing that interface.

But before you do some words of warning: Think twice. You probably don't need the abstract class here. It sounds like you have some kind of data structure that suits well for the job which is used by two classes however those two classes are not that data-structure.

However by extending both those two classes from the abstract data-structure class you are actually making those two classes very much this data-structure only.

Favorite composition over inheritance.

Just saying, for your original question about how to test the abstract class, you create a test-double out of it. This either works with PHPUnit mocks which is able to mock abstract classes (and Testing Abstract Classes) and while doing so taking over the defined methods.

But I normally just create a stub-class for testing that is creating a new file which contains a class definition extending from the abstract base class that is otherwise independent to the rest of the application (but bound on the abstract class) and then use it as subject in the unit-test (compare with Test methods of Abstract Class with PHPUnit).

Doing so most often does not hide the fact of not needing an abstract base class after all behind complicated mock and stub setups. Just the write as little code as necessary approach that is so hard to achieve.

Hope this helps, feel free to ask back.

Oh and actually here is another tip. What I did once or twice for an abstract base class is to create an abtract test-case as well that contains the tests for the base. Extending from it then for the concrete implementation tests did work quite well. IIRC the related question was:

Community
  • 1
  • 1
hakre
  • 193,403
  • 52
  • 435
  • 836
  • thanks the answer makes good sense. But you write -> "Actually that and you perhaps want to apply the same set of unit tests on any other class implementing that interface", so if the base abstraction got a getTop(), this is extended to the deck and stack class, you want me to right tests for them as well even if they are identical to those in the base test? – Ronni Skansing Sep 29 '13 at 10:59
  • 1
    What I meant by that is that if you've got an interface you can theretically write one phpunit-testcase for that interface and then test each concrete class implementing that interface with that testcase. That is independent to having an abstract base-class. Is this more clear? – hakre Sep 29 '13 at 11:03
  • Yes it clear :) Im gonna go google writting testing to a interface. – Ronni Skansing Sep 29 '13 at 11:10