Help:Writing testable code

From semantic-mediawiki.org
Jump to: navigation, search
Table of Contents

Having testable code (or for that matter unit tests) doesn't make the software smoother nor faster but it will help to specify an expected behaviour and allows a test to fail when the actual behaviour deviates from the expectation.

Why do we need testable code?

Because it will help to specify the expecation (through the unit test) on how a class (unit) should function and a failing test can point to a disintegrative change for reasons like an altered API or public interface, an unexpected input, or a wrong assertion to begin with (checking a field which didn't yield any influence about an expected behaviour) but of course this doesn't allow a conclusion about the whole system unless sufficient integration tests are provided.

Things to avoid

  • Avoid using static method calls in a constructor or new keyword in a constructor or at field declaration [a.01].
  • Avoid using GLOBAL state objects ($GLOBALS [a.02] ) to influence an object behaviour.
  • Avoid static classes/methods [a.06] unless you are doing class independent object factoring
  • Avoid turning protected/private into public methods unless it is really necessary to access the object, instead use the ReflectionClass [a.10] for access during testing.

Best practices

  • Use dependency injection (constructor injection, setter injection, interface injection, or call time injection) to influence an object behaviour (see [a.12], [a.13], [a.14]).
  • During testing, separate a class (the unit under test) from its integration by simulating controlled behaviour (mock behaviour, canned behaviour) of its partners (classes that are not directly under the control of the test environment or part of the test definition).

See also

[a.01] <http://misko.hevery.com/code-reviewers-guide/>

[a.02] <http://c2.com/cgi/wiki?GlobalVariablesAreBad>

[a.06] <http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/>

[a.10] <http://www.mikeyd.com.au/2011/01/20/how-to-use-phps-reflectionclass-to-test-private-methods-and-properties-with-phpunit/>

[a.12] <http://fabien.potencier.org/article/11/what-is-dependency-injection>

[a.13] <http://net.tutsplus.com/tutorials/php/dependency-injection-in-php/>

[a.14] <https://github.com/wikimedia/mediawiki-extensions-SemanticMediaWiki/tree/master/includes/dic>