Beyond Unit Testing => Specification of Intent

It seems like every day my unit testing style becomes more and more stylized and it seems I am driving toward something specific, elegant and readable. I want my tests to not only validate that the code does what I think it should do, but it also tells the story of what is happening and how. The latest permutation of this obsession has me focusing on the context of my specifications. Why have lines and lines of object initialization code when I can instead explicitly state the context that the tests are running under in an expressive way?

Consider the two following code samples. Does either help you to understand the intent of the system under test? Which do you prefer? Why? Do you find it silly? Pointless?

Old & Busted:

[TestFixture]
public class when_getting_the_import_status_and_all_files_exist_for_a_date : with_a_imports_controller
{
    private FileLoadStatus fileLoadStatus;

    public override void Context()
    {
        base.Context();
        var logs = new List { new FileLog { Id = 1, WasSuccessful = true } };
        var types = new List
                        {
                            new FileType()
                                {
                                    Id = 1,
                                    Name = "foo",
                                    Logs = logs
                                }
                        };

        logs.Each(x => x.Type = types.First());
        fileLoadStatus = new FileLoadStatus
                             {
                                 FileTypes = types,
                                 Logs = logs
                             };

        looker.Stub(x => x.GetStatusFor(Clock.Yesterday)).Return(fileLoadStatus);

    }

    public override void Because_of()
    {
        result = controller.GetStatusFor(Clock.Yesterday);
    }

    [Test]
    public void I_should_get_a_file_type()
    {
        result.FileTypeStatuses.Any(x => x.Name == "foo").ShouldBeTrue();
    }

    [Test]
    public void I_should_see_a_file_type_with_an_OK_status()
    {
        result.FileTypeStatuses.Where(x => x.Name=="foo")
            .FirstOrDefault().Status.ShouldBe("OK");
    }

    [Test]
    public void I_should_get_a_log_for_the_file_type()
    {
        result.Logs.Any(x => x.Id == 1).ShouldBeTrue();
    }
}

New Hotness?:

[TestFixture]
public class when_getting_the_import_status_and_a_file_has_loaded_twice_and_failed : with_a_imports_controller
{

    private FileLoadStatus fileLoadStatus;
    FileType fileType;

    public override void Context()
    {
        base.Context();
        fileType = I.Have().AFileType()
            .WithALogFile().ThatProcessed(Clock.Yesterday).ThatSucceeded()
            .WithALogFile().ThatProcessed(Clock.Yesterday.AddMinutes(10)).ThatFailed();
        fileLoadStatus = fileType.ToFileLoadStatus();
        looker.Stub(x => x.GetStatusFor(Clock.Yesterday)).Return(fileLoadStatus);
    }

    public override void Because_of()
    {
        result = controller.GetStatusFor(Clock.Yesterday);
    }

    [Test]
    public void I_should_get_the_filetype()
    {
        result.FileTypeStatuses.Any(x => x.Name == fileType.Name).ShouldBeTrue();
    }
    [Test]
    public void I_should_see_the_file_type_with_an_Failed_status()
    {
        result.FileTypeStatuses.Where(x => x.Name == fileType.Name)
            .FirstOrDefault().Status.ShouldBe("Failed");
    }

    [Test]
    public void I_should_see_two_logs_for_the_file_type()
    {
        result.Logs.Count().ShouldBe(2);
    }

}
Follow me on Mastodon!