Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Info

We are going examine the benefits of using TDD as a design technique and see what the benfits are if we follow a TDD approach to developing production code.

Phase 1

Write the unit test first for a CUT called FileLoader.  It should only have one public method on it.  Once the test is written develop the CUT to pass the test.

...

The above function should load a text file from the disk, and return the number or characters in it.

Your test should specify the input the file name including its path, and the number of characters expected be in the file.

Assert on the actual file length (number of characters in the file) against the expected file length (number of characters read from the file)

In the production class we suggest you use something like File.ReadLines()

Once you have completed the above test and production code, think about this question

  • Question: What’s the weakness of this design

A solution can be found here

Phase 2

Write the unit test first for a CUT called FileLoader.  It should only have a new public method on it.  Once the test is written develop the CUT to pass the test.

In order to facilitate your design, you need to think about the structure of the test

  1. In the //Act part of the test, we want to write something like this

Code Block
        // act
        int bytesRead = cut.LoadFile(fileToLoad, (fname) =>
        {
            Array<string> result = null;
            try
            {
                result = File.ReadLines(fname);
            }
            catch (IOException e) { }
            return result;
        });

...

By moving the mechanics of how a file is loaded into FileLoader we’ve decoupled the functionality. This new design now means we can instruct FileLoader to load a file resource in different ways, not just using the standard file IO.

So the test has forced us to think carefully about what we think is the purpose of FileLoader. Our initial intent may have been to load a file from the disk, which is can do, but we have broadened it’s design so it is more flexible and less brittle.

Once you have completed the above test and production code, think about this question

  • Question: What’s the weakness of this design

A solution can be found here

Phase 3 - working stubs

The phase 2 test was weakened by the fact that It broke one of the tenants o a good test

...

You should not have to change the CUT.

Once you have completed the above test and production code, think about this question

  • Question: Can we further improve the test

A solution can be found here

Phase 4 - working with mocks

Info

Mocks are not stubs

A Mock can be used to create Stubs, and Dummies

A mocking library will create a dummy object that must be populated with methods that have predefined results and parameters

...

A solution can be found here

Do expectation parameters really matter?

Let’s look at the code

Code Block
languagec#
            var file = Substitute.For<MyFile>();
            file.ReadLines(fileToLoad).Returns(pretendFileContent);

            // act
            int bytesRead = cut.LoadFile(fileToLoad, (fname) =>
            {
                IEnumerable<string> result = file.ReadLines(fileToLoad);

                return result;
            });

...