I think it was Brian Marick who pointed out that the great benefit of a coverage report is that it tells you what you forgot to think about when you wrote the test suite. One response to code that isn't covered is to write the tests to exercise that code, but there are a couple of other possibilities he suggests might be better:
1. Can the uncovered code be removed from the system entirely? Maybe if none of the tests for other parts of the system invoked it, it's not used at all. (This is less likely if you use a lot of test stubs.)
2. Maybe if you didn't think about the scenario where the uncovered code gets invoked when you were writing the test suite, there are other things you also didn't think about—and maybe some of them aren't covered in the implementation either. Write down the missed case and put the implementation away for a while—hopefully long enough to forget how it's implemented. Once you've forgotten, refer to your notes and write a suite of tests that covers the missed case as well as anything similar.
— ⁂ —
I agree that test-first improves your tests in the way you describe: your test suite is guaranteed to have nearly complete coverage. Also, you have some evidence that the test itself works rather than vacuously passing.
But I think there are two other benefits of test-first programming that are commonly undersold.
First, it makes programming more fun, because you have immediate feedback when you make a test pass.
Second, sometimes you write a test for code you haven't written yet, and you can see by looking at the test that your design sucks: you need seven objects and six method calls to do something simple, and one of the method calls has a boolean parameter, making the code incomprehensible. This feedback allows you to improve your design, possibly several times, before writing the implementation. This allows for faster design iteration than refactoring the implementation toward a better design does. I think this is what jeffbee is saying in https://news.ycombinator.com/item?id=28677978.
I find test-first most useful when debugging a hairy problem, and I think that's somewhere it's not used enough.
Reproducing the bug consistently* is the first step to understanding how it works, and how to fix it. And then you get the thrill of trying to turn that test green as you tinker.
...
* Okay, sometimes "consistently" is "fails about 1/100 executions", but that's not so bad if you can run your unit test 1000 times in the span of 30s.
1. Can the uncovered code be removed from the system entirely? Maybe if none of the tests for other parts of the system invoked it, it's not used at all. (This is less likely if you use a lot of test stubs.)
2. Maybe if you didn't think about the scenario where the uncovered code gets invoked when you were writing the test suite, there are other things you also didn't think about—and maybe some of them aren't covered in the implementation either. Write down the missed case and put the implementation away for a while—hopefully long enough to forget how it's implemented. Once you've forgotten, refer to your notes and write a suite of tests that covers the missed case as well as anything similar.
— ⁂ —
I agree that test-first improves your tests in the way you describe: your test suite is guaranteed to have nearly complete coverage. Also, you have some evidence that the test itself works rather than vacuously passing.
But I think there are two other benefits of test-first programming that are commonly undersold.
First, it makes programming more fun, because you have immediate feedback when you make a test pass.
Second, sometimes you write a test for code you haven't written yet, and you can see by looking at the test that your design sucks: you need seven objects and six method calls to do something simple, and one of the method calls has a boolean parameter, making the code incomprehensible. This feedback allows you to improve your design, possibly several times, before writing the implementation. This allows for faster design iteration than refactoring the implementation toward a better design does. I think this is what jeffbee is saying in https://news.ycombinator.com/item?id=28677978.