In a strict Test Driven development methodology every step is required to be tested before hand. Even the existence of a class or of its methods have - strictly speaking - to be tested before they are actually even created.
I have a problem to make write tests to see if a method exists.
class BasicTests(unittest.TestCase):
def setUp(self):
self.test = RandomGenClass()
def testRandomGenClassExists(self):
""" Does the class exist? """
self.assert_(self.test is not None)
def testMyMethodExists(self):
""" Does MyMethod() exist?"""
result = self.test.myMethod()
self.assert_(result is not None)
In both cases Python would already fail if the class didn't exist. The test never gets to assert. Is there a better way to achieve this?
With Exceptions
If a class isn't defined, trying to use it will throw a very specific error, so one way to go about this is to catch that error (in setUp, presumably, or wherever it's first used), and fail right then and there.
def setUp(self):
try:
self.test = RandomGenClass()
except NameError as e:
pass # fail appropriately here.
Bear in mind that this could mask the cause of some errors: for instance, if RandomGenClass.__init__ raises a NameError. So for your case, you'd probably have to look a little more closely at the error that's raised, to make sure that it's "RandomGenClass" that's undefined, and not some deeper name.
With globals()
So, perhaps a better way to accomplish this (for your use case, anyway) is by looking in the dictionary returned by globals() for the name of the class you wish to use, but personally I think this is a little uglier and more prone to issues. It doesn't have the problem of masking other errors though.
if not 'RandomGenClass' in globals():
pass # fail appropriately
With hasattr
If the classes exist in other modules (likely, but not necessarily the case), we can use hasattr on the module objects in the same way as we'll test for methods (below). This is probably the cleanest way overall.
import some_module
if not hasattr(some_module, 'ClassName'):
pass # fail appropriately
Depending on where the class originates, you might actually be able to catch it earlier. If you're importing classes from wherever they're defined, you could just import them all explicitly, and look for ImportError if a class is undefined.
As for method testing, that part's easy. Once you know that the class exists and you've got an instance of it, you can use hasattr to determine whether a given name is defined for that object.
if hasattr(self.test, 'method_name'):
result = self.test.method_name()
Of course, you can also do this in almost exactly the same way as you tested for the existence of the class: by going ahead and doing it, and catching the error if it blows up. Again, this one would require some kind of validation that the attribute error you're catching is actually the one you're looking for.
try:
result = self.test.myMethod()
except AttributeError as e:
pass # fail appropriately
The documentation for unittest contains an example where assertRaises is invoked:
import random
import unittest
class TestSequenceFunctions(unittest.TestCase):
def setUp(self):
self.seq = range(10)
def test_shuffle(self):
# make sure the shuffled sequence does not lose any elements
random.shuffle(self.seq)
self.seq.sort()
self.assertEqual(self.seq, range(10))
# should raise an exception for an immutable sequence
self.assertRaises(TypeError, random.shuffle, (1,2,3))
def test_choice(self):
element = random.choice(self.seq)
self.assertTrue(element in self.seq)
def test_sample(self):
with self.assertRaises(ValueError):
random.sample(self.seq, 20)
for element in random.sample(self.seq, 5):
self.assertTrue(element in self.seq)
if __name__ == '__main__':
unittest.main()
An unknown method raises an AttributeError, perhaps catching that as part of an assertRaises clause is an approach?
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