Python基本和子类的unit testing

我目前有几个unit testing共享一组通用testing。 这是一个例子:

import unittest class BaseTest(unittest.TestCase): def testCommon(self): print 'Calling BaseTest:testCommon' value = 5 self.assertEquals(value, 5) class SubTest1(BaseTest): def testSub1(self): print 'Calling SubTest1:testSub1' sub = 3 self.assertEquals(sub, 3) class SubTest2(BaseTest): def testSub2(self): print 'Calling SubTest2:testSub2' sub = 4 self.assertEquals(sub, 4) if __name__ == '__main__': unittest.main() 

以上的输出是:

 Calling BaseTest:testCommon .Calling BaseTest:testCommon .Calling SubTest1:testSub1 .Calling BaseTest:testCommon .Calling SubTest2:testSub2 . ---------------------------------------------------------------------- Ran 5 tests in 0.000s OK 

有没有一种方法来重写上面,以便第一个testCommon不被调用?

编辑:而不是运行5以上的testing,我希望它只能运行4testing,2从SubTest1和另一个2从SubTest2。 Pythonunit testing似乎正在运行原来的BaseTest,我需要一个机制来防止这种情况的发生。

使用多重inheritance,所以你有普通testing的类本身不会从TestCaseinheritance。

 import unittest class CommonTests(object): def testCommon(self): print 'Calling BaseTest:testCommon' value = 5 self.assertEquals(value, 5) class SubTest1(unittest.TestCase, CommonTests): def testSub1(self): print 'Calling SubTest1:testSub1' sub = 3 self.assertEquals(sub, 3) class SubTest2(unittest.TestCase, CommonTests): def testSub2(self): print 'Calling SubTest2:testSub2' sub = 4 self.assertEquals(sub, 4) if __name__ == '__main__': unittest.main() 

不要使用多重inheritance,它会稍后咬你。

相反,你可以将你的基类移动到单独的模块中,或者用空白类来包装它:

 import unittest class BaseTestCases: class BaseTest(unittest.TestCase): def testCommon(self): print 'Calling BaseTest:testCommon' value = 5 self.assertEquals(value, 5) class SubTest1(BaseTestCases.BaseTest): def testSub1(self): print 'Calling SubTest1:testSub1' sub = 3 self.assertEquals(sub, 3) class SubTest2(BaseTestCases.BaseTest): def testSub2(self): print 'Calling SubTest2:testSub2' sub = 4 self.assertEquals(sub, 4) if __name__ == '__main__': unittest.main() 

输出:

 Calling BaseTest:testCommon .Calling SubTest1:testSub1 .Calling BaseTest:testCommon .Calling SubTest2:testSub2 . ---------------------------------------------------------------------- Ran 4 tests in 0.001s OK 

你可以用一个命令来解决这个问题:

 del(BaseTest) 

所以代码看起来像这样:

 import unittest class BaseTest(unittest.TestCase): def testCommon(self): print 'Calling BaseTest:testCommon' value = 5 self.assertEquals(value, 5) class SubTest1(BaseTest): def testSub1(self): print 'Calling SubTest1:testSub1' sub = 3 self.assertEquals(sub, 3) class SubTest2(BaseTest): def testSub2(self): print 'Calling SubTest2:testSub2' sub = 4 self.assertEquals(sub, 4) del(BaseTest) if __name__ == '__main__': unittest.main() 

马修·马歇尔的答案很好,但是它要求你在每个testing用例中inheritance两个类,这是很容易出错的。 相反,我使用这个(python> = 2.7):

 class BaseTest(unittest.TestCase): @classmethod def setUpClass(cls): if cls is BaseTest: raise unittest.SkipTest("Skip BaseTest tests, it's a base class") super(BaseTest, cls).setUpClass() 

