how to reuse tests written using unittest.testcase - python

I've written some tests using unittest as below and I want to reuse them in another class where I'm stuck and need help..
Code snippets are as below.
MyTestClass.py
Class MyTestClass(unittest.TestCase):
#classmethod
def test_TC01_set(self):
self.devAddr = "127.0.0.0"
self.teststoSkip = 'TC02'
def skip(type):
if type in self.teststoSkip:
self.skipTest('skipped!!') #unittest.Testcase method
def test_TC02(self):
self.skip('TC02')
print 'test_TC02 will do other tasks'
def test_TC03(self):
self.skip('TC03')
print 'test_TC03 will do other tasks'
This will work fine. Now I want to reuse the same testcases in another class. say,
RegressionMyTest.py
from MyTestClass import MyTestClass
Class RegressionMyTest(MyTestClass):
#classmethod
def setupmytest(self):
self.test_TC01_set(self)#this will work fine since it is accessing classmethod
self.tes_TC02(self)#cant access like this since it is not a class method
self.tes_TC03(self)#cant access like this since it is not a class method
How can I reuse the tests in MyTestClass in RegressionMyTest so that both MyTestClass and RegressionMyTest should work if they are run individually using nosetests/unittest.

Usually tests are supposed to assert code is functioning in a certain way, so I'm not sure if it would make sense to actually share tests between testsuites, (I don't think it would be very explicit)
Python tests cases are just python classes, that are introspected by the test runner for methods beginning in test_. Because of this you can you use inheritance in the same way you would with normal classes.
If you need shared functionality, you could create a base class with shared initialization methods/ helper methods. Or create testing mixins with utility functions that are needed across tests.
class BaseTestCase(unittest.TestCase):
def setUp(self):
# ran by all subclasses
def helper(self):
# help
class TestCaseOne(BaseTestCase):
def setUp(self):
# additional setup
super(TestCaseOne, self).setUp()
def test_something(self):
self.helper() # <- from base
Perhaps you don't want to define a setup method on the base class and just define on child classes using some helper methods defined in the base class? Lots of options!

