Motley says: "If I write code to pass tests I’m cheating!"




Motley: Tests need to validate code that has already been written - not the other way around.


Maven: Writing tests before you code allows the tests to drive your code while providing more sound requirements validation.



[Context: Motley is thinking through test-driven development before he goes off and tries it]


Motley: I've been thinking about this TDD thing and something is weird - if I write code to pass tests that's cheating! Tests need to validate code that has already been written.


Maven: Cheating? Hardly. Your tests are written around the requirements. What's wrong with writing code to execute the requirements? You're actually cheating if you write tests after the code. Now the tests are exercising the code but you are an extra step away from the requirements. Validation that you met the requirements is loose at best.


Motley: But I write my application code to satisfy the requirements. What's the difference?


Maven: The difference is that tests validate that the requirements are met, which is a logical layer between the requirements and the code. It forces you to think about the requirements in greater detail before implementing them. Plus, you get all the other benefits we talked about with TDD.


Motley: Well, maybe, but…


Maven: Just do me a favor and try out TDD for a couple of days, okay?


Motley: Fine, fine, fine. If it gets you off my back. Give me a couple of days to play. Now go make yourself useful and clean up the kitchen or something.



Maven's Pointer: "Requirements" as described in TDD are usually described at a lower level than you may be used to. A "requirement" is one small nugget of functionality that you want to implement. It may be an entire (simple) method, or one positive or negative path through the method.


Maven's Resources:   Test-Driven Development in Microsoft .NET, by James Newkirk and Alexei Vorontsov, Microsoft Press, ISBN: 0735619484, 2004.

Comments (3)
  1. Chris Becker says:

    I’ve found it rare that unit tests can completely encompass the requirements for a program. Programs with complex inputs and outputs would be hard pressed to test all of their features with unit tests. There’s still a need for a human tester to try new scenarios and think of ways the customer would use the product. Unit tests and automation simply validate that a path a tester has taken previously is still valid.

    Unit tests can help ensure you aren’t breaking some core piece of functionality without knowing, but can they really be used as "requirements validators" for mid to large sized programs? Wouldn’t we get into the habbit of "The light’s green, ship it!"?

  2. Thanks for the comment Chris!

    Unit tests address testing on a whitebox (low) level. They do their best to address the requirements as thoroughly as possible, but keep in mind we are talking about very low-level requirements here (e.g. boundary conditions in an API). There are also user scenarios and integration amongst the units that unit tests typically do not address.

    There is definitely still room for human testers. The test team tests integrated user scenarios (especially from the customer perspective), stress, performance, and creates and maintains more exhaustive test automation. With developers writing unit tests, the test team can then focus on the "right" thing and not have to find all the little issues devs should have caught.

    Unit tests cannot play the role of requirements validators on the system level – only on the unit level. We have to recognize the need for all levels of testing and should never ship a product just based on passing unit tests.

  3. Corey Ladas says:

    There are a couple of overlapping issues here.  Unit tests are a form of design verification.  Since good designs are a projection of the requirements, DVTs should get you a large subset of requirements verification.  A related question then, is the feasibility of automated requirements verification, which is similar to but not identical with unit testing.  Unit tests are always about testing individual units, where automated subsystem or system tests test many units together.  The two types of test might even share code.  The difference might be the substitution of mock objects vs real live objects.  An automated subsystem test might feed a high level component scripted test data, but called through the same interface as the corresponding unit test.  Unit vs integration vs acceptance testing is more about the scope of coverage than the mechanism employed.

Comments are closed.

Skip to main content