Consider the following sequence of events:
A()
that does a unit of workB()
that uses function A()
B()
to make sure no bugs are presentB()
cover function A()
As a result you have at least 2 tests covering some of the same functionalityQuestion 1: Was it worth it to write tests for function A()
to begin with?
Question 2: By following these steps code contains many tests that cover the same thing more than once. Is there a technique to avoid this?
ASSUME:
For the purposes of this question please assume that B does 2 things, one of which is A in its entirety
void performLifeChoice() { // B()
if (timeIsRight) {
askForPromotion(); // A()
} else {
goBackToSchool();
}
}
My general answer would be yes, it's worth writing unit tests for A(), for 2 reasons:
1) You may end up calling A() from a different context than B(), and in that case, you will be glad to know that A() is working, and avoid test duplication. If you didn't have a test for A() separately, you would end up re-writing what are effectively the same tests twice, for the equivalent branch of code.
2) Relatedly, if you don't test A() individually, you may end up having turtles all the way down. Imagine now that a function C() is calling B() in one of its branches, and D() calls C(), etc... If you follow the path of only testing the higher level function, you'll end up with an integration test which will have to cover a larger and larger set of pre-conditions. Keeping individual units tested with the smallest possible context allows you in principle to avoid that problem.
An implicit conclusion of my answer is that if A() will never, ever be called from a place other than B(), it might be worth making A() private, and at that point, testing may become "optional". One the other hand, keeping that test might still be useful, in that it will help you pinpoint that when B() fails, it's because you broke A(). In the words of Kent Beck, "if a test fails, how many things could be wrong? the closer the answer is to 1, the more "unit-y" the test is." - it's useful to have unit tests which help you pinpoint exactly where in your code things went wrong.
Now how could you go about testing B(), without in effect replicating the tests of A(), with added pre-conditions?
This is where Mocking/Stubbing or similar techniques can come into play. If you consider what B() is doing, it really isn't performing A(), it's acting as a "coordinator", piping conditions to various paths. An adequate test, in my opinion, would be "When TimeIsRight, then B() should call A()", the answer provided by A() is not relevant to B(), it's the responsibility of A(), which your unit test covers.
In that frame, what a test on B() should Assert is that A() is called when TimeIsRight, not what A() returns. Depending on the specifics of your code, you may consider making A() "substitutable" within B(), for instance via an interface, or via a function that is injected in place of A().
As the methods seem to be in the same class,
If A()
is private, just test B()
. A()
will be tested as part of B()
's test.
If A()
is public, don't test it as you test B()
. Verify A()
's correctness in a separate test. Then in another test, just check that B()
calls A()
properly. In your example, it would mean verifying if askForPromotion()
was called in timeIsRight
circumstances.
Note that things would be slightly different if A() and B() were in separate classes.
By the way, with a TDD approach, the order of your events should be 2. 1. 4. 3. ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With