Resume - Test-Driven Development

Slide: https://docs.google.com/presentation/d/1NZ7TYLtUV6WS43ekrOEdgHcs9AUd35L4gTN35QhQyjk/edit?usp=sharing

When a task is given to us to build software, maybe we will directly implement the requested requirements, one by one. As the features grow, how do we ensure that existing features still work?

By testing it.

But testing it manually will cost us time (at least), especially as the features grow. When the agile methodology is adopted, a change in requirements is likely to happen, as the stakeholders see the progress of the developed product.

So, let's test it automatically.

Doing unit tests at a minimum

There are several kinds of tests in software engineering. The most simple one that should be done as early as possible is unit tests.

Software testing levels

It should be simple because unit tests only test individual components in isolation using their public interfaces (functions or methods, in the OOP world). It should be done as early as possible because it allows us to safely refactor the internal working of the components, as long as the public interfaces are stable.

One approach that we can take is to create unit tests as soon as we finished developed a particular interface (function or method), or a component. Using this approach, we may implement the components first, then create unit tests to safeguard future development.

Creating unit tests before implementing the actual component

Participants in action

But as any tests should be created based on requirements, we can define the unit tests first, then implement the actual components.

Creating unit tests before implementing the components means that the tests will fail before the components are implemented. But that's the point: we verify that the development that we will do is not implemented yet (hence, the failing tests).

Creating unit tests also allow us to implement the component in the most simple way that will pass the unit tests. The implementation may not be perfect. The performance may not be good (at first). But we ensure that it is working correctly based on the tests.

By ensuring we create an implementation that will pass the tests, we will have a peace of mind in refactoring the implementation, should we want to do it (e.g. we want to optimize the performance without breaking the functionalities).

This approach is called "test-driven development" — as the development is driven by unit tests that we create. From the narration above, we also see a "red-green-refactor" pattern in test-driven development practice, where:

  1. We make the unit tests, and ensure they fail (red);
  2. We implement the functionalities in the most simple way to pass the tests (green);
  3. We may refactor the implementation then, ensuring it still pas the tests (refactor). (Refactoring the tests may also be done.)

This pattern is illustrated in the image below.

Red-green-refactor pattern

Problem with imperfect implementation

Previously, we said that by doing unit tests, we allow any kind of implementation, as long as they pass the tests. This may create a problem where a silly code like this passes:

private int Sum(int a, int b) {
    return 42;
}

because it is only being tested with 31 + 11.

Thus, it is our job to have enough tests to make sure that the implementation will be done correctly. These tests must be derived from the requirements that are being given to us.

Conclusion

  1. Start creating automated tests, especially unit tests. It helps you to build confidence that your software will not break as the features grow.
  2. Start doing test-driven development. Test-driven development allows you to implement your software in the most simple way possible.
  3. Practice makes perfect. As you build more software and test them automatically (especially using test-driven development), you will know how to make unit tests that ensure the implementation not to be a silly one :).

Hope this helps us to be a better software engineer!

Group photo at the end of session

@saifulwebid

results matching ""

    No results matching ""