1. Design it right the first time, tests and all.
2. Build a throwaway, no tests, little refactoring as you quickly iterate
Programmers who fall into category 1 in my experience mistakenly believe that they understand the requirements of the software they are writing. Category 2 programmers tend to be ones who actually deal with users/real world, and know that they don't understand the requirements.
My position is that if you are building something for the first time, you are going to get it wrong, so get it wrong as quickly and cheaply as possible. This means getting it in front of users as quickly as possible, bugs and all.
I often find that I unit test all but the latest layer. As soon as I start depending on code from something else, it's time to write some tests. But if I just wrote something, it's probably in flux and tests would just prematurely lock down the interface. Write the code, write the client (which probably requires that you rewrite the code), and then write the tests in lieu of debugging the code.
Hasnt it been done already? Couldnt find anything I would class as 'scientific' with a quick google search. Would be a good thesis for someone.
If I'm constantly changing my mind about how best to do something, I don't want the massive overhead of having to change unit tests all the time as well.
I'll test as I go, in the code.
Unit tests should hook into the application in such a way that you can reorder the GUI and change nothing.
If you are using Unit tests correctly then any change to the code base at worst requires 10% of that effort to change the test cases. If you can think of any meaningful change that is worse then that your something is wrong with how you're testing.
The tests tell you where the tests fail. Some of those failures may be due to bugs, and others may simply due to the way your code now works.
Which highlights one of the "problems" with unit tests: if something fails, you have to take time to go and fix it. If you have no tests, you can assume there are no bugs because you are such a great programmer, then go home after a job well done.
That there actually are bugs there doesn't bother you, because you don't know about them. It takes less time to write buggy code.
No. More often than not, if you change was a large architectural one, which is often the case in young software, your tests are now irrelevant, or broken.
>> "It's the difference between walking with your eyes open or closed... it may be more work to process all that information about obstacles, but it sure is helpful if you want to avoid those obstacles."
Do you seriously think people are just blindly coding and never testing anything here?
while(true) {
writeABitOfCode();
while (!compile()) fixCompilationErrors();
testThingsYouMightHaveChanged();
checkLogsForIssues();
}If you change that into writeAnAutomatedTestForItAndRunYourTestSuite() you get the following benefits:
1) Every test you write accrues value onto your test suite and helps you avoid problems later;
2) You don't need to spend time to figure out what you might have broken with your change - your test suite tells you in seconds;
3) You can say with some measure of certainty that it's extremely unlikely that your change broke anything.
while (!compile()) {
fixCompilationErrors();
fixUnitTests();
rewriteUnitTestsThatNoLongerMakeSense();
WriteNewUnitTests();
}
Your iterate loop just became maybe twice or 3 times as long. Less iterations = worse code.Delete em. You should be iterating your unit tests.
Over time you will find some really useful unit tests for common mistakes, and others that are basically useless. Try and approach things from the perspective of what you would like to know works and not just tossing everything and the kitchen sink at the problem. When you find a bug add a unit test just in case it comes back, if you change major parts of the system, port the most useful unit tests and delete the rest.
I think of unit tests as saving you from the (I thought I just fixed this) problem.
PS: The major advantage of this approach is you keep adding more tests to the older parts of the system, which are also the most costly to change because other parts of the system assume it works. And assumptions you and your code is making can be really hard bugs to find and fix.
1) You don't bother testing much. You make lots of changes, iterate quickly. Before the changes, you have code that, let's say, you know works. After the changes, you know there's probably bugs, but you don't know where.
2) You test fairly thoroughly. You make lots of changes, iterate quickly. Before the changes you have code that you know works. After the changes, you know where most of the bugs are because your tests tell you where they are.
It's the difference between walking with your eyes open or closed... it may be more work to process all that information about obstacles, but it sure is helpful if you want to avoid those obstacles.