I don't think your title describe your question correctly. Your code mistake is:
Calling a parent class "object method" in the child "class method"(#classmethod), because an "object method" must have one class instance(object), so in the child "class method", the system could find any object instance for its parent class.
You just need review the concepts of "class methods" and "object methods"(or instance methods) in programming language.

Related

How to create a mock that behaves like sub-classes from abstract class

I'm trying to create mocks from scratch that can pass the test issubclass(class_mock, base_class) where the base class is an abstract class derived from abc.ABC. Before you ask the question, I will answer why I'm trying to do it.
I have an internal package containing a base class and a collection of sub-classes that properly implement the abstract interface. Besides, I have a factory class that can instantiate the sub-classes. The factory is built is such a way that it can inspect its own package and have access to the existing sub-classes. The factory is meant to be always in the same package as the derived and base class (constraint). I think you guessed that I'm actually testing the factory... However, since the sub-classes can change in number, their name or their package name, etc., I cannot implement a correct unit test that directly refers to the actual cub-classes (because it introduces a coupling) and I need mocks.
The problem is that I didn't succeed to create a mock that satisfies the above conditions for a class derived from an abstract class. What I was able to achieve is for a class derived from another non-abstract class.
Here is the code that illustrates the problem more concretely.
import unittest.mock
import inspect
import abc
class A:
pass
class B(A):
pass
class TestSubClass(unittest.TestCase):
def test_sub_class(self):
b_class_mock = self._create_class_mock("B", A)
print(isinstance(b_class_mock, type))
print(inspect.isclass(b_class_mock))
print(issubclass(b_class_mock, A))
#staticmethod
def _create_class_mock(mock_name, base_class):
class_mock = unittest.mock.MagicMock(spec=type(base_class), name=mock_name)
class_mock.__bases__ = (base_class,)
return class_mock
So, for this code, everything is ok. It prints 3 True as wanted.
But as long as the class A is defined as abstract (class A(abc.ABC)), the last test is failing with an error saying that the mock is not a class even if the 2 previous tests are saying the opposite.
I dived a bit into the implementation of abc.ABCMeta and found out that __subclasscheck__ is overridden. I tried to know the process behind it but when I reached the C code and everything became a way more complicated, I tried to rather track when the error message is generated. Unfortunately, I didn't succeed to understand why it is actually not working.

Why a subclass would override a base class method but make it identical (and not use it)?

Studying inheritance in Python, and my understanding so far is that a subclass only overwrites a method of the base class if it is intends for the method to do something different that of the base class.
So using HowDoI as an example, we see that in test_howdoi.py the HowdoiTestCase class, which inherits from unittest.TestCase, overwrites TestCase's setUp() function (which just passes):
def setUp(self):
self.queries = ['format date bash',
'print stack trace python',
'convert mp4 to animated gif',
'create tar archive']
self.pt_queries = ['abrir arquivo em python',
'enviar email em django',
'hello world em c']
self.bad_queries = ['moe',
'mel']
OK so far.
test_howdoi.py then goes on though to overwrite tearDown(), yet it is written to just pass (as per the base class's definition). And tearDown() does not get used anywhere.
Why would a base class function be overwritten with the same behaviour as its behavior in the base class?
Why would it be overwritten at all if there is no intention to use it?
Structure you're describing may be reduced to following code:
class A(object):
def f(self):
pass
class B(A):
# this declaration is redundant since exact same behaviour is already inherited.
def f(self):
pass
And trying to answer your question:
Why would it be overwritten at all if there is no intention to use it?
setUp and tearDown methods ARE used in unittest runners (as name suggests - before and after test).
Why would a base class function be overwritten with the same behaviour
as its behavior in the base class?
Some of reasons may be:
IDEs generated TestCase class stub, developer just kept it
Developer didn't read docs, which states that setUp and tearDown are optional and have empty implementations by default
Some developers like to explicitly write that setUp / tearDown is empty for current test suite
TLDR: By accident or due to personal preference.

Testing several implementation of one interface

Suppose that I have an interface defined like this:
class MyInterface(abc.ABCMeta):
#abstractmethod
def my_method(self, *params):
pass
And several implementations of it.
class Implentation1(MyInterface):
pass
class Implentation2(MyInterface):
pass
All of these classes must be tested under the same class. I was wondering it there is any way to specify that you want a test case to be run with different classes. I am using nosetests and unittest.

Call all subclass methods from super?

I'm currently implementing some unit tests for my company's build scripts. To eliminate bloat and make it a little easier to implement new tests, I'm making all my test classes inherit from a custom subclass called BasicTest that inherits from PyUnit's TestCase.
There are currently two functions that all tests utilize from BasicTest: The constructor (Although it could obviously be overwritten in the future) and the runTest() method that is the default method name that the super's constructor uses if no value is passed in (e.g. BasicTest() would create a test that will execute the runTest() method when called upon, whereas BasicTest('Foo') would use the Foo() method).
I would like to make runTest() simply run all possible tests from the inheriting object it is called on. However, as runTest() is defined only in BasicTest and inherited by the subclasses, I'm looking for a way to dynamically call all of the subclass' methods from the super. I know this violates the rules of OO programming, but from what I can see, Python was never one to follow rules in the first place :)
For clarity, the following illustrates my intentions:
I want runTest() to be called from a subclass object and only handle that object's methods. Let's say SubclassTest() that has methods TestParse() and TestExec(). I want it so that:
sub = SubClassTest()
sub.runTest()
runs TestParse() and TestExec(), but I want the runTest() method to be defined in and inherited from BasicTest without being overriden.
one can create metaclass which will collect all interesting methods of subclasses into class property
class TestMetaclass(type):
def __new__(cls, name, bases, attrs):
own_tests = [v for k,v in attrs.iteritems() if k.startswith('test')]
attrs['test_method_list'] = own_tests
return super(TestMetaclass, cls).__new__(cls, name, bases, attrs)
set this metaclass to base class as __metaclass__
and implement runTests method
class BaseTest():
test_method_list = []
__metaclass__ = TestMetaclass
def runTests(self):
for method in self.test_method_list:
method(self)
And after this all subclasses will be constructed using this metaclass
class TestOne(BaseTest):
def test_foo(self):
pass
In the end one can use collected methods running runTests() method
TestOne().runTests()
Sample code:
load base class .py file as module
and inspect
import inspect
import imp
imp.load_source((name of class by which to want that module), (path base class name of file).py)
module = __import__((name of class by which to want that module))
inspect.getmembers(module) will give you dict of name, cls
Hope this helps

How to run the same test-case for different classes?

I have several classes that share some invariants and have a common interface, and I would like to run automatically the same test for each of them.
As an example, suppose I have several classes that implement different approaches for partitioning a data-set. The common invariant here would be, that for all of these classes the union over all partitions should equal the original data-set.
What I currently have looks something like this:
class PartitionerInvariantsTests(unittest.TestCase):
def setUp(self):
self.testDataSet = range(100) # create test-data-set
def impl(self, partitioner):
self.assertEqual(self.testDataSet,
chain.from_iterable(partitioner(self.testDataSet))
Then I add a different function that calls impl for each of the classes I want to test with an instance of that class. The problem with this becomes apparent when doing this for more than one test-function. Suppose I have 5 test-functions and 5 classes I want to test. This would make 25 functions that look almost identical for invoking all the tests.
Another approach I was thinking about was to implement the template as a super-class, and then create a sub-class for each of the classes I want to test. The sub-classes could provide a function for instantiating the class. The problem with that is that the default test-loader would consider the (unusable) base-class a valid test-case and try to run it, which would fail.
So, what are your suggestions?
P.S.: I am using Python 2.6
You could use multiple inheritance.
class PartitionerInvariantsFixture(object):
def setUp(self):
self.testDataSet = range(100) # create test-data-set
super(PartitionInvariantsFixture, self).setUp()
def test_partitioner(self):
TestCase.assertEqual(self.testDataSet,
chain.from_iterable(self.partitioner(self.testDataSet))
class MyClassTests(TestCase, PartitionerInvariantsFixture):
partitioner = Partitioner
Subclass PartitionerInvariantsTests:
class PartitionerInvariantsTests(unittest.TestCase):
def test_impl(self):
self.assertEqual(self.testDataSet,
chain.from_iterable(self.partitioner(self.testDataSet))
class PartitionerATests(PartitionerInvariantsTests):
for each Partitioner class you wish to test. Then test_impl would be run for each Partitioner class, by virtue of inheritance.
Following up on Nathon's comment, you can prevent the base class from being tested by having it inherit only from object:
import unittest
class Test(object):
def test_impl(self):
print('Hi')
class TestA(Test,unittest.TestCase):
pass
class TestB(Test,unittest.TestCase):
pass
if __name__ == '__main__':
unittest.sys.argv.insert(1,'--verbose')
unittest.main(argv = unittest.sys.argv)
Running test.py yields
test_impl (__main__.TestA) ... Hi
ok
test_impl (__main__.TestB) ... Hi
ok
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK

Categories