I have an abstract class:
import abc
class Hello(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def add(self, foo):
pass
@abc.abstractmethod
def remove(self, foo):
pass
I'm using abc for do abstract methods, so, when i do:
hello = Hello()
and this error is raised: TypeError: Can't instantiate abstract class Hello with abstract methods add, remove
So I can test this type error with:
self.assertRaises(Exception, Hello) # but this only test the constructor and i can't get the 100% of code coverage. I need call the add method and the remove method
Extra question: anybody knows how can i assert the message exception in python 2.6? (you can't use the with:
for raise assertions.)
How can i test this abstract methods for get the 100% of code coverage?
There are two ways to unit test a class hierarchy and an abstract class: Using a test class per each production class. Using a test class per concrete production class.
To define an abstract method we use the @abstractmethod decorator of the abc module. It tells Python that the declared method is abstract and should be overridden in the child classes. We just need to put this decorator over any function we want to make abstract and the abc module takes care of the rest.
There are two options to test an abstract base class (ABC) in Python: you can either override or patch the __abstractmethods__ property to be able to instantiate the abstract class and test it directly or you can create a child class that implements all the abstract methods of the base class.
Note the abstract base class may have more than one abstract methods. The child class must implement all of them failing which TypeError will be raised.
What about creating a doc string of the abstract method instead of using pass
as mentioned here, https://stackoverflow.com/a/19275908/469992 ? It can also be used to give some information about what the method is supposed to do in the sub classes.
abstract.py,
from abc import ABCMeta, abstractmethod
class A(object):
__metaclass__ = ABCMeta
@abstractmethod
def some_method(self):
"This method should ..."
class B(A):
def some_method(self):
return 1
test_abstract.py,
import unittest
import abstract
class TestB(unittest.TestCase):
def test(self):
self.assertEqual(abstract.B().some_method(), 1)
Then, using python 2.6.8, nosetests --with-xcoverage
outputs,
.
Name Stmts Miss Cover Missing
----------------------------------------
abstract 7 0 100%
----------------------------------------------------------------------
Ran 1 test in 0.004s
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With