|Written by JLangbridge|
|Wednesday, 24 December 2008 19:10|
A few days ago, I had the pleasure of doing a bit of pair programming with OT, the lead developer of a small software company. It was a pleasure, but it cost me a few aspirins...
He's seen me code, and he knows of (part) of my background. I haven't told him everything, but there again, I can't. Anyway, he knows enough. He showed me the benefits of Extreme Programming, and why I should use it. I'm interested in any technique that I can get hold of, and even if I am fond of prints, printfs and the lot, I'm not the sort to ignore any advice. So here we go, peer programming, with Olivier starting a new Python project.
The first thing you notice, once he creates the general structure with all the files and folders, he created a test.py file. The name is self explicit, but I was still wondering why. Ok, so here we go! We need to create an RPC client that talks to a server. The real life applications are countless, this is simply a generic program to start off another project, or just to show off the advantages of Python, whatever. First thing we need to do is to create a proxy server that our python script can talk to, and that will answer us. The proxy is then responsible for sending out RPCs and getting back to us when it is done. Its a simple slave. So! First thing we do, open up tests.py, and create a test. Ahem... Ummm... We haven't done the proxy yet? The answer was "Exactly". I smiled, shut up, and watched him code. He wrote a test for a proxy that didn't even exist. "I want to talk to my proxy, and this is what I want it to answer". A few lines of simple code later, off we went, for a make test. It failed, miserably. What did you expect? So, now that the test has failed, let's make it pass.
The idea of creating a test and then writing the code was interesting, but I still didn't see the advantage to it. I'll admit that in all the code I've written up until now, I've never made any test framework or test structure other than the typical. So off he goes to code his proxy, and once he's done, he fires up make test again, and it fails. He expected x, and the proxy answered y. Now things get interesting. His routine looked good, seemed to act well, but here we have a test that is supposed to work, and the result is strange. The test itself is elementary, and a test script looks like a first year developers course. x = MyRoutine(2), then check that x = True. So if MyRoutine is sent the number 2, it has to return True. Simple! But why didn't it work? We made a simple mistake, one that got past both of us. It didn't get by the test, though. Olivier wouldn't have been affected by this, and indeed he wasn't. He made a make test, just like he did every 5 minutes afterwards, and he was told of a problem. I, on the other hand, wouldn't have seen this immediately, and I probably would have spent some quality time with a debugger checking things over and over.
The idea of writing tests before even beginning some code suddenly appealed to me, and I can even remember a big 4-month project where unit testing would have saved me hours, and probably days, of debugging. Don't you just hate it when you want to go home, but you can't? The make fails, and you just can't leave the office until everything is done. I've returned home well after midnight from time to time because of that, and I've taken work home with me on an almost daily frequency because of that. And here we go, we make a test that will fail, even before we write anything. All those nightmares coming back at me... But, no. This is a simple test, and if ever on the third or forth attempt at getting the thing to work, it still doesn't pass the test? Delete the code, and restart. Once it's done, re-make test. Then write a test for the second bit of code that you will write. At the end of the day, you might have run dozens, maybe even hundreds of make tests, but you will never find yourself in a situation where you will be submerged in errors, because you know exactly what works, and what doesn't yet pass the test. I've learned that there are things that you know don't work, and that there are things you are convinced work. Now here comes a new element, things that I know work. And even better, if ever you change some lines that risk affecting the rest of the application, who cares? If it does create a conflict, the make test will show it immediately.
Since that day, I've been making tests for almost everything that I do. I've done some more peer programming with Olivier, and even if I do get shouted at from time to time because I still write print commands, I do so less and less because tests are just so simple. Test it to death. Test that it works when I do this, and even test that it doesn't work when I do that.
So, unit testing? Fun, constructive, quick. Quick might sound strange because you write more code, but even if you do write more code, you spend less time debugging. This was my first real approach to Extreme Programming, and I can't wait to try that again.
|Last Updated on Sunday, 08 March 2009 21:36|