Things a developer should know to practice TDD – Types of tests

This is the third post of TDD series in which I will focus on different types of tests used in TDD. In the first post, I focused on TDD cycles and shared some common misconceptions on the second post

Part 3 Types of tests

More than 15 years ago, while studying for graduation I learned about two sets of testing, Whitebox and Blackbox or Functional and Non-functional. At that time I asked if I want to be a developer why do I need to know about testing? Nowadays It is clear that why all developer should think about testing. However, TDD is about Whitebox or Functional testing.

Test-driven development has no relations with black-box and or all kind of testing, i.e. Performance, Regression, Smoke, Stress,  Sanity, Security, beta etc

Test Pyramid

Three types of test helps me to  go with test driven development and they are

  • Acceptance Tests:  In agile software development, acceptance testing reflecting user stories created by/for the software’s customer during development. This can be achieved by binding a business readable specification.
  • Integration Tests:  To test that the resulting combination functions correctly
  • Unit tests: To test a single small unit

An example

Starting with an acceptance test, to pass those acceptance test write few unit tests, write some integration tests to test the combination of multiple functionalities. When the acceptance test started passing you can stop writing production code and unit tests

Let’s try a simple example. There is a story to return all available products.

  • So, starting with an acceptance test  GetAvaliableProducts should return 1 available product even though 2 products are stored in the system.
  • To make this test compile we may create the new application service and a method  GetAvaliableProducts on it.
  • Next, write a unit test for ProductApplicationService require a repository; create a constructor that requires repository as an argument
  • Verify method calls the repository
  • The method must return product type and other unit tests
  • Write unit tests to implement repository.
  • Write integration tests to test application service return data from all the way from storage
  • Keep writing unit and integration tests unless the acceptance test started passing.

Test Classifications by Assertions

Depending on what you are asserting test can be divided into two types

  • by testing state
  • by testing interactions

Most of the times we should assert on the state of the object. It is recommended to write the interaction test as less as possible.  Interaction tests are most likely to break if any changes on the feature

TDD Classifications by Approaches

Classic TDD

Classical TDD is mainly focused on incremental unit tests. This approach encourages the bottom-up design. In this design approach, you write small independent classes first, because higher-level classes depend upon them

Test-Driven Development by Example – Book by Kent Beck introduces TDD and known as Classical or Chicago School or inside-out approach

London School TDD

London school TDD is the top-down approach. This is started by thinking of how the user suppose to use the system. You need to pay attention to the inputs and outputs of the system.  It’s that integrated test which buys the developers the luxury of writing tightly focused isolation tests of each unit.

Growing Object-Oriented Software, Guided by Tests (Beck Signature) by Steve Freeman describes this top-down approach, which is also known as Mockist or outside-in approach

Classical vs Mockist testing

This table has been copied from here

TDD as Tools

I prefer to use both of them. Starting with a top-down approach as it forces to think of inputs and outputs of the system. But when it is not clear about the implementation, classic TDD is here to rescue. Bottom-up approach is focused on one thing. I like to use both of them side by side or jumping between them. After all the main goal is Better Code Design

Next up What To Test. I will share my opinions about what should be tested. I believe a few parts of the system can be tested by another level of automated testing, e.g. user accptance, load testing etc.

References

I would like to hear your thoughts