Page 1 of 1
Unit testing an object that resides inside another object
Posted: Fri Sep 29, 2006 5:47 am
by onion2k
I have an object that will (when I've written it) only ever be created as part of a larger object. That is to say, the code is roughly like:
Code: Select all
class BigObject {
var $objSmallObject;
function BigObject() {
$this->objSmallObject = new SmallObject();
}
}
$objBigObject = new BigObject();
SmallObject will never be created outside of BigObject. Would it be better to write unit tests that create an instance of smallObject on it's own, or to write unit tests that test $objBigObject->objSmallObject? It doesn't really make much difference as far as I can tell. I'm wondering whether it's better to keep the tests as simple as possible, or to make them as realistic as possible.. or maybe I should write tests for both situations?
Posted: Fri Sep 29, 2006 6:09 am
by ibbo
Keep it real for thats how its going to work in reality.
If no $obj is ever going to be instantiated outside of $TopObj then dont test for it, though I guess you could test some scenarios if you chose to.
Me I would stick to testing it for how it should react in the world.
Ibbo
Re: Unit testing an object that resides inside another objec
Posted: Fri Sep 29, 2006 6:29 am
by timvw
onion2k wrote:I
SmallObject will never be created outside of BigObject.
The question is the following: Will the SmallObject be used outside the BigObject?
- If no, the object is internal/implementation detail to BigObject and i don't see a reason to test it. (Since in your application domain the BigObject is the smallest defined unit).
- If yes, you most definitely want to verify that it works as expected.
Posted: Fri Sep 29, 2006 7:24 am
by Maugrim_The_Reaper
I wouldn't bother testing SmallObject either... I might do so if it's sufficiently large and complex to warrant its separate group of tests (to narrow down any future reported issues) but you're calling it "Small" object so that seems unlikely.
Posted: Mon Oct 02, 2006 3:51 am
by sike
i would test it because it has a defined responsibilty and thus needs testing imho.
my second reason would be tdd (:
chris
Posted: Mon Oct 02, 2006 5:14 am
by Maugrim_The_Reaper
Applying TDD is still dependent on the objects size IMO. Would you test a 20 line value object?
Posted: Mon Oct 02, 2006 5:16 am
by onion2k
Maugrim_The_Reaper wrote:Applying TDD is still dependent on the objects size IMO. Would you test a 20 line value object?
I think I would actually. Why wouldn't you?
Posted: Mon Oct 02, 2006 5:31 am
by sike
if small object is kind of a value object it really needs no testing. if it provides functionality it surely does.
chris
Posted: Mon Oct 02, 2006 6:28 am
by Maugrim_The_Reaper
I think I would actually. Why wouldn't you?
It's too small - and it's functionality would (if a 20 liner) be minimal. It's like the argument for testing every getter/setter in a class (not including more complex __get/__set methods). If the method is that simple, then the risk of issues is fairly small. Testing it would definitely give you greater coverage (no argument there!) but the time invested compared to the potential risk can be sizeable. Has to be a limit to how much detail you need to go into even when applying TDD...
If the value object is not even exposed outside its creator class, then why bother? It's automatically covered (at a larger grain though) by the creator class's unit tests.
I suppose however, this can be interpreted as a preference. So if you feel more confident testing more, and you think the effort is worthwhile and acceptable, then who am I to argue?

Posted: Mon Oct 02, 2006 6:38 am
by Chris Corbyn
Maugrim_The_Reaper wrote:I think I would actually. Why wouldn't you?
It's too small - and it's functionality would (if a 20 liner) be minimal. It's like the argument for testing every getter/setter in a class (not including more complex __get/__set methods). If the method is that simple, then the risk of issues is fairly small. Testing it would definitely give you greater coverage (no argument there!) but the time invested compared to the potential risk can be sizeable. Has to be a limit to how much detail you need to go into even when applying TDD...
If the value object is not even exposed outside its creator class, then why bother? It's automatically covered (at a larger grain though) by the creator class's unit tests.
I suppose however, this can be interpreted as a preference. So if you feel more confident testing more, and you think the effort is worthwhile and acceptable, then who am I to argue?

I agree. Test the components which use it. If they work and they depend upon it I think you can assume the small component works. It's the same as accessors, there's no need to test blatantly obvious things. I'll ocassionally test small things not because I think they need testing but for clarification of the use of them. I'm quite new to TDD but already I can see how it can be initially easy to get sidetracked testing things which needn't be tested. Your tests will likely just finish up confusing.
Posted: Mon Oct 02, 2006 10:08 am
by onion2k
Hmm.. this thread is getting a little off topic. I would agree with not bothering to test very simple objects, that's understandable. However..
In the case I stated in the orginal post SmallObject is actually quite complex. I'm writing a project management application, and SmallObject is the a 'task' object. 'tasks' can only exist within a 'project' object (each 'project' is essentially a registry of 'task' instances with a collection of methods to check for clashes, build new tasks, that sort of thing). The 'task' object holds information about the task it describes (title, dates, colour, assets assigned etc). It has methods for things like checking availability, validating dates, assigning and deassigning assets. Much more complicated than a value object.
The puzzle is whether to write unit tests to test the functionality of a 'task' as an instance on it's own, or whether to write unit tests that test the functionality of a 'task' accessed through the 'project' object. Or both.
Posted: Mon Oct 02, 2006 10:22 am
by Maugrim_The_Reaper
Maugrim_The_Reaper wrote:I might do so if it's sufficiently large and complex to warrant its separate group of tests
You've stated it's sufficiently complex - enough that you worry about it

. In that case, test it. Seems complex enough from your description to warrant it.
Posted: Mon Oct 02, 2006 10:28 am
by onion2k
Maugrim_The_Reaper wrote:You've stated it's sufficiently complex - enough that you worry about it

. In that case, test it. Seems complex enough from your description to warrant it.
It's definitely complicated enough to test. That's never been in question in my opinion. The problem is whether I opt for the 'realistic' test or the 'simple' test. The 'realistic' test is to write tests that test 'task' through an instance of 'project', while the 'simple' test is to create an instance of 'task' and just test that directly.
Posted: Mon Oct 02, 2006 10:48 am
by Maugrim_The_Reaper
I would hazard simple.
If you test Task's public interface, and all runs green, then you can be reasonably certain it behaves the same way as if within Project. Project tests would likewise just test its public interface - it would ignore any implementation details (including Task). If something goes wrong it's not going to be difficult to deduce which is responsible for any issue - only one set of tests will turn red...
Checking how Project uses Tasks is not a public behaviour - it's a private implementation detail. If you test "through" Project (and forgive me if I misunderstand you) how can you know what the state of Task is? It's likely a private property of Project, and thus not accessible through Project's public interface.
Posted: Mon Oct 02, 2006 12:38 pm
by Chris Corbyn
The simple test would be a "unit" test in the true sense of the term. That's what I'd do initially. The "realistic" test whereby you test it under some complex state would be more like an integration test -- still valuable, still needed.
Do both.