Unit testing an object that resides inside another object

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
onion2k
Jedi Mod
Posts: 5263
Joined: Tue Dec 21, 2004 5:03 pm
Location: usrlab.com

Unit testing an object that resides inside another object

Post 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?
User avatar
ibbo
Forum Commoner
Posts: 51
Joined: Tue Sep 19, 2006 6:20 am

Post 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
timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Re: Unit testing an object that resides inside another objec

Post 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.
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post 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.
sike
Forum Commoner
Posts: 84
Joined: Wed Aug 02, 2006 8:33 am

Post by sike »

i would test it because it has a defined responsibilty and thus needs testing imho.
my second reason would be tdd (:

chris
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

Applying TDD is still dependent on the objects size IMO. Would you test a 20 line value object?
User avatar
onion2k
Jedi Mod
Posts: 5263
Joined: Tue Dec 21, 2004 5:03 pm
Location: usrlab.com

Post 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?
sike
Forum Commoner
Posts: 84
Joined: Wed Aug 02, 2006 8:33 am

Post by sike »

if small object is kind of a value object it really needs no testing. if it provides functionality it surely does.

chris
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post 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? :)
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post 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.
User avatar
onion2k
Jedi Mod
Posts: 5263
Joined: Tue Dec 21, 2004 5:03 pm
Location: usrlab.com

Post 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.
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post 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.
User avatar
onion2k
Jedi Mod
Posts: 5263
Joined: Tue Dec 21, 2004 5:03 pm
Location: usrlab.com

Post 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.
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post 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.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post 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.
Post Reply