How to check if a method exists in TDD?
在严格的测试驱动开发方法中,每一个步骤都需要在动手之前进行测试。甚至一个类或它的方法的存在——严格来说——都要在它们真正被创建之前进行测试。
我有一个问题要做写测试来看看方法是否存在。
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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) |
在这两种情况下,如果类不存在,python就已经失败了。测试永远无法断言。有没有更好的方法来实现这一点?
类型的存在
例外情况
如果一个类没有被定义,那么试图使用它会抛出一个非常具体的错误,因此实现这一点的一种方法是捕获该错误(在
1 2 3 4 5 | def setUp(self): try: self.test = RandomGenClass() except NameError as e: pass # fail appropriately here. |
记住,这可能掩盖一些错误的原因:例如,如果
与
因此,也许实现这一点的更好方法(无论如何,对于您的用例来说)是在
1 2 | if not 'RandomGenClass' in globals(): pass # fail appropriately |
与
如果类存在于其他模块中(很可能,但不一定是这样),我们可以在模块对象上使用
1 2 3 | import some_module if not hasattr(some_module, 'ClassName'): pass # fail appropriately |
根据类的来源,您可能实际上能够更早地捕获它。如果要从定义类的任何地方导入类,那么只需显式导入所有类,如果类未定义,则查找
至于方法测试,那部分很容易。一旦您知道类存在并且有了它的实例,就可以使用
1 2 | if hasattr(self.test, 'method_name'): result = self.test.method_name() |
当然,您也可以用与测试类存在性几乎完全相同的方法来完成这项工作:继续进行并执行,如果错误发生,则捕获错误。同样,这一个需要某种验证,您捕获的属性错误实际上就是您要查找的错误。
1 2 3 4 | try: result = self.test.myMethod() except AttributeError as e: pass # fail appropriately |
检查方法是否存在可以使用
1 2 3 4 5 6 | class A(object): def MethodInA(self): pass print hasattr(A, 'MethodInA') print hasattr(A, 'RandomMethodNameNotInA') |
输出将是
1 2 | True False |
这也适用于在模块中定义的类或方法,因此,如果要检查是否存在的类是在模块中编写的,则可以使用相同的方法,例如:
1 2 3 4 | import logging print hasattr(logging,"LogRecord") print hasattr(logging,"LogRecords") |
UnitTest的文档包含一个调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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() |
一个未知的方法引发一个attributeError,也许捕捉到作为assertraises子句一部分的attributeError是一种方法?
How to check if a method exists in TDD?
这个问题被标记为python,但tdd无处不在。下面是一个基本的PHP示例…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | class DatabaseTest extends PHPUnit_Framework_TestCase { protected function setUp() { // if the class is not existing, one would skip the method tests if (!class_exists('DatabaseHelper', false)) { $this->markTestSkipped( 'DatabaseHelper class not available. Skipping all method tests.' ); } // subject under test $database = new Database; // i wouldn't go so far, as to test the methods of the class, anyway.. if(!is_callable(array($database, 'myMethod'))) { $this->markTestSkipped( 'DatabaseHelper class does not contain method myMethod. '. 'Skipping all method tests.' ); } // this is very often used: if an PHP extension is not available if (!extension_loaded('mysqli')) { $this->markTestSkipped( 'The MySQLi extension is not available.' ); } } public function testConnection() { // do Db thing ... // assert method of a class $this->assertTrue( method_exists('DatabaseHelper', 'myHelperFunction'), 'Class DatabaseHelper does not have method myHelperFunction' ); } } |
使用的PHP函数
- 类别:
class_exists() 。 - 方法:
method_exists() —或更好的is_callable() 。 - 分机:
extension_loaded() 。
也可以使用
1 2 3 4 5 6 7 8 9 10 11 12 | /** * Assert that a class has a method * * @param string $class name of the class * @param string $method name of the searched method * @throws ReflectionException if $class don't exist * @throws PHPUnit_Framework_ExpectationFailedException if a method isn't found */ function assertMethodExist($class, $method) { $oReflectionClass = new ReflectionClass($class); assertThat("method exist", true, $oReflectionClass->hasMethod($method)); } |