<p>pytest-randomly 默认只打乱测试类和函数的顺序,不打乱同一类内 test_* 方法的顺序;需加 --randomly-shuffle-methods 参数(≥3.10.0)才能随机化类内方法执行顺序。</p>

pytest-randomly 默认打乱测试函数和测试类的执行顺序,但不会打乱同一测试类内多个 test_* 方法的内部顺序——这是最容易误解的一点。
为什么测试顺序会意外固定?
pytest 默认按文件中定义顺序执行测试,而 pytest-randomly 仅在 pytest 的「收集阶段」后对已收集的测试节点(TestFunction 或 TestCase)做 shuffle。它不介入类内方法的排序逻辑,所以一个类里 test_a、test_b、test_c 总是按源码顺序跑,哪怕整个类被随机排到了第 5 位。
常见错误现象:pytest --randomly-seed=1234 多次运行,类间顺序变,但类内方法顺序不变,误以为“没生效”。
- 确认是否安装:运行
pip install pytest-randomly,不是pytest-random(旧包) - 检查是否被其他插件干扰:比如
pytest-xdist并行时,--randomly-seed必须显式传入,否则各 worker 使用不同默认 seed - 避免在
conftest.py中手动调用random.shuffle()—— 这会和插件冲突,导致重复 shuffle 或报错
如何让类内方法也随机?
必须启用 --randomly-dont-shuffle-classes 的反向配置:不,等等——这个参数其实是「禁用类级别 shuffle」,不是你想要的。真正控制类内方法的是 --randomly-shuffle-classes(默认开启),但它只影响类之间的顺序。
立即学习“Python免费学习笔记(深入)”;
要打乱类内方法,得靠 pytest 自身机制:pytest 从 7.0 起支持 --shuffle(需装 pytest-shutil),但更直接的方式是升级到 pytest-randomly>=3.10.0 并使用 --randomly-shuffle-methods:
pytest --randomly-shuffle-methods --randomly-seed=42
该参数强制对每个类下的所有 test_* 方法单独 shuffle,且与类间 shuffle 独立。注意:它不改变 fixture 执行顺序,也不影响 setup_method 调用时机。
- 只对标准命名的测试方法生效(
test_*或*_test),不处理@pytest.mark.parametrize生成的子测试项 - 若测试依赖隐式顺序(比如共享临时文件或全局状态),开启此选项大概率暴露 bug,这反而是它的价值所在
- CI 中务必固定
--randomly-seed,否则无法复现失败
seed 不固定导致 CI 失败难以复现?
CI 日志里只显示 Randomized with seed 1729483201,但本地没加 --randomly-seed=1729483201 就无法还原现场。
- 在
pyproject.toml中预设 seed(推荐):[tool.pytest.ini_options] addopts = ["--randomly-seed=1234"]
- 或在 CI 脚本中显式传参:
pytest --randomly-seed=$SEED,并把 $SEED 记录进日志开头 - 不要依赖环境变量
RANDOMLY_SEED—— 它只在无命令行参数时 fallback 生效,优先级低,容易漏 - 如果用
tox,确保deps包含pytest-randomly,且commands显式调用pytest,而非依赖python -m pytest的隐式加载(某些 tox 版本下插件加载不稳定)
最常被忽略的是:pytest-randomly 对 unittest.TestCase 子类的支持有限——它能 shuffle 类,但类内 test_* 方法仍按字母序执行,除非你也启用了 --randomly-shuffle-methods 且 pytest 版本 ≥ 7.2。


















