9

I have been doing a number of tests for developing using TDD; i.e write my test first.

I have always been used to writing the test like so, using this naming convention.

  MethodName_DoesWhat_WhenTheseConditions

These work great for unit testing as I am aware of what the method names are, but doing TDD I am not aware of the method names. For example I have a user story that states

    "As a user, I can return the total number of records in the database"

Now just taking a look at this, I know straight away that I will have a number of methods, layers.

But I don't know the names of these methods right now in TDD, so does it make sense to try and prefix the test names? Does anyone have any advice here?

Also once I have written my tests and my methods/classes and everything is working does it make sense to create additional "unit tests" to test the class for things I didn't via TDD?

1
  • 1
    Did any of these answers help? Did you find a resolution to your problem?
    – Ben Smith
    Commented Jul 22, 2014 at 13:41

4 Answers 4

6

By following an "Outside-In" development approach you would discover/evolve your TDD unit test names as part of the development process (also see this answer here)

For example take your user story (I've slightly amended it):

As a user
I want to know the total number of records in the database
So that I can report back to the business owner

When developing this story you would break it down into a number of scenarios e.g.

Given a user logs in
When they request the total number of records
Then they should be presented with the result

At this stage you still don't know what unit tests you would need. However, using the "Outside-In" development approach you would now revert to TDD techniques to implement the necessary functionality.

For example you would next implement the log-in facility using your normal TDD approach. Hence you might have a test method called:

WhenSubmitValidCredentials_ShouldBeAuthorised

You can also "fake it until you make it" using this approach i.e. you can mock certain dependencies (e.g. the authorisation mechanism) so that you can focus on implementing the key features of the scenario.

So following this approach you would incrementally develop all of the functionality required for your User Story whilst creating the exact unit tests to satisfy the scenarios.

4

Given your user story, my test names would be something like:

  • shouldGetZeroWhenTheDatabaseIsEmpty
  • shouldGetOneWhenThereIsOneRecord
  • shouldGetTwoWhenThereAreTwoRecords

And the test class would be something like DatabaseRecordCounterTest.

2

There are many approaches to test naming, the one you mentioned being one of them. Prefixing with method name is good (and suitable for most-many cases), yet you might run into minor issues when your unit test spans through multiple methods (i.e. common add-remove or add-search combinations).

With TDD, you should start with user story (as you do now) and name your test accordingly. Only then you go to implementation. With TDD, your methods names will be driven by tests.

Also once I have written my tests and my methods/classes and everything is working does it make sense to create additional "unit tests" to test the class for things I didn't via TDD?

There should not be a single thing you don't do via TDD. That's the whole point -- you drive your design and implementation via tests. You don't write single line of code that would not originate from failing test.

0

I like using two methods which I stole from Phil Haack and Erik Dietrich

Basically there is a base class that defines the class under test, then inherited classes that are named after the behavior they will test. Tests are then added with verbose names.

public class TestClassUnderTest
{
    public ClassUnderTest Target { get; set; }
    [SetUp]
    public void before_each_test()
    {
        Target = new ClassUnderTest();
    }

    // Now each behavior has its own class with the system under test available through the Target property
    public class ThisMethod : TestClassUnderTest
    {
        [Test]
        [ExpectedException(typeof(Exception))]
        public void throws_if_null_is_passed()
        {
            Assert.IsTrue(false); // make it fail at first
        }

        [Test]
        public void returns_true_if_string_is_empty()
        {
            Assert.IsTrue(false); // make it fail at first
        }
    }

    public class ThatMethod : TestClassUnderTest
    {
        [Test]
        public void returns_argument_concatenated_with_timestamp()
        {
            Assert.IsTrue(false); // make it fail at first
        }
    }
}

With this system the test class name (in this example ThisMethod and ThatMethod) can be abstracted into the behavior aspect you are testing against until naming can make sense. You can start by naming it after the desired behavior, and then either refactor the behavior name into a function name if applicable, or refine it (for example if the behavior spans multiple methods, eg: InstanciatioAndInitialization with a test initialization_must_be_called_before_any_other_calls_to_the_system). A nice bonus is that all tests are grouped logically into the same context, which renders nicely in you test UI.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.