开发者

TDD procedure for writing tests for a function with multiple execution paths

While following test driven development, I came across a function that I need to write which is similar to the following:

public MyClass DoSomething(string v开发者_运维知识库alue)
{
    SomeClass existCheck = repository.Get(value);

    if(existCheck == null)
        throw new InvalidOperationException("SomeClass must exist to do something");

    if(existCheck.MyClass != null)
        return existCheck.MyClass;

    MyClass myClass = new MyClass()
    {
        // create object
    };

    return myClass;
}

Using TDD, I would need to write seperate tests to

  1. Assert that the exception is thrown
  2. Assert that an existing SomeClass is returned
  3. Assert that a new MyClass is returned

Do I write all three tests first then code them or do I write each test, then code the functionality in the function required for the test to pass and then write the next test and the code the functionality etc.?


I've always believed that with TDD you should take baby steps, with the Red-light Green-light approach. I would proceed in the following steps:

  1. Write a test for the existCheck == null scenario, which will fail (Red-light)
  2. Do the necessary work for scenario 1 to succeed, and re-run the test (green-light)
  3. Write a second test for the existCheck.MyClass != null scenario, which will fail. You could often do this by copying your first test and modifying it.
  4. Modify the method so that both tests 1 and 2 pass.
  5. Repeat steps 3 and 4 for the final execution path.

Generally, I find you can progress with a test as the method proceeds, and then copy the test each time you reach a branch, tailoring each test to each differing path.


The basic workflow of TDD is red/green/refactor:

  1. Write the test first, it should fail (red).

  2. Write as few production code (and as simple as possible) to make the test pass (green).

  3. Refactor the production code preserving the green status.

If you discover that not everything is yet implemented, start from point 1. So in your case - you might either write all the tests first and then implement everything or write test for the first branch, make it green by writing first condition, write test for the second branch, make it pass, etc.

In my opinion it's nice to have a full problem description (full test suite) before starting the actual code, rather then switching back and forth from test to production code.


Write a separate test for each expected behavior.

A good rule of thumb is that each test should usually contain a single assertion.

Edit -- Answering the question that was actually asked...

The TDD process is to write each test, make it pass, and then refactor what you did. Only after that is done should you proceed to write the next test.

Technically, you can write other tests up-front, but comment them out, so it's as if they have not yet been written. Spend very little time on future tests though, because you may discover that they are the wrong tests based on what you do to make the first one pass, and then refactoring that you do afterward.


It depends on your angle of attack. If you have the entire pattern of the class figured out -- and your question suggests this -- Then you write all tests. If your code evolves in smaller steps, then you do a test at the time. The key point of TDD, is to write the test first.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