你想达到什么目的? 如果你有共同的testing代码(断言,模板testing等),然后把它们放在没有用test前缀的方法中,所以unittest不会加载它们。

 import unittest class CommonTests(unittest.TestCase): def common_assertion(self, foo, bar, baz): # whatever common code self.assertEqual(foo(bar), baz) class BaseTest(CommonTests): def testCommon(self): print 'Calling BaseTest:testCommon' value = 5 self.assertEquals(value, 5) class SubTest1(CommonTests): def testSub1(self): print 'Calling SubTest1:testSub1' sub = 3 self.assertEquals(sub, 3) class SubTest2(CommonTests): def testSub2(self): print 'Calling SubTest2:testSub2' sub = 4 self.assertEquals(sub, 4) if __name__ == '__main__': unittest.main() 

马修的答案是我仍然使用2.5以来需要使用的答案。 但是从2.7开始,你可以在你想要跳过的任何testing方法上使用@ unittest.skip()装饰器。

http://docs.python.org/library/unittest.html#skipping-tests-and-expected-failures

你需要实现你自己的跳过装饰器来检查基types。 之前没有使用过这个function,但是我可以使用BaseTest作为标记types来调整跳转:

 def skipBaseTest(obj): if type(obj) is BaseTest: return unittest.skip("BaseTest tests skipped") return lambda func: func 

另一种select是不执行

 unittest.main() 

而不是你可以使用的

 suite = unittest.TestLoader().loadTestsFromTestCase(TestClass) unittest.TextTestRunner(verbosity=2).run(suite) 

所以你只能在类TestClass执行testing

我想过解决这个问题的方法是隐藏testing方法,如果使用基类。 这样,testing不会被跳过,所以在许多testing报告工具中,testing结果可以是绿色而不是黄色。

与mixin方法相比,IDE的PyCharm不会抱怨unit testing方法从基类中丢失。

如果一个基类从这个类inheritance,它将需要重写setUpClasstearDownClass方法。

 class BaseTest(unittest.TestCase): @classmethod def setUpClass(cls): cls._test_methods = [] if cls is BaseTest: for name in dir(cls): if name.startswith('test') and callable(getattr(cls, name)): cls._test_methods.append((name, getattr(cls, name))) setattr(cls, name, lambda self: None) @classmethod def tearDownClass(cls): if cls is BaseTest: for name, method in cls._test_methods: setattr(cls, name, method) cls._test_methods = [] 

只需将testCommon方法重命名为其他内容即可。 unit testing(通常)会跳过任何没有“testing”的东西。

快速简单

  import unittest class BaseTest(unittest.TestCase): def methodCommon(self): print 'Calling BaseTest:testCommon' value = 5 self.assertEquals(value, 5) class SubTest1(BaseTest): def testSub1(self): print 'Calling SubTest1:testSub1' sub = 3 self.assertEquals(sub, 3) class SubTest2(BaseTest): def testSub2(self): print 'Calling SubTest2:testSub2' sub = 4 self.assertEquals(sub, 4) if __name__ == '__main__': unittest.main()` 

我做了大约相同的@Vladim体育( https://stackoverflow.com/a/25695512/2451329 ),但略有修改:

 import unittest2 from some_module import func1, func2 def make_base_class(func): class Base(unittest2.TestCase): def test_common1(self): print("in test_common1") self.assertTrue(func()) def test_common2(self): print("in test_common1") self.assertFalse(func(42)) return Base class A(make_base_class(func1)): pass class B(make_base_class(func2)): def test_func2_with_no_arg_return_bar(self): self.assertEqual("bar", func2()) 

我们去吧

将BaseTest方法名称更改为setUp:

 class BaseTest(unittest.TestCase): def setUp(self): print 'Calling BaseTest:testCommon' value = 5 self.assertEquals(value, 5) class SubTest1(BaseTest): def testSub1(self): print 'Calling SubTest1:testSub1' sub = 3 self.assertEquals(sub, 3) class SubTest2(BaseTest): def testSub2(self): print 'Calling SubTest2:testSub2' sub = 4 self.assertEquals(sub, 4) 

输出:

冉2testing在0.000s

调用BaseTest:testCommon调用
SubTest1:testSub1调用
BaseTest:testCommon调用
SubTest2:testSub2

从文档 :

TestCase.setUp()
调用方法来准备testing夹具。 这在调用testing方法之前立即调用; 此方法引发的任何exception将被视为错误而不是testing失败。 默认实现什么都不做。