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
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
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
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.