3 Testing techniques

 

This chapter covers

  • Organizing your tests comprehensively
  • Writing assertions that are flexible and robust
  • Isolating and instrumenting parts of your code for tests
  • Defining strategies for choosing what to test and what not to
  • Learning what code coverage is and how to measure it

Well-written tests have two main qualities: they break only when the application misbehaves, and they tell you precisely what’s wrong. In this chapter, we will focus on techniques that help you achieve these two goals.

If you’ve written a test for the addToCart function, for example, you don’t want it to break if that function is still working. If the test does break, it will generate extra costs because you will have to spend time updating it. Ideally, your tests should be sensitive enough to catch as many bugs as possible but sufficiently robust so that they fail only when necessary.

Considering that your tests for the addToCart function broke for a good reason, they still wouldn’t be particularly helpful if their feedback was undecipherable or if 10 other unrelated tests failed when they shouldn’t. A carefully architected test suite provides you with high-quality feedback to fix problems as quickly as possible.

In this chapter, to achieve high-quality feedback and robust yet sensitive tests, I will focus on how to organize tests, write assertions, isolate code, and choose what to test and how to test it.

3.1 Organizing test suites

3.1.1 Breaking down tests

3.1.2 Parallelism

3.1.3 Global hooks

3.1.4 Atomicity

3.2 Writing good assertions

3.2.1 Assertions and error handling

3.2.2 Loose assertions

3.2.3 Using custom matchers

3.2.4 Circular assertions

3.3 Test doubles: Mocks, stubs, and spies

3.3.1 Mocking imports

3.4 Choosing what to test

3.4.1 Don’t test third-party software

3.4.2 To mock, or not to mock: That’s the question

3.4.3 When in doubt, choose integration tests

3.5 Code coverage

sitemap