如何让pytest忽略返回非零代码并写入stderr的特定子进程调用?
我来帮你搞定这个pytest测试的问题!
你现在遇到的核心问题是:调用somedaemon子进程时,用了像subprocess.check_call或check_output这类会抛出异常的方法——这些方法在子进程返回非零退出码时,会触发CalledProcessError,而pytest会把未捕获的异常判定为测试失败。但你期望这个子进程失败是正常场景,所以需要主动处理这个逻辑,让pytest认可这是预期结果。
下面给你两种可行的解决方案,适配CentOS 7环境:
方案1:改用subprocess.run(推荐)
subprocess.run不会因为子进程非零退出而抛出异常,你可以直接获取退出码和输出内容,然后通过断言验证预期行为:
import subprocess def test_somedaemon_expected_failure(): # 调用子进程,同时捕获stdout和stderr proc_result = subprocess.run( ["somedaemon"], stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True # 如果是Python 3.6+可用,让输出以字符串而非字节返回 ) # 断言子进程返回非零码 assert proc_result.returncode != 0, "Somedaemon应该返回非零退出码" # 断言stderr有内容输出 assert proc_result.stderr.strip() != "", "Somedaemon应该向stderr输出内容"
方案2:用pytest.raises捕获预期异常
如果你习惯用check_call/check_output这类方法,可以用pytest的上下文管理器pytest.raises主动捕获预期的CalledProcessError,同时验证异常的细节:
import subprocess import pytest def test_somedaemon_expected_failure(): with pytest.raises(subprocess.CalledProcessError) as exc_info: subprocess.check_call( ["somedaemon"], stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True ) # 验证退出码符合预期 assert exc_info.value.returncode != 0 # 验证stderr确实有输出 assert exc_info.value.stderr.strip() != ""
针对CentOS 7的额外提示
CentOS 7默认的Python版本可能偏旧(比如Python 2.7或3.6):
- 如果是Python 2.7,
subprocess.run不存在,你可以改用subprocess.call,它会直接返回退出码,不会抛出异常:import subprocess def test_somedaemon_expected_failure(): returncode = subprocess.call( ["somedaemon"], stderr=subprocess.PIPE, stdout=subprocess.PIPE ) assert returncode != 0 - 如果
somedaemon是后台守护进程,可能需要添加timeout参数(Python 3.3+支持)或者额外检查进程状态,确保它确实按预期退出,而非挂起。
如果应用Branden的解决方案后有具体的结果或新问题,也可以补充细节再调整,但上面的方案应该能解决你最核心的需求:让pytest接受子进程的非零退出为预期行为,从而让测试通过。
内容的提问来源于stack exchange,提问作者J. Curtis
相关产品推荐
相关产品推荐

