如何实现测试套件中测试类的顺序执行:先跑完一类再执行下一类
你遇到的核心问题是混用了unittest测试套件和pytest的@pytest.mark.run(order=...)标记,两者的执行顺序逻辑发生了冲突:
- unittest的
TestSuite会按类分组执行测试,但pytest的order标记是全局生效的——它会把所有带order标记的测试方法按数字从小到大排序,完全忽略类的归属。 - 最终导致两个测试类的方法按order值穿插执行(比如两个类的
order=1方法先跑,再跑两个类的order=2方法),出现了你看到的“同时调用两个类测试方法”的现象。
下面给出两种针对性的解决方案,你可以根据自己的技术栈偏好选择:
方案一:纯用Unittest控制执行顺序
如果想继续依赖unittest的测试套件,需要移除pytest的order标记,让unittest严格按类分组执行,同时确保类内方法的执行顺序符合预期。
步骤1:调整测试类,移除pytest的order标记
以hamburgerTest类为例,移除所有方法上的@pytest.mark.run(order=...),如果方法名的默认ASCII排序不符合你的执行需求,可以自定义类内方法的排序逻辑:
from pages.Home.hamburger_page import HamburgerPage from utilites.testStatus import TestStatus import pytest import unittest @pytest.mark.usefixtures("oneTimeSetUp", "setUp") class hamburgerTest(unittest.TestCase): # 自定义类内测试方法的执行顺序 def sortTestMethodsUsing(self, name1, name2): execution_order = [ "test_hamburger_menu_latest_WAF021", "test_hamburger_menu_top__WAF022", "test_hamburger_menu_badges__WAF023", "test_hamburger_menu_users__WAF024", "test_hamburger_menu_groups__WAF025", "test_hamburger_menu_announcements__WAF026" ] return execution_order.index(name1) - execution_order.index(name2) @pytest.fixture(autouse=True) def classSetup(self, oneTimeSetUp): self.ha = HamburgerPage(self.driver) self.ts = TestStatus(self.driver) def test_hamburger_menu_latest_WAF021(self): result = self.ha.find_latest() self.ts.markFinal("To find latest link", result, "Click on latest link") # 其他测试方法保持原有逻辑,移除order标记...
同样处理TopicTest类,移除pytest的order标记,按需自定义类内方法排序。
步骤2:保留原有测试套件代码
你的现有测试套件已经是按类分组的,只要pytest的order标记不再干扰,unittest会先执行完hamburgerTest的所有方法,再执行TopicTest的所有方法:
import unittest from tests.Home.hamburger_test import hamburgerTest from tests.Home.topic_test import TopicTest # 加载两个测试类的所有用例 tc1 = unittest.TestLoader().loadTestsFromTestCase(hamburgerTest) tc2 = unittest.TestLoader().loadTestsFromTestCase(TopicTest) # 按顺序组合测试套件 Test1 = unittest.TestSuite([tc1, tc2]) # 执行测试 unittest.TextTestRunner(verbosity=2).run(Test1)
方案二:纯用Pytest控制类级执行顺序
如果更倾向于pytest的生态,建议放弃unittest的TestSuite,改用pytest的类级order标记,确保整个类的所有方法执行完后,再执行下一个类。
步骤1:给测试类添加类级order标记
修改hamburgerTest类,添加类级的@pytest.mark.run(order=1),标记它为第一个执行的类:
from pages.Home.hamburger_page import HamburgerPage from utilites.testStatus import TestStatus import pytest import unittest @pytest.mark.run(order=1) # 类级order,确保这个类先执行 @pytest.mark.usefixtures("oneTimeSetUp", "setUp") class hamburgerTest(unittest.TestCase): @pytest.fixture(autouse=True) def classSetup(self, oneTimeSetUp): self.ha = HamburgerPage(self.driver) self.ts = TestStatus(self.driver) @pytest.mark.run(order=1) def test_hamburger_menu_latest_WAF021(self): result = self.ha.find_latest() self.ts.markFinal("To find latest link", result, "Click on latest link") # 其他测试方法保持原有order标记不变...
修改TopicTest类,添加类级的@pytest.mark.run(order=2),标记它在第一个类之后执行:
from pages.Home.topic_page import topicPage from utilites.testStatus import TestStatus import pytest import unittest import time @pytest.mark.run(order=2) # 类级order,在第一个类执行完成后再运行 @pytest.mark.usefixtures("oneTimeSetUp","setUp") class TopicTest(unittest.TestCase): @pytest.fixture(autouse=True) def classSetup(self,oneTimeSetUp): self.tp = topicPage(self.driver) self.ts = TestStatus(self.driver) @pytest.mark.run(order=1) def test_header_login(self): self.tp.find_header_logIn() # 其他测试方法保持原有order标记不变...
步骤2:用pytest命令直接运行测试
不需要再写unittest的测试套件代码,直接用pytest命令执行测试文件即可:
pytest path/to/your/test/directory -v
pytest会先执行标记为order=1的类的所有方法(类内方法按自身的order标记执行),完成后再执行标记为order=2的类。
额外建议
- 尽量避免同时混用unittest和pytest的执行顺序控制逻辑,减少冲突风险。
- 如果使用pytest,推荐使用官方维护的
pytest-order插件(替代旧的pytest-ordering),功能更稳定:
用法和上述类似,只需把pip install pytest-order@pytest.mark.run(order=N)换成@pytest.mark.order(N)即可。
内容的提问来源于stack exchange,提问作者manoj

