Can a test access private methods and properties?

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
georgeoc
Forum Contributor
Posts: 166
Joined: Wed Aug 09, 2006 4:21 pm
Location: London, UK

Can a test access private methods and properties?

Post by georgeoc »

N.B. - I'm using PHP 4.

Am I right in thinking that, in broad terms, tests should not need to access private properties of tested objects, or run private methods? I would say that this can lead to a dependency by the tests on the internal logic of the tested object, which is bad.

I ask because I've done it a lot in my first test-driven project - my test cases often start by testing smaller private methods first before the big public methods which utilises them. Of course, I could strip out the earlier tests and just test the public method, but there are some boundary conditions I find it hard to replicate if I'm only allowed to interface with public methods.

Thoughts, or links to previous discussions (I have searched but found very little), would be much appreciated. I can imagine this question has cropped up before.

Thanks!
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

Considering they are protected/private, no, tests can't access them directly.

If made protected you could build a testing descendant that proxies to the protected methods and data.
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post by Ambush Commander »

TDD involves peeking "under the hood", so even though it may not seem right to test private/protected methods, it's all part of the process. Unit testing in general, however, only stipulates testing of the public interface. It's a choice of philosophy, really: PHP 4, having no encapsulation support, will not complain either way.
georgeoc
Forum Contributor
Posts: 166
Joined: Wed Aug 09, 2006 4:21 pm
Location: London, UK

Post by georgeoc »

Ambush Commander wrote:TDD involves peeking "under the hood", so even though it may not seem right to test private/protected methods, it's all part of the process. Unit testing in general, however, only stipulates testing of the public interface. It's a choice of philosophy, really: PHP 4, having no encapsulation support, will not complain either way.
Thanks. So I shouldn't worry too much, but perhaps I should strive to test public methods only in the future as a 'best practice'.
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

Test only the public methods (or in PHP4, the ones meant as public ;)). A naming convention like adding an underscore in front of a private method/property name is very useful. There are, as Ambush Commander said, times when you really do need to test private methods. I find on specification heavy classes testing private methods make it far easier to locate where a problem is since in many specification heavy classes there's hundreds of lines of code, and only a few public methods (stuff like implementing a YAML lexer and parser for example). Generally though avoid like the plague - internal private methods are never (ever) intended to be a stable API and refactoring can change them fast and often meaning your tests would need a lot of updating. I also often find that where private methods need testing, it's a refactoring sign - maybe those private methods really want to be public in an extracted class? Check if they are genuinely reusable for other code.
georgeoc
Forum Contributor
Posts: 166
Joined: Wed Aug 09, 2006 4:21 pm
Location: London, UK

Post by georgeoc »

Great - thanks for all the advice. It's cleared it up in my mind.

I'm already using the _privateMethod() system you recommend.
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Post by Jenk »

If a method needs testing, it should not be private! TDD.. If you can't test it, you're doing it wrong.
Post Reply