In attempt to subscribe to behavior-driven development I've been using rspec and jasmine for testing my ruby and javascript code respectively. Along the way I've had some thoughts about the value of testing, in particular for collaborative projects. Although there's plenty of discussion online about this I found it helpful to jot down my thoughts.
Tests mitigate many problems that arise with collaborative projects:
- You learn ways to develop a component so that it can be used in isolation, i.e., so it can be used in your tests of the component, without whatever other infrastructure will be in place or the code into which the component will be plugged. This forces a degree of modularity and an interface to the component that is sufficient for testing, and thus likely sufficient for other components to interact with it in sensible ways.
- Someone can read the tests of a component to learn how a component is used (say, if the documentation is not quite sufficient, or worse, absent).
- Tests are helpful is by forcing well-defined, stable interfaces for APIs. Two developers can be working on two separate components that must interact. If they get together and discuss the interfaces, they can each encode the specification in tests of their components, and use the tests as a means of keeping the interfaces stable.
- Tests can even play a role in ensuring that APIs and interfaces don't change between minor versions when subscribing to the semantic versioning ideals.
- By having a habit of developing components that can stand alone well enough to be tested, it provides a means of involving a developer who is not yet familiar with the the other components of a system or the big picture of the project. The developer can be given a set of tests that his component must satisfy, and thus he doesn't need to know sufficiently much to design the interface, that can be provided by another developer. Instead he must simply implement the component so that the tests are satisfied.
- When a developer leaves the company or project, the tests survive as a record of how things are supposed to work.
- The philosophy that "code wins arguments" can be put into practice by proving that a bug exists with a test that fails. Then a successful fix will be evidenced by a passing test. Each of these steps can be committed to the repository and referenced from the bug tracker so that everyone knows the bug is fixed, can see how it was fixed, and if the bug ever resurfaces, then the test that proved its existence will fail and the bug can be squashed again.
- Tests provide a means of noting the absence of a feature so that it will not be forgotten to be implemented, but allowing a developer to continue on her current trajectory and not be distracted by every thing that crops up.
- Tests allow one to delegate work. If you notice something is missing from another developer's code or want to communicate to another developer what needs to be done, writing some tests are a good way to do this. It has the benefit that you can communicate how you want something to work, and it shows the other developer that you care enough about the feature to spend the time to write the specs. This way it's easier to ask them to spend time developing it, as everyone is busy and might not want to simply be told what to do. This way it's sort of a joint effort.