Testing attach() method

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")

Moderator: General Moderators

Post Reply
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Testing attach() method

Post by Luke »

I'm testing a method that basically adds to an internal array of the class. How can I test that I have successfully attach()'d something? Reflection?

Code: Select all

$cal->attach($event);
// test that $cal->_children contains $event
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Post by Jenk »

Code: Select all

$this->assertTrue(in_array($event, $cal->getChildren(), true));
?

Generally speaking, you don't test private methods/properties. They are not part of the interface, and thus not part of the behaviour - however, if you find yourself either wanting to test, or must test, then sometimes it's an indication that it shouldn't be private, or it should have a public accessor (the latter being my preference).
McGruff
DevNet Master
Posts: 2893
Joined: Thu Jan 30, 2003 8:26 pm
Location: Glasgow, Scotland

Post by McGruff »

Definitely agree: don't test private properties. Tests should not mention any implementation details otherwise they will be very brittle when you refactor. (Mocks & interaction tests do of course expose some implementation stuff - the method calls on neighbouring objects - but then that's their whole point).

In general you can either:
(1) make assertions on data returned by public methods of the tested class
(2) make assertions based on third party effects such as mock object expectations, files written, database rows inserted, etc.
(3) don't make any assertions at all if it's really trivial such as...

Code: Select all

function getFoo() {
    return $this->foo;
}
If the calendar has methods like getEvents() or getEventsOn($date) you could check for the event in there. That sounds too easy an answer?

The important thing is to stick to your guns. If you've figured out the simplest, easiest to understand interface for a class don't change it or add bits just to make it easier to test.

When you name a test, try and use the language of the domain as far as you can. This might help to keep you thinking about interfaces and behaviours rather than getting caught up in implementation details. You do start to lose that the deeper you get into the object graph, where the language tends to get more technical, but it's always about interfaces and behaviours.
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

Just to reiterate - if it's private then don't test it. I'm sure you already know that private stuff can change all the time, whereas a public interface will generally not.

I'm not so sure about avoiding adding new public methods to make testing easier. In many cases you shouldn't because you just end up with class bloat, code serving no real purpose. However I think you should ask the question anyway: Will it add useful functionality? In most cases we're talking about a simple getter - and in some cases users will like that extra getter when it comes to building on your base class for their applications.
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Post by Luke »

Thanks you all. This has been immensely helpful. This whole thing makes a lot more sense for me now. I'm not sure what it is about unit testing that has kept me so baffled, but for some reason I've just never been able to grasp the concepts. I will try and keep in mind that I should only be testing the public interface as like you guys said, implementation should be able to be changed without having to change the tests too much if at all. :)
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Probably re-iterating, but you should probably just test it the way you want it to work from the face of it (i.e. if you attach() the event does it become available at the correct date in the calendar?) Testing if it's added to the array is just going to cause you to judder and swear once you start to refactor ;)
McGruff
DevNet Master
Posts: 2893
Joined: Thu Jan 30, 2003 8:26 pm
Location: Glasgow, Scotland

Post by McGruff »

Maugrim_The_Reaper wrote:I'm not so sure about avoiding adding new public methods to make testing easier. In many cases you shouldn't because you just end up with class bloat, code serving no real purpose. However I think you should ask the question anyway: Will it add useful functionality? In most cases we're talking about a simple getter - and in some cases users will like that extra getter when it comes to building on your base class for their applications.
Sometimes code which is hard to test is a smell indicating bad design and changing a class to make it easier to test can lead to a better one. That's probably more to do with shuffling responsibilities around rather than changing the interface. Probably.

I can't quite define this without contradicting myself. As a rule I'd say that yes you definitely want to put the simplest-interface-you-can-think-of first. That's the fixed point which implementations orbit around. You don't want to compromise that if you can avoid it. Code can almost always be thrashed into shape.

At the same time test-first is a process of learning about the domain and testing problems might suggest improvements to the design. I suspect that's not what's happening here but I could be wrong.
Post Reply