【问题标题】:How to parameterize python unittest setUp method?如何参数化 python unittest setUp 方法?
【发布时间】:2015-02-24 12:00:45
【问题描述】:

我正在尝试使用不同的 setUp 方法运行相同的测试用例。我试过使用鼻子测试和参数化,但它似乎不支持参数化 setUp 方法。这是我正在尝试做的一个示例:

...
from nose_parameterized import parameterized

class Example(unittest.TestCase):

    @parameterized.expand(['device1', 'device2'])
    def setUp(self, device):
        desired_caps = {}
        desired_caps['key1'] = device
        desired_caps['key2'] = 'constant value'

    self.driver = webdriver.Remote(url, desired_caps)

    def tearDown(self):
        self.driver.quit()

    def test_app_launch(self):
        # assert something

错误是:TypeError: setUp() takes exactly 2 arguments (1 given)

还有其他方法可以参数化 setUp 方法吗?我还研究了鼻子测试生成器,但它似乎也不是要走的路。

【问题讨论】:

    标签: python nosetests unit-testing


    【解决方案1】:

    所以我的方法是设置一个基础测试,其中包含设备必须通过的所有测试。然后,您必须使用从该 baseTest 继承的 deviceTests 以及它们自己的附加设置,这些设置将是特定于设备的。

    # this is the base test. Everything that is not specific to the device is set up here. It also contains all the testCases.
    import unittest
    class deviceTest( unittest.TestCase ):
    
      def setUp( self ):
        '''
        General setUp here
        '''
        self.desired_caps = {}
        self.desired_caps['key2'] = 'constant value'
    
      def testWorkflow( self ):
        '''
        Here come the tests that the devices have to pass
        '''
    
    class device1Test( deviceTest ):
    
      def setUp( self ):
        '''
        device1 specific setup
        '''
        #also run general setUp    
        deviceTest.setUp( self )
        self.desired_caps['key1'] = device
        self.driver = webdriver.Remote(url, desired_caps)
    
    
    class device2Test( deviceTest ):
    
      def setUp( self ):
        '''
        device2 specific setup
        '''
        #also run general setUp
        deviceTest.setUp( self )
        self.desired_caps['key1'] = device
        self.driver = webdriver.Remote(url, desired_caps)
    
    
    if __name__ == '__main__':
      suite = unittest.defaultTestLoader.loadTestsFromTestCase( device1Test )
      suite.addTest( unittest.defaultTestLoader.loadTestsFromTestCase(device2Test ) )
      unittest.TextTestRunner( verbosity = 2 ).run( suite )
    

    【讨论】:

    • 这可能适用于一小部分设备,但我可能有数百个设备。设备列表也是动态的(即,它是在每次测试运行之前通过 API 获取的,并且每次都可能包含不同的设备集)
    • 它对我有用,但我通过将设备名称传递给方法来减少了更多的特定设置。在 deviceXTest: deviceTest.setup(self, device_name) 中,然后从父 deviceTest 中,您可以使用此参数创建适当的上限并调用驱动程序。
    【解决方案2】:

    使用类属性:

    class Example(unittest.TestCase):
    
        # change before running tests
        device = None
    
        # make sure device is initialized
        def setUpClass(cls):
            if not cls.device:
                raise Exception("Please initialize device before running tests")
    
        def setUp(self):
            # consider moving to 'setUpClass'
            desired_caps = {}
            desired_caps['key1'] = Example.device
            desired_caps['key2'] = 'constant value'
    
        self.driver = webdriver.Remote(url, desired_caps)
    
        def tearDown(self):
            self.driver.quit()
    
        def test_app_launch(self):
            # assert something
    

    并分别为每个设备运行测试。您的代码建议可以将更多内容移至 setUpClass 方法。

    【讨论】:

    • 你的意思是我应该通过命令行参数将设备传递给测试?
    • 你可以,我不确定你是如何设置测试的。我的观点是设备在整个测试过程中永远不会改变,所以一次又一次地分配它没有意义。在课程设置中进行一次就可以了,课程应该使用不同的运行测试不同的设备(假设所有设备都必须通过所有测试)。
    • 由于报告的目的,我试图避免多次调用测试文件,总是使用不同的参数值。我只需要一份包含所有设备的报告,以便我可以将其包含在持续集成工作流程中。只有在参数化 setUp 方法能很好地发挥作用时,使用鼻子测试和参数化运行这些测试才会产生这样的结果。
    【解决方案3】:

    我会在测试中使用参数化插件,并调用自定义设置和拆卸方法,将设备参数作为测试的一部分传递给它们。使用 unittest 的 setUp() 几乎没有什么魔力,而且看起来你无论如何都在滥用它。

    【讨论】:

      猜你喜欢
      • 2017-09-30
      • 1970-01-01
      • 2013-03-27
      • 2012-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多