Python unit test with base and sub class

前端 未结 15 2163
独厮守ぢ
独厮守ぢ 2020-11-28 18:44

I currently have a few unit tests which share a common set of tests. Here\'s an example:

import unittest

class BaseTest(unittest.TestCase):

    def testCo         


        
相关标签:
15条回答
  • 2020-11-28 18:50

    You can solve this problem with a single command:

    del(BaseTest)
    

    So the code would look like this:

    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()
    
    0 讨论(0)
  • 2020-11-28 18:51

    I made about the same than @Vladim P. (https://stackoverflow.com/a/25695512/2451329) but slightly modified:

    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())
    

    and there we go.

    0 讨论(0)
  • 2020-11-28 18:53

    Change the BaseTest method name to 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)
    

    Output:

    Ran 2 tests in 0.000s

    Calling BaseTest:testCommon Calling
    SubTest1:testSub1 Calling
    BaseTest:testCommon Calling
    SubTest2:testSub2

    From the documentation:

    TestCase.setUp()
    Method called to prepare the test fixture. This is called immediately before calling the test method; any exception raised by this method will be considered an error rather than a test failure. The default implementation does nothing.

    0 讨论(0)
  • 2020-11-28 18:55

    Here is a solution that uses only documented unittest features an that avoids having a "skip" status in your test results:

    class BaseTest(unittest.TestCase):
    
        def __init__(self, methodName='runTest'):
            if self.__class__ is BaseTest:
                # don't run these tests in the abstract base implementation
                methodName = 'runNoTestsInBaseClass'
            super().__init__(methodName)
    
        def runNoTestsInBaseClass(self):
            pass
    
        def testCommon(self):
            # everything else as in the original question
    
    

    How it works: per the unittest.TestCase documentation, "Each instance of TestCase will run a single base method: the method named methodName." The default "runTests" runs all the test* methods on the class—that's how TestCase instances normally work. But when running in the abstract base class itself, you can simply override that behavior with a method that does nothing.

    A side effect is your test count will increase by one: the runNoTestsInBaseClass "test" gets counted as a successful test when it's run on BaseClass.

    (This also works in Python 2.7, if you're still on that. Just change super() to super(BaseTest, self).)

    0 讨论(0)
  • 2020-11-28 18:58

    Use multiple inheritance, so your class with common tests doesn't itself inherit from TestCase.

    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()
    
    0 讨论(0)
  • 2020-11-28 18:59

    Just rename the testCommon method to something else. Unittest (usually) skips anything that doesn't have 'test' in it.

    Quick and simple

      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()`
    
    0 讨论(0)
提交回复
热议问题