Let's say I have a function that is documented to take a collections.Sequence
ABC. How do I test the code within this function against the ABC interface? Can I write a unit test (or tests) confirming that my code only calls methods defined by this ABC and not, say, a method defined by list
or some other concrete implementation of collections.Sequence
? Or is there some other tool or method to verify this?
Asked
Active
Viewed 165 times
2

detly
- 29,332
- 18
- 93
- 152
2 Answers
1
Simply test the function by passing an instance of a class that only implements those methods. If you need to, you can subclass a built-in type such as list
and override its __getattribute__ method, like this:
class TestSequence(list):
def __getattribute__(self, name):
if name not in collections.Sequence.__abstractmethods__:
assert(False) # or however you'd like the test to fail
return object.__getattribute__(self, name)

jangler
- 949
- 6
- 7
-
"an instance of a class that only implements those methods" — this is the core of what I'm asking, I think: is there an easier way to obtain such a thing? Your method works, but duplicates information that is already in the ABC. Thus, there's a risk of getting out of sync, making another mistake, etc. (Also, if someone were to do this, they might be better off using a mock object or similar... depending on the test.) – detly May 29 '15 at 03:13
-
Would using `if name not in Sequence.__abstractmethods__` solve your problem? – jangler May 29 '15 at 03:25
0
Implement the ABC directly yourself, with methods as trivial or complex as needed by the code:
import collections
class TestSequence(collections.Sequence):
def __init__(self):
pass
def __len__(self):
return 3
def __getitem__(self, index):
return index
If you make a mistake and omit abstract method implementations, your code will produce an error:
TypeError: Can't instantiate abstract class TestSequence with abstract methods __getitem__
If your code under test calls a method not defined by the ABC, you will see the usual no attribute error:
AttributeError: 'TestSequence' object has no attribute 'pop'

detly
- 29,332
- 18
- 93
- 152