Holistic Solution Creation Part 2 - Test First Design advice from a really bad example

In contrast to what you've just read in the title, I actually really like Test First Design (TFD) and try to embrace it at every opportunity. Unfortunately I am about to pick one of the worst examples I could possibly to illustrate using it.

Let's quickly review the functionality we are trying to implement from FtpTask not quite right.

  • FTP Upload, Download and Delete
  • Runs as MsBuild task
  • WinForms GUI to create and Test MsBuild Task
  • Console App with command line arguments

I want to deal with Unit Testing a UI later, and for now lets discard the MSBuild Task and console applications as well as they are only frameworks that call the functionality. That leaves the core FTP functionality, the SiteFTPEngine class, which is responsible for the uploads or downloads and of an entire site by gathering a list of files from either the file system or the FTP Server, and then transferring them to the opposite location.

Unit Testing should be isolatable

As we consider our Unit Testing we have to bear in mind that the unit tests will be run on multiple machines, at least on the developers machine and the build server. Unfortunately we cannot guarantee that an FTP server or even a file system will be available (and write-able to without admin rights)  at all times and so therefore the best thing to do is to mock them out. That leaves us with an interesting decision of where to draw the line on the mock.

So what do we test

We can mock at too low a level. I can implement a mock at the FTPWebRequest level. This would require a lot of time and investigation into RFCs. Currently I know that 200 is the status code for a success, but how many other statuses are there?

Conversely if I mock and too high a level, I miss testing any functionality at all. Consider the functionality in an Upload.

Get a list of files from the local machine and transfer each one to the FTP server.

If I mock out the file system and the FTP server, that leaves me with

Get a list of files from a mock and transfer each one to another mock

But I know nothing about FTP...

Here's a very radical point.

I believe that just because not everybody can run your unit tests does not mean that you shouldn't create them.

The ultimate benefits in Unit Testing come from the tests being repeatable and ultimately be used in continuous integration builds, such as via a cruise control server.

The benefits in Test First Design come from writing tests before writing functionality, and using those tests to prove that functionality.

I think this really bad example is actually a fantastic edge case. According to the common rules of Unit Testing there is very little I would attempt to write a test for. However I can write and test lots of functionality by writing tests that may never be run anywhere except on my development box.

Developer Tests

I personally have never used the FTPWebRequest object in anger before. I didn't for example, have any idea that each Server type can implement its own format for the ls command. When I tackled this piece of work, I started by setting up a local FTP server on my machine. Now I could guarantee that I had an FTP server and a File System. This meant I could use TestDriven.Net to run a single test in the debugger and check exactly what format the IIS 6.0 FTP server produced directory listings in. Later I could perform the same test against a Server 2003 box and ultimately against a Server 2008 machine. I just know there's no point in trying the same on my cruise control machine.

Conclusion

You add value by providing test harnesses that can be used to test functionality. nUnit/mbUnit is one of the best harnesses around due to its simple nature for writing those tests. However those same test runners encourage all tests to be run all the time. Sometimes you can get really useful development assistance by writing a test that isn't going to run by the test runner, particularly by a continuous integration server. nUnit/mbUnit even give you the chance to

Add comment

  Country flag


  • Comment
  • Preview
Loading