Reputation: 5670
If I am not too sure of which of following tests would be necessary or redundant. Consider unit testing the following code:
public class Locker {
public enum Type { FOO, BAR, FOOBAR };
private Locker() {}
public boolean shouldlock (int x) {
return x > 10;
}
public boolean lock (Type type, int x) {
switch (type) {
case FOO : return shouldlock(x);
case BAR : return shouldlock(x * 2);
}
return false;
}
}
Test case 1: test shouldlock
for both true and false case. - no doubt so far.
Question 1
:
Test case 2: lock
for input type Foo
also be tested for true and false cases, ie both of them. ? Underlying its calling shouldlock
and we have already tested both cases for it. Thus it may be redundant. But not too sure.
Question 2
:
Test case 3: Assuming answer to Question1
is true, do we still need to test Bar
for true and false case ?
Question 3
:
Test case 4: Assuming answer to both Question1 and Question2
is true. Assume now shouldlock
is changed to private (just assume it). Would the only difference in testing be that I should omit Test case 1
?
Question 4
:
Test case 5: Is it required to check that the only left out enum FOOBAR
returns false ?
Question 5
:
Assuming answer to question 4 is true, then what if enum tomorrow contains 100 more items ? How to scale such a test ?
Upvotes: 2
Views: 301
Reputation: 30320
I know this is a contrived example for the sake of the question, so I will answer in general.
You want to test with as many inputs as it takes to satisfy yourself that the code works. Sure, you might miss something, but the test will be there when you need to recreate the bug later.
In the case of shouldlock
, I would test with a set of integers that ease my mind that the code works--like a very low negative number, a very high positive number, 0, and more representative numbers you expect as input.
As far as lock
, your questions suggest you are thinking in terms of implementation, which I believe is a mistake. You need to think in terms of the clients of the method. Specifically, don't say "Do we still need to test for BAR
?" Rather, you just need to think of a reasonable number of ways your method can be called by a client and test accordingly. This means with all your enum
values.
In terms of scale, I think the question is moot because the difficulty of testing with a 100-item enum
(as unlikely as that is) suggests you should change the implementation, so your method would probably change. Your tests would then reflect that.
As for changing a method to private
, then you don't have to test it anymore. Only your public API needs to be tested. You might want to add assertions to those methods though.
The bottom line is don't agonize over 100% test coverage. There are diminishing returns, and when a bug is found, you will have a test available to reproduce it and fix it.
Upvotes: 1
Reputation: 945
shouldlock
and verify that it is called with x
(probably using a constant value for the test). Using something like Mockito and have it call the real method only when calling lock
.shouldlock
is called wtih x * 2
.FOO
with 10 and 11, BAR
with 5 and 6.FOOBAR
is required.Upvotes: 1
Reputation: 4623
First of all, it depends which are the scenarios your code has to take care of. With this perspective, you can think about approaching your work in a test-driven development (TDD) manner, in which you first write the tests that should cover your desired functionality, and than write the code that make your tests pass.
With this approach, there are no general valid answers for your questions. It only depends on what you need and how rigorous you need to be.
Second, you can approach your unit tests with the following idea in mind: make the unit tests code coverage as high as possible. I'm thinking here mostly about the line coverage and the conditional coverage. This means that the code that is executed during unit testing should be comprised of as many lines as possible and it should cover as many conditional branches as possible, respectively.
Also, with this approach, you might want to reduce redundancy as much as possible, that is keep the count of times a line is executed as low as possible, but above 0 (ideally 1). In this case, the answers to your questions are:
true
or false
.BAR
case, for one of the cases, but TEST IT (you want to cover the case BAR
line.true
and false
cases, yes.return false
line.Upvotes: 1