Part 1 : Test Driven Development — the basics

Melanie Fayne
4 min readJun 15, 2022

--

Test Before vs Test After : Traditional Testing

A big question in software development is whether to test software before we code or after. Tradition has always been to code first then write test cases for the code we’ve already written. This type of testing has a common point of failure in that, sure the system would would pass the tests because the tests made sure of that, but working on the tests would gradually become more and more difficult. How so? Imagine we have some already existing code and now we’re writing tests for it. We are bound to encounter the following problems to name just a few:

  1. Untestable Code : Since the code wasn’t designed/written to be testable, there’s stuff we can’t access in the code for testing. Hence asserting that the code did what we think it should would be difficult.
  2. Tests are highly coupled with the code : We end up writing tests that are very specific to the code we’ve already written. This would mean that changing the code would mean having to rewrite the tests for the code as well.
  3. Testing the code rather than requirements : We end up testing that the code that we wrote is the code that we wrote, which isn’t very helpful. Attention shifts from, ‘Does the code do what it’s supposed to do?’ and goes to ‘Does the code work regardless?’

A better approach to testing is writing unit tests even before we code. In other words, Test Driven Development …

Test Driven Development

What it is

Test-driven development (TDD) is a software development process relying on software requirements being converted to test cases before software is fully developed, and tracking all software development by repeatedly testing the software against all test cases. This is as opposed to software being developed first and test cases created later. [1][1].

In a nutshell :

  • Test driven development means just that i.e. development is driven by tests i.e the tests come first!
  • TDD puts emphasis on specifications (requirements) instead of tests
  • TDD is based around confirming behavior rather than testing code.

How to do it (The Steps)

The following sequence is based on the book Test-Driven Development by Example :

steps in tdd
  1. Add a test : The adding of a new feature begins by writing a test that passes if the feature’s specifications are met. The developer can discover these specifications by asking about use cases and user stories. A key benefit of test-driven development is that it makes the developer focus on requirements before writing code. This is in contrast with the usual practice, where unit tests are only written after code.
  2. Run all tests. The new test should fail for expected reasons : This shows that new code is actually needed for the desired feature. It validates that the test harness is working correctly. It rules out the possibility that the new test is flawed and will always pass.
  3. Write the simplest code that passes the new test : Inelegant or hard code is acceptable, as long as it passes the test. The code will be honed anyway in Step 5. No code should be added beyond the tested functionality.
  4. All tests should now pass : If any fail, the new code must be revised until they pass. This ensures the new code meets the test requirements and does not break existing features.
  5. Refactor as needed, using tests after each refactor to ensure that functionality is preserved : Code is refactored for readability and maintainability. In particular, hard-coded test data should be removed. Running the test suite after each refactor helps ensure that no existing functionality is broken. Examples of refactoring:
  • Moving code to where it most logically belongs
  • Removing duplicate code
  • Making names self-documenting
  • Splitting methods into smaller pieces
  • Re-arranging inheritance hierarchies

6. Repeat : The cycle above is repeated for each new piece of functionality. Tests should be small and incremental, and commits made often. That way, if new code fails some tests, the programmer can simply undo or revert rather than debug excessively.

This workflow is sometimes called Red-Green-Refactoring, which comes from the status of the tests within the cycle.

  • The red phase indicates that code does not work.
  • The green phase indicates that everything is working, but not necessary in the most optimal way.
  • The blue phase indicates that the tester is refactoring the code, but is confident their code is covered with tests which gives the tester confidence to change and improve our code.

The Benefits

  1. Early bug notification
  2. Better Designed, cleaner and more extensible code.
  3. Confidence to Refactor
  4. Good for teamwork
  5. Good for Developers

In the next and final part of this article, we put the basics of test driven development into practice.

REFERENCES

Article References

Video References

--

--