由其声明确定的Python单元的执行顺序

2022-05-17 00:00:00 python selenium python-unittest

问题描述

我使用的是python单元测试和Selify,在我的代码中,我有一个带有许多测试用例的测试类:

class BasicRegression(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Chrome(executable_path=Data.driver)
        cls.driver.implicitly_wait(1)
        cls.driver.maximize_window()

    def testcase1_some_stuff(self):
        do_something()

    def testcase2_some_stuff(self):
        do_something()

    def testcase3_some_stuff(self):
        do_something()

    ...

    @classmethod
    def tearDownClass(cls):
        cls.driver.close()
        cls.driver.quit()

if __name__ == '__main__':
    unittest.main()

测试按字母顺序执行,即,测试用例1、测试用例2和测试用例3,直到测试用例9。标准。问题出现在测试用例10中,依此类推,它首先被执行。

我的问题是如何设置他们的执行顺序?


解决方案

首先,单元测试应该是独立的。所以一定是python-unittest。通过python-unittest执行的测试应该设计为能够独立运行。纯粹的单元测试提供了一个好处,当它们失败时,它们通常会描述出到底出了什么问题。尽管如此,我们仍然倾向于使用unittest框架编写功能测试、集成测试和系统测试,如果不对它们进行排序,这些测试将无法运行,因为Selenium会自动执行浏览上下文。要实现排序,您至少需要对测试名使用更好的命名约定,例如:test_1test_2test_3等,这是可行的,因为测试是按照字符串的内置排序进行排序的。

但是,根据您的观察,问题出现在test_10等排序顺序似乎被破坏的地方。例如,在名为test_1test_2test_10的3个测试中,unittest似乎在test_2之前执行test_10

  • 编码:

    import unittest
    
    class Test(unittest.TestCase):
    
        @classmethod
        def setUp(self):
            print("I'm in setUp")
    
        def test_1(self):
            print("I'm in test 1")
    
        def test_2(self):
            print("I'm in test 2")
    
        def test_10(self):
            print("I'm in test 10")
    
        @classmethod
        def tearDown(self):
            print("I'm in tearDown")
    
    if __name__ == "__main__":
        unittest.main()
    
  • 控制台输出:

    Finding files... done.
    Importing test modules ... done.
    
    I'm in setUp
    I'm in test 1
    I'm in tearDown
    I'm in setUp
    I'm in test 10
    I'm in tearDown
    I'm in setUp
    I'm in test 2
    I'm in tearDown
    ----------------------------------------------------------------------
    Ran 3 tests in 0.001s
    
    OK
    

解决方案

在不同的讨论中提出了不同的解决方案,其中一些方案如下:

  • @max讨论Unittest tests order建议将sortTestMethodsUsing设置为None如下:

    import unittest
    unittest.TestLoader.sortTestMethodsUsing = None
    
  • @topocopter在讨论changing order of unit tests in Python中建议将sortTestMethodsUsing设置如下:

    import unittest
    unittest.TestLoader.sortTestMethodsUsing = lambda _, x, y: cmp(y, x)
    
  • @ElmarZander在Unittest tests order讨论中建议使用nose并将您的测试用例编写为函数(而不是某个TestCase派生类的方法)nose不调整顺序,而是使用文件中定义的函数顺序。

  • @Keiji在讨论中Controlling the order of unittest.TestCases提到:

SortTestMethodsUsing需要一个类似于Python2的函数,该函数 在Python3中没有等效项(我去检查了一下是否有<=> 宇宙飞船操作员,但显然不是;他们希望你依赖 分别比较<==,这似乎是一种倒退 步骤...)。该函数接受两个参数进行比较,并且必须返回 如果第一个较小,则为负数。值得注意的是这一特殊情况 大小写时,该函数可能会假定参数永远不相等,因为 unittest不会在其测试名称列表中放置重复项。

考虑到这一点,下面是我找到的最简单的方法,假设 您只使用一个TestCase类:

def make_orderer():
    order = {}

    def ordered(f):
        order[f.__name__] = len(order)
        return f

    def compare(a, b):
        return [1, -1][order[a] < order[b]]

    return ordered, compare

ordered, compare = make_orderer()
unittest.defaultTestLoader.sortTestMethodsUsing = compare

然后,用@ordered注释每个测试方法:

class TestMyClass(unittest.TestCase):
    @ordered
    def test_run_me_first(self):
        pass

    @ordered
    def test_do_this_second(self):
        pass

    @ordered
    def test_the_final_bits(self):
        pass

if __name__ == '__main__':
    unittest.main()
这依赖于Python以被批注的顺序调用批注 函数将出现在文件中。据我所知,这是有意的,而且 如果它变了,我会很惊讶,但我不知道它是不是 有保障的行为。我认为这个解决方案甚至可以在Python2中运行 同样,对于那些不幸被它困住的人,尽管我 我还没有机会对此进行测试。

如果您有多个TestCase类,则需要在class之前为每个类运行一次 定义,但如何将其与sortTestMethodsUsing一起使用 将更加棘手,我也还无法对其进行测试。

郑重声明,我测试的代码不依赖于测试 秩序是固定的-我完全理解你不应该依赖于 测试顺序,这就是人们用来避免回答这个问题的原因 问题。我的测试顺序可以是随机的,它只会起作用 也是。然而,我有一个非常好的理由希望订单 固定到它们在文件中定义的顺序:这使它 更容易看到哪些测试失败。

相关文章