CompSci701 Lecture Reflection: Testability

It’s a Trade-Off

  • Encapsulation helps comprehensibility and alterability, but hinders testability.
  • For testability, I want to break encapsulation so that I have:
    • Controllability, being able to directly control the state of objects
    • Observability: being able to see directly see what’s in the state.

Having a well-encapsulated production class, and a transparent MOCK

In order to solve the dilemma, we separate the class being used in production and the class being used in tests.

Inject the MOCK in via DI

In order to allow the production class and the mock to be flexibly swapped, we use Dependency Injection.

  • We follow the Dependency Inversion principle, so that:
    1. Both services, the production class and the mock class, extend the same abstract service
    2. The client (where the service is injected) depends on abstraction.
  • We follow the Liskov Substitution principle, so that:
    1. The mock service still has the functionalities
    2. We can safely substitute the service with the mock service, and let it “pretend” to be the real class, by good usage of inheritance.

Establishing Testing Criteria

In the definition of Testability, the establishment of test criteria, and the conduction of tests, are separated:

Testability — degree of effectiveness and efficiency with which test criteria can be established for a system, product or component and tests can be performed to determine whether those criteria have been met.

What are good testing criteria that I should establish?

Here are some of my thoughts:

  • The test criteria should match the requirements of the product owner:
    • If the team have defined the user story well, the description of the user story is a good source of extracting items of testing criteria.
    • If the user story does not tell us much about how it should be tested, maybe the team should review the story and see how to make the acceptance criteria clearer.
    • This part of testing criteria is likely to be stable.
  • Given that unit tests often go into more details than the user story, the work structure breakdown will be important too.
    • Important to internal quality.
  • The testing criteria specific to the design decision are the parts lead to tests that might have to be altered when the design is altered.

TDD: I’m not alone in not getting it 🎉

but there is good stuff inside

It is really good to know that I am not the only one not getting the point of TDD. However, there are some insights that could be gained from the TDD philosophy:

  1. Writing tests beforehand is a good way to ensure that the team understands the requirements well before digging into coding.
    • If we are not doing TDD, we still need to define the requirements well
    • We could ask for “Acceptance Criteria” similar to test cases, although we might not be writing the actual tests until we have finished developing the actual code.
  2. TDD tends to lead to smaller classes because the class can only be unit tested if it is properly isolated and has a “unit” functionality.
    • If the design is made following good OOP practice, we could still create small and good classes of SR without the facilitation of TDD.