1. 测试用例分组并行执行
- pytest:
- 可以使用
pytest - xdist
插件实现并行测试。首先安装插件:pip install pytest - xdist
。
- 假设我们有以下测试文件
test_example.py
:
import pytest
def test_1():
assert 1 + 1 == 2
def test_2():
assert 2 + 2 == 4
def test_3():
assert 3 + 3 == 6
- 在命令行中使用`pytest -n 4`(`4`表示使用4个进程并行执行测试,可根据机器性能调整),`pytest`会自动将测试用例分配到不同进程并行执行,提高执行效率。
- unittest:
unittest
本身没有直接的并行执行功能,但可以结合multiprocessing
模块实现。例如:
import unittest
import multiprocessing
class TestExample(unittest.TestCase):
def test_1(self):
self.assertEqual(1 + 1, 2)
def test_2(self):
self.assertEqual(2 + 2, 4)
def test_3(self):
self.assertEqual(3 + 3, 6)
def run_tests(test_class):
suite = unittest.TestLoader().loadTestsFromTestCase(test_class)
unittest.TextTestRunner().run(suite)
if __name__ == '__main__':
processes = []
for _ in range(4): # 4个进程
p = multiprocessing.Process(target = run_tests, args = (TestExample,))
processes.append(p)
p.start()
for p in processes:
p.join()
2. 有效利用缓存机制减少重复计算
- pytest:
- 可以使用
functools.lru_cache
来缓存函数结果。例如,在测试中有一个计算开销较大的函数:
import pytest
import functools
@functools.lru_cache(maxsize = 128)
def expensive_calculation(x):
# 模拟复杂计算
result = 0
for i in range(x * 1000000):
result += i
return result
def test_expensive_calculation():
result1 = expensive_calculation(5)
result2 = expensive_calculation(5)
assert result1 == result2
- unittest:同样可以在
unittest
测试用例中使用functools.lru_cache
,用法与pytest
场景类似。
3. 其他优化方面
- 跳过不必要的测试:
- pytest:使用
pytest.mark.skipif
装饰器跳过在特定条件下不需要执行的测试。例如:
import sys
import pytest
@pytest.mark.skipif(sys.platform == 'win32', reason = "不支持Windows平台")
def test_not_windows():
# 测试代码
pass
- **unittest**:在`unittest`中,可以在测试方法中手动检查条件并使用`self.skipTest`方法跳过测试。例如:
import sys
import unittest
class TestSkip(unittest.TestCase):
def test_skip(self):
if sys.platform == 'win32':
self.skipTest("不支持Windows平台")
# 测试代码
pass
- 优化测试夹具(fixture):
- pytest:对于一些开销较大的
fixture
,可以设置scope
为module
或session
,减少创建次数。例如:
import pytest
@pytest.fixture(scope ='module')
def expensive_fixture():
# 创建fixture的代码,如数据库连接等
connection = "模拟数据库连接"
yield connection
# 清理代码,如关闭数据库连接
connection.close()
def test_with_fixture(expensive_fixture):
# 使用fixture的测试代码
pass
- **unittest**:在`unittest`中,`setUpClass`和`tearDownClass`方法类似`pytest`中`scope`为`module`的`fixture`,可以在类级别设置和清理资源,减少重复操作。例如:
import unittest
class TestWithFixture(unittest.TestCase):
@classmethod
def setUpClass(cls):
# 创建资源,如数据库连接等
cls.connection = "模拟数据库连接"
@classmethod
def tearDownClass(cls):
# 清理资源,如关闭数据库连接
cls.connection.close()
def test_with_fixture(self):
# 使用资源的测试代码
pass