The first full length episode of Stride’s podcast, The Rabbit Hole, is now live! This week’s topic is Test Driven...
When initially learning about test-driven development, it’s tempting to want to test everything using every kind of test. However, when building a valuable test suite, over-testing isn’t the best approach. This guide is primarily targeted at production applications with problematic test suites, as well as provide information that will be useful in all stages of development.
An effective test suite allows you to make changes to your code with minimal worry about introducing regressions without hindering the development process. Having too few tests will make it difficult to expand or refactor your codebase without introducing regressions. Having too many tests causes a lengthy feedback loop between committing code and being able to deploy. Over-tested code can be difficult to refactor when the tests are coupled too tightly with the implementation.
Acceptance tests, sometimes referred to as “system tests” or “end-to-end tests,” drive your application or library using its external interface, rather than testing internal logic. For web applications, this is often accomplished using a testing library that can automatically drive a web browser and make assertions against the HTML on the page. An end-to-end test can consist of many steps. For example, a test of the account registration process for a website could consist of driving the browser through:
These tests are often the first tests you will write in a new application, and are a good place to start when adding test coverage to existing applications because they line up closely with user stories. However, they tend to be very slow, therefore should be used sparingly. Test only the paths you expect normal users to encounter frequently. Avoid duplicating code coverage. For example, you need to test the login process once, but any other acceptance tests that require a user to be logged in should set the user’s session directly rather than using the UI to log in.
A unit test is a specification of the nooks and crannies of a particular unit of an application. In languages with a module system, a single module is generally considered a testable unit, and in object-oriented languages a class is a single unit. Many modern programming languages have built-in or official frameworks for unit testing, and a unit test should have no dependencies other than the unit being tested and the test framework.
Unit tests are designed to be comprehensive; the entire public interface of a unit should be tested. Each test should be small, covering one aspect of the unit’s behavior. Since unit tests tend to be fast, accumulating large numbers of unit tests which follow the aforementioned rules is not a concern.
* If a unit depends on a library that behaves in a manner contrary to the documentation, and your unit needs to work around that library’s defect, you should test the workaround to ensure your code doesn’t break if the library is fixed.
Integration tests resemble unit tests. They are designed to test the cooperation of multiple units. Integration tests should be comprehensive for interactions between the units, but generally do not need to cover cases of bad input from one unit to another. Bad or unexpected messages from one unit to another should be covered in each unit’s tests, as well as in higher-level tests. An integration test can use the same tooling as a unit test, but needs to include several units as well as the testing framework.
The idea of a performance test is to ensure that changes to the application do not cause it to run more slowly. This can be a tricky thing to test, because there are so many different aspects of an application that can affect performance. The tests can be written using unit testing tools, but rather than running them and expecting a pass/fail result, the tests should be run on one machine against the current production version of the code and against the new code. If the time to run the tests increases in the new version, that is a regression that may need to be corrected.
Not every application needs performance tests. In fact, most applications don’t need performance tests. You need performance tests if:
By Paul Blair
Pair programming is probably the most controversial and least-adopted Agile practice. Capers Jones finds that for...
Posted February 12, 2016