Reputation: 2363
My language is python 3
and I am trying to understand how to use the same set of tests to test different implementations of the same algorithm.
So far I am looking at the built-in unittest
and my impression is that I have to make some sort of a class hierachy: a class that inherits from unittest.TestCase and implements all the actual tests and several descendants from its class that each test particular implementations with the tests from the parent.
However, this is just my idea of how it should look like. Could you please tell me how to actually use the same set of tests to test different functions that implement the same algorithm?
Upvotes: 6
Views: 2712
Reputation: 953
Use parameterized tests with your tested functions as a parameter.
For example, using ddt
module for parameterized testing:
def sum1(list1):
return sum(list1)
def sum2(list1):
res = 0
for x in list1:
res += x
return res
import unittest
from ddt import ddt, data
@ddt
class SumTest(unittest.TestCase):
@data(sum1, sum2)
def test_sum(self, param):
self.assertEqual(param([1, 2, 3]), 6)
if __name__ == '__main__':
unittest.main()
In this example, you have two functions "sum1" and "sum2" implementing the same algorithm: summing of list elements. In your test class, you have only one testing method "test_sum" that takes the concrete summing function as a parameter. The two summing functions are specified as a list of values for a parameterized test.
You can install "ddt" with pip:
pip install ddt
Upvotes: 1
Reputation: 39354
I've done this by writing tests in a class that does not inherit from TestCase
and then writing multiple test classes that do inherit from TestCase
and the tests, but either have a factory method or a class attribute of the class to instantiate:
class TestAnyImplementation:
def testThis(self):
obj = getImpl() # call to factory method
self.assertTrue(obj.isEmpty())
class TestFooImplementation(TestAnyImplementation,TestCase):
def getImpl(self):
return Foo()
class TestBarImplementation(TestAnyImplementation,TestCase):
def getImpl(self):
return Bar()
Upvotes: 5
Reputation:
You can leave your tests unchaged if you import
the different implementations with the same name. To test impl1
, do
import impl1 as impl
in your test code. To test impl2
, do
import impl2 as impl
Everything else can be left unchanged, if both impl1
and impl2
have the same interface.
Edit: You can wrap these import in an if
clause and use a commandline parameter to select one.
chooseImpl = ... # get commandline parameter
if chooseImp == "impl1":
import impl1 as impl
elif chooseImp == "impl2":
import impl2 as impl
Using this approach you can don't have to change the test.
Upvotes: 1