Saturday, August 6, 2011

Living with observational tests

I'd say that at least half of the unit tests I look at end up having a ton of extra work and extra assertions. It's always really frustrated me but I think some developers just find this style of tests to be more helpful. I think some people view tests as a central claim with proof and others view it as a record of observations.

I view unit tests like a math proof or logical argument. I have a claim (also known as an assertion) and I have the simplest proof of that claim I can think of. If my claim is that new bank accounts start with a zero balance then my test will mention the claim in the title and assertion. Maybe something like this:

[Test]
public void NewBankAccountShouldStartWithAZeroBalance()
{
    BankAccount newBankAccount = new BankAccount();
    Assert.AreEqual(0, newBankAccount.Balance, "A new bank account should start with a zero balance.");
}

My recent insight is that others seem to view tests more like a record of observations. Imagine walking through a park and writing what you see and hear along the way. "There's a dog. The dog is barking. There's a tree. There's a guy in a suit. The dog is still barking. There's a jogger." etc. Many of the unit test I see are like this, a walk through some scenario or object lifetime with observations made along the way:

[Test]
public void BankAccountTest()
{
    BankAccount account = new BankAccount();
    Assert.IsTrue(account != null, "The account is not null");
    Assert.IsTrue(account.Balance == 0, "The balance is zero."); 
    
    account.DoSomething("ABC", 123);
    Assert.IsTrue(account.Things.Count == 3, "The account has three things."); 
    Assert.IsTrue(account.Balance == 0, "The balance is zero."); 

    // 60 more lines of stuff somewhat related to bank accounts....
}

My frustrations came from realizing that these tests were written differently than what I prefer but not realizing that it's because there's a completely different way of looking at what a test is. The assertion messages are worded differently, the test is named differently, the assertions are different, the only similarity is that both styles are run from NUnit. These aren't unit tests in the strict meaning, they aren't integration tests, and they aren't really system tests; they're what I think of as observational tests — just a bunch of observations. I couldn't figure out what the point of this kind of test was because there is no point to the test. The assertions seemed irrelevant or superfluous because the assertions aren't used as proof of a central claim, they're just things that the original developer noticed or had on his mind when writing the test. They don't say what something should be or why because they're just observations of how things are — there is no expectation or reasoning behind it — just a bunch of observations.

I'm still not sure what to do with failing assertions on these observational tests. I don't want to delete the entire test because they provide some value to someone (well, actually yes I do want to delete them but I won't). These observational tests often fail but I've never found a bug in the code from these; it's always been a bad test or a valid change in the code that broke the now invalid assertion. There's no point in trying to change the developers who like these tests since not only do they prefer these observational tests but I've already tried and failed. I think that if it doesn't look like an obvious bug then I should just update the assertion or delete it. That's what I've always ended up doing anyway but now I won't waste more than a couple minutes on it since it's not worth the frustration.

No comments:

Post a Comment