Discussion of testing theory and practice, including methodologies (such as TDD, BDD, DDD, Agile, XP) and software - anything to do with testing goes here. (Formerly "The Testing Side of Development")
/**
* @todo uncomment abstract
*/
/*abstract*/ class OF_Entity
{
For the simple reason that these are classes that have unit tests for them but they are legitimately abstract as well. I'm beginning to realise that going round uncommenting these things for release and putting the comments back in when one needs to run unit tests isn't going to work.
So...a bunch of questions:
Should I be testing abstract classes at all? Baring in mind there is such a thing as an abstract class that is never extended by the library itself.
As far as I can see there is no way to temporarily override the abstract constraint at runtime. Is this true?
Should I test these by extending them right above the test case that wishes to test them?
Should I write some code that extracts the entire class definition, removes abstract members and the abstract on the class itself (by means of string manipulation) and evals the new class into existance?
ole wrote:
[*]Should I be testing abstract classes at all? Baring in mind there is such a thing as an abstract class that is never extended by the library itself.
Generally no. If it's a library flex point, as it is here, then yes.
ole wrote:
[*]As far as I can see there is no way to temporarily override the abstract constraint at runtime. Is this true?
Yes, except for maybe funky tricks with runkit or reflection. I've never needed to do it.
ole wrote:
[*]Should I test these by extending them right above the test case that wishes to test them?
Yes. This is probably the clearest method. It will probably improve the interface too. If it's difficult to create the necessary subclasses, then it's probably difficult to use your library.
ole wrote:
[*]Should I write some code that extracts the entire class definition, removes abstract members and the abstract on the class itself (by means of string manipulation) and evals the new class into existance?
This is what the mock toolkits do already. In SimpleTest it's with partial mocks. With PHPUnit you can probably use the mocks directly in some way, as they inherit from the mocked class. If the people reading your tests are familiar with these tools, then you can save yourself some drudge with this technique.
I don't often have that much stuff in an abstract class to the point that I need to test the functionality of it. You can mock an abstract class and test the mock from an interface point of view which is often useful in any case. This way you're testing how it ties in with everything else, without actually specifically extending it with a subclass to provide some specific functionality. You can test subclasses separately and leave out the bits you already tested around the interface of the abstract class.
(Sorry I realise this thread had gone to sleep but I just noticed it)
Actually its good you revived this because I wanted to ask about testing protected and private methods. Should you make them public, test them, then make them private when you know they work? What would be nicest is if you could test them through publics but it is often necessary to split a task into small parts in TDD.
Lately I've been arriving at the conclusion that often it's not needed to make a method protected or private, providing running it will not "break" anything. As feyd says however, test the smallest unit of code you can but consider a "unit" as the API you have (i.e the public parts only). If this feels like you're testing far too huge chunks then maybe you are... maybe you need to refactor.
I have, on the odd ocassion tested protected (not private) methods by simply writing an empty subclass of the class you wish to test and then making the methods public here and calling the protected ones through the "parent" keyword. That is smelly though so try not to.
class Foo
{
protected function runMe() {}
}
class Bar extends Foo
{
public function runMe() { return parent::runMe(); }
}
class TestOfFoo extends UnitTestCase
{
public function testRunMeReturnsTrue()
{
$foo = new Bar();
$this->assertTrue($foo->runMe());
}
}
If this feels like you're testing far too huge chunks then maybe you are... maybe you need to refactor.
I have a class that does some heavy string processing. It has a single public function called 'process' which uses a couple of private helpers which came about through refactoring. I suppose I could make those helpers public, there's no state to this string processor so it wouldn't break anything but I find the idea of exposing any more than the minimum a little uncomfortable. Perhaps I need to muse over why this is -- for one it acts as documentation when I have only a single public there can be no confusion over which method should be used.
I have, on the odd ocassion tested protected (not private) methods by simply writing an empty subclass of the class you wish to test and then making the methods public here and calling the protected ones through the "parent" keyword. That is smelly though so try not to.
On the surface it does seem smelly but it is really though? That subclass only exists for the purpose of testing, probably directly above the unit test case, so it is not included with the class being tested. For testing it fulfils its purpose simply and for all other purposes it doesn't exist so why it is a problem?