On Wednesday evening, I had an “Aha!” moment when listening to Steve Freeman talk about Test-Driven Development: That’s not what we meant at the local branch of the BCS. Apparently there has been a bit of backlash against TDD recently, with people complaining that their test suites are so big and fragile that they take more effort to maintain than the actual code does. Steve was explaining his approach to writing tests and how to avoid these pitfalls.
As part of his presentation, he advocated that tests should be written for interfaces not implementations, and in fact for protocols rather than interfaces. He contrasted an example of good practice, using a combination of externally visible methods to test behaviour, with a poor example that used a backdoor to twiddle internal state. He remarked that it was only when he started to write these sort of tests that he finally understood the oft-repeated mantra that logical models should be separated from the implementation.
This was my “Aha!” moment, as I realised why some people were finding TDD difficult. When I first encountered TDD, I already knew enough about specifying behaviour to let me write meaningful tests. I had several years’ experience of writing specifications using mathematical logic, and although you don’t use the actual language of mathematical logic to write tests, the mindset is very much applicable.
It seems to me that this is an example of the value of a computer science education. I guess that if you learn how to program from a purely practical approach, you may not be exposed to the more formal aspects of computer science. You might still learn how to write good tests, as there is material around written from a pragmatic perspective and you can work some things out for yourself, but it might be more a matter of chance. I also wonder whether university courses are making the links between the theory and the skills that can be transferred to the less formal approaches that are used in practice.
The main lesson for me is an understanding of the help that people may need when they are learning to write tests for the first time, or to create larger, maintainable test suites.
As part of his presentation, he advocated that tests should be written for interfaces not implementations, and in fact for protocols rather than interfaces. He contrasted an example of good practice, using a combination of externally visible methods to test behaviour, with a poor example that used a backdoor to twiddle internal state. He remarked that it was only when he started to write these sort of tests that he finally understood the oft-repeated mantra that logical models should be separated from the implementation.
This was my “Aha!” moment, as I realised why some people were finding TDD difficult. When I first encountered TDD, I already knew enough about specifying behaviour to let me write meaningful tests. I had several years’ experience of writing specifications using mathematical logic, and although you don’t use the actual language of mathematical logic to write tests, the mindset is very much applicable.
It seems to me that this is an example of the value of a computer science education. I guess that if you learn how to program from a purely practical approach, you may not be exposed to the more formal aspects of computer science. You might still learn how to write good tests, as there is material around written from a pragmatic perspective and you can work some things out for yourself, but it might be more a matter of chance. I also wonder whether university courses are making the links between the theory and the skills that can be transferred to the less formal approaches that are used in practice.
The main lesson for me is an understanding of the help that people may need when they are learning to write tests for the first time, or to create larger, maintainable test suites.
Comments