Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I duplicate tests for convenience overloads?

It's really common for me to make convenience overloads for methods. Here's an example of something I might do:

public void Encode(string value) {
    Encode(value, DefaultEncoding);
}

public void Encode(string value, Encoding encoding) { 
    // ... 
}

I'm starting to pay more attention to unit testing, and testing methods like this introduces some obstacles I'm not sure I trust myself to approach alone. The first and most important problem is whether I should duplicate tests for both overloads. For example, both methods should throw ArgumentNullException if value is null; is it more correct to recognize there could be different logic and write two tests or is it better to assume that the convenience overloads have no logic of their own?

I've also got a secondary problem. My naming scheme is the same as Roy Osherove's: "MemberName_State_ExpectedResult". If I duplicate tests, then I have clashing names without introducing some oddball naming convention. How do you handle this if you duplicate tests?

like image 769
OwenP Avatar asked Oct 12 '09 21:10

OwenP


4 Answers

" write two tests or is it better to assume that the convenience overloads have no logic of their own?"

Umm.... Your tests aren't defined by "assumptions". They're defined by the design of the class you're testing.

You don't do anything based on "assumptions".

If the convenience function is actually a convenience function, it must do the same thing and you must write a test that demonstrates that both variant methods actually do the same thing.

If "there could be different logic" (1) it isn't really a convenience function and (2) you must write a test that demonstrates that both variant methods actually do the correct thing (which may be the same with different logic, or may be different, I can't tell from the question.)

"MemberName_State_ExpectedResult. If I duplicate tests, then I have clashing names "

Avoid foolish consistency questions. If you have the same method with different signatures, then this naming convention isn't very good, is it? Sticking to it faithfully, in spite of it's problems, is a foolish consistency.

You can't trivially use this when you have methods that are distinguished only by argument signatures. So just make something up that works for all your convenience functions.

like image 160
S.Lott Avatar answered Nov 17 '22 01:11

S.Lott


What I usually do is to make the 'real' method virtual. This means that I can test the convenience method using a test-specific derived class (usually created by a dynamic mock) to verify that it correctly calls the 'real' method.

If the only difference between the 'real' method and the convenience method is the use of a default value for a particular parameter, you can cover this with a single unit test and move on.

I second S.Lott's answer regarding the naming convention.

like image 28
Mark Seemann Avatar answered Nov 17 '22 01:11

Mark Seemann


I frequently don't test the convenience methods to the same level of detail as the core method they call. For example your ArgumentNullException case. I wouldn't test it twice. My feeling is that unit testing is white box testing. I'm allowed to know the implementation.

Of course this could mean that I'm going to get burned when I go and refactor later and add functionality to the convenience method. But I'm pretty decent at doing TDD (not a full zealot as you can tell from the first paragraph). So I think I would most likely write a test for that new functionality and cover it then.

I'm not claiming it's more or less correct. It's just what I do.

like image 40
Mike Two Avatar answered Nov 17 '22 01:11

Mike Two


I think the answer is simpler then you think: do you care whether the overloaded methods work or not? If you care that they work, how do you know for certain unless you test them?

It should take you about 15 seconds to write a test that compares the output of the overloaded function with the one that it overloads. Do it and move on.

like image 31
Bryan Oakley Avatar answered Nov 16 '22 23:11

Bryan Oakley