tags:

views:

382

answers:

4
+7  Q: 

TDD ...how ?

Hi,

I'm about to start out my first TDD (test-driven development) program, and I (naturally) have a TDD mental block..so I was wondering if someone could help guide me on where I should start a bit.

I'm creating a function that will read binary data from socket and parses its data into a class object.

As far as I see, there are 3 parts:

1) Logic to parse data 2) socket class 3) class object

What are the steps that I should take so that I could incrementally TDD? I definitely plan to first write the test before even implementing the function.

+3  A: 

Your split sounds reasonable. I would consider the two dependencies to be the input and output. Can you make them less dependent on concrete production code? For instance, can you make it read from a general stream of data instead of a socket? That would make it easier to pass in test data.

The creation of the return value could be harder to mock out, and may not be a problem anyway - is the logic used for the actual population of the resulting object reasonably straightforward (after the parsing)? For instance, is it basically just setting trivial properties? If so, I wouldn't bother trying to introduce a factory etc there - just feed in some test data and check the results.

Jon Skeet
+1  A: 

Test Driven Development ? So, this means you should start with writing a test first.

Write a test which contains the code like 'how you want to use your class'. This class or method that you are going to test with this test, is not even there yet.

For instance, you could write a test first like this:

[Test]
public void CanReadDataFromSocket()
{
     SocketReader r = new SocketReader( ... ); // create a socketreader instance which takes a socket or a mock-socket in its constructor

     byte[] data = r.Read();

     Assert.IsTrue (data.Length > 0);
}

For instance; I'm just making up an example here. Next, once you're able to read data from a socket, you can start thinking on how you'll parse it, and write a test in where you use the 'Parser' class which takes the data that you've read, and outputs an instance of your data class. etc...

Frederik Gheysels
Agree with the first two sentence, but what's about assertation? An AAA example would be better, I think.
boj
Yes indeed; defenitly, you have to test in your test whether or not the results are as expected.
Frederik Gheysels
+4  A: 

The issue in TDD is "design for testability"

First, you must have an interface against which to write tests.

To get there, you must have a rough idea of what your testable units are.

  1. Some class, which is built by a function.

  2. Some function, which reads from a socket and emits a class.

Second, given this rough interface, you formalize it into actual non-working class and function definitions.

Third, you start to write your tests -- knowing they'll compile but fail.

Part-way through this, you may start head-scratching about your function. How do you set up a socket for your function? That's a pain in the neck.

However, the interface you roughed out above isn't the law, it's just a good idea. What if your function took an array of bytes and created a class object? This is much, much easier to test.

So, revisit the steps, change the interface, write the non-working class and function, now write the tests.

Now you can fill in the class and the function until all your tests pass.

When you're done with this bit of testing, all you have to do is hook in a real socket. Do you trust the socket libraries? (Hint: you should) Not much to test here. If you don't trust the socket libraries, now you've got to provide a source for the data that you can run in a controlled fashion. That's a large pain.

S.Lott
+2  A: 

First, start thinking "the testS", plural, rather than "the test", singular. You should expect to write more than one.

Second, if you have mental block, consider starting with a simpler challenge. Lower the difficulty until it's real easy to do, then move on to more substantial work.

For instance, assume you already have a byte array with the binary data, so you don't even need to think about sockets. All you need to write is something that takes in a byte[] and return an instance of your object. Can you write a test for that ?

If you still have mental block, lower it yet another notch. Assume your byte array is only going to contain default values anyway. So you don't even have to worry about the parsing, just about being able to return an instance of your object that has all values set to the defaults. Can you write a test for that ?

I imagine something like:

public void testFooReaderCanParseDefaultFoo() {
  FooReader fr = new FooReader();
  Foo myFoo = fr.buildFoo();
  assertEquals(0, myFoo.bar());
}

That's rock bottom, right ? You're only testing the Foo constructor. But you can then move up to the next level:

public void testFooReaderGivenBytesBuildsFoo() {
  FooReader fr = new FooReader();
  byte[] fooData = {1};
  fr.consumeBytes(fooData);
  Foo myFoo = fr.buildFoo();
  assertEquals(1, myFoo.bar());
}

And so on...

Morendil