Pytest:如何盲目运行任何子进程并捕获所有输出?

问题描述 投票:0回答:2

我有一个 Python 程序,它可以在其他几种语言的脚本上调用

print()
和/或调用
subprocess.Popen()
,也可以
print, console.log, system.out.println,
等。实际的程序可以轻松地将所有这些打印到终端,这是预期的行为.

对于集成测试,我想捕获所有这些输出以检查它是否与预期值匹配。我无法模拟子流程。这不是单元测试,我不关心我的Python代码实际上在做什么,只关心输出是否正确。

所有这些选项都可用于捕获内部 Python 输出:

代码大致如下。对于

capfd

redirect_stdout
,您只需改变 
run_string
 之前和之后所做的事情即可。

# tests are parametrized from several JSON files. def test_code(test_json): with open("/tmp/output_file.txt", "w+") as output_file: orig_stdout = sys.stdout sys.stdout = output_file print("initial") run_string(test_json["code"]) output_file.seek(0) sys.stdout = orig_stdout output = output_file.read() assert output == test_json["expected"]
这些都完美地获得了内部输出,但都

未能subprocess.Popen

获得一致的输出。我尝试过使用所有这些方法,将 
subprocess.stdout
 设置为文件,设置为 
PIPE
 并稍后将其打印回来,
shell=True
 以及其他一些方法,但它们都有相同的奇怪问题。我真的无法解释这种行为,所以我只是希望有人可以帮助我:

    当我实际使用 CLI 运行代码时,所有这些代码都工作正常。
  • JavaScript 子进程始终有效,无论我使用哪种方法,它的输出都会被正确捕获。
  • 当我使用 VSCode 集成测试调试时,
  • Python 子进程
  • 确实工作,但当我从命令行运行pytest时,
    。啊?为什么?!?!?!?
  • Lua 子进程完全挂起。看来子进程从未真正启动,尽管很难判断发生了什么,因为我无法从 Python 调试到 Lua,而且我不能只是打印出来,因为 Pytest 试图捕获所有内容。
  • 到目前为止我只添加了这 3 种语言,但我打算添加更多语言(理论上是所有语言),所以我希望有一个通用的解决方案。
我也可以尝试测试整个 CLI,但我想避免这种情况,而且我不确定它是否会起作用。如果有人知道一种方法来强制 Pytest 像本机代码一样运行,而无需将子进程放入某种盒子中,那么这确实是我所需要的。

python subprocess pytest
2个回答
0
投票
对于那些想知道的人,我最终选择了

capfd

 钩子,并完全删除了嵌套子流程的要求。我的应用程序需要执行的子进程不再允许直接输出到 shell,特别是因为它是如此不一致。这是我最终得到的代码。

def test_dits(dit_json, capfd): if "long" in dit_json and not pytest.all_val: # type: ignore pytest.skip("Long test") run_string(dit_json["dit"], "tests/fail.dit") output, err = capfd.readouterr() assert output == dit_json["expected"]
    

0
投票
我参加聚会迟到了,但是对于任何做类似事情的人来说,如果您在 pytest 测试中使用

capture_output=True

,请记住通过“
subprocess.run( )
”。

如果这样做,则返回对象将包含来自子流程的

stdout

 数据。有关更多信息,请参阅 
Python stdlib 子进程文档...

© www.soinside.com 2019 - 2024. All rights reserved.