At some point I had to create some class "Class1" and that class needs a method "method". So I have the following:
Class1MethodTest: A total of N tests that check the behavior of Class1.method Class1 method: A full implementation of the method
But a bit later I need a different class "Class2" to have a completely similar method "method". Now I have several approaches:
Class1MethodTest: A total of N tests Class1 method: Full implementation Class2MethodTest: Another set of identical tests Class2 method: Another full implementation
Pros: Stupid simple
Cons: not DRY
At least that's the first attempt and I might even write this before doing any refactoring, right?
_hidden_private_implementation_function: Full implementation of required method Class1MethodTest: A total of N tests Class1 method: Call hidden_private_whatever Class2MethodTest: Another set of identical tests Class2 method: Also call hidden_private_stuff
Pros: DRY code, still stupid simple
Cons: Tests aren't DRY, "Test interface, not implementation"
MethodTest: A total of N tests TotallyPublicCommonMethod: Full implementation of required method Class1MethodTest: Just one test to verify that Class1 method calls the Public one Class1 method: Call public common method Class2MethodTest: One more test Class2 method: Also call common method
Pros: DRY, stupid simple
Cons: .. any other than "You're testing implementation, not interface"?
This is where it gets a bit exotic. Python allows me to DRY the "Approach 3" directly:
_hidden_private_implementation_function: Full implementation of required method makeTestForClass(cls): return a total of N tests for class cls Class1MethodTest = makeTestForClass(Class1) Class1 method: Call hidden_private_whatever Class2MethodTest = makeTestForClass(Class2) Class2 method: Also call hidden_private_stuff
Pros: DRY, "Don't test implementation"
Cons: Not that simple. Too hard to modify if I ever decide to change something in Class1.method, but not Class2.method
I can think of a couple more approaches but those are not very different from these above.
Right now I have some code looking something like "Approach 1" and I am thinking on which way I should go next to make it all cleaner and better.