Soteric
Soteric

Reputation: 3120

One unit per case or one unit per assert(s)

In unit-tests should I write one unit per case or one unit per assert from support cost point of view? I have the following code

void methodUnderTest(Resource resource) {
    if(!resource.hasValue()) {
        Value value = valueService.getValue(resource);
        resource.setValue(value);
    }

    // resource.setLastUpdateTime(new Date()); // will be added in future
    db.persist(resource);
    email.send(resource);
}

The commented line will be added in near future and I think what it will cost to update units.

As far as I see there are two ways to test this code.

  1. Write 2 units passing resource with value and without value. In both tests verify that db.persist and email.send were called. When LastUpdateTime is added I'll have to update both tests to verify the property was set.

  2. Write separate unit tests: one checks that db.persist was called, the other checks email.send, third and fourth for resource with and without value. When LastUpdateTime is added I just write new unit.

I like the second way because I like the idea that I won't have to touch working units. But that would be probably a lot of code duplication because actually all 4 tests do the same and only use different asserts.

The first approach looks more correct from 'just one concept per unit test' point of view. But aren't such tests hard to maintain? Adding something new I will always have to revise all existing tests and it doesn't sound good.

Is there some best practise here I should follow?

Upvotes: 0

Views: 52

Answers (2)

Aaron Digulla
Aaron Digulla

Reputation: 328780

There is no general answer for this. You need to balance your needs and constraints:

  • If a test is small, executes quickly and fails very rarely, there is no reason to split it into several.
  • If you have many assertions in a single test, then all of them probably provide value towards figuring out why the test fails but only the first one will be executed, keeping you from valuable information. Try to have only a single assert per test (combine the assertions into one big string, for example).
  • If you test several features in a single test, you have a variant of the "missing valuable information." If each test tests a single feature, the combination of succeeded and failed tests may give you the clue why they fail. Try to aim for a single feature per test.
  • Lastly, it gives me a good feeling when I see thousands of tests being executed.

Upvotes: 0

Ber
Ber

Reputation: 41873

I propose you put the common stuff of all tests into the setUp() for the tests, the have exactly one assert per unit test, as in your second way of testing.

When you add the new line of code, you just add one more test case with a single assert.

Not modification of existing tests, not code duplication.

Upvotes: 2

Related Questions