代码之家  ›  专栏  ›  技术社区  ›  curlew77

Pytest:mock/patch sys。stdin在程序中使用python线程

  •  2
  • curlew77  · 技术社区  · 6 年前

    我已经获得了一些在重构之前需要测试的代码。它使用深度递归,因此设置了新的限制,然后在新线程中运行:

    sys.setrecursionlimit(10**6)
    threading.stack_size(2**27)
    ...
    threading.Thread(target=main).start()
    

    代码严重依赖于 sys.stdin sys.stdout 例如

    class SpamClass:
        def read(self):
            self.n = int(sys.stdin.readline())
            ...
            for i in range(self.n):
                [a, b, c] = map(int, sys.stdin.readline().split())
        ...
        def write(self)
            print(" ".join(str(x) for x in spam()))
    

    为了测试代码,我需要传入一系列输入文件的内容,并将结果与一些相应的示例输出文件的内容进行比较。

    到目前为止,我已经尝试了三四种不同类型的模拟和修补,但都没有成功。我的其他测试都是为pytest编写的,所以必须使用其他东西会非常麻烦。

    我试过修补 module.sys.stdin 具有 StringIO ,这似乎不起作用,因为pytest capsys 设置 系统。斯特丁 设置为null,因此会抛出一个错误,尽管有补丁。

    我也尝试过使用pytest的 monkeypatch 用于更换发动机的固定装置 module.SpamClss.read 方法使用测试中定义的函数,但这会产生一个分段错误,我认为这是因为线程在测试之前退出(或者?)。

    'pytest test_spam.py' terminated by signal SIGBUS (Misaligned address error)
    

    有没有关于如何做到这一点的建议?非常感谢。

    1 回复  |  直到 6 年前
        1
  •  2
  •   curlew77    6 年前

    嗯,我仍然不知道问题是什么,也不知道我是否做得对,但它现在起作用了。我不确定线程方面是否正常工作,但其他方面似乎没有问题。

    @pytest.mark.parametrize("inputs, outputs", helpers.get_sample_tests('spampath'))
    def test_tree_orders(capsys, inputs, outputs):
        """
        """
        with patch('module.sys.stdin', StringIO("".join(inputs))):
            module.threading.Thread(target=module.main()).start()
    
        captured = capsys.readouterr()
    
        assert "".join(outputs) == captured.out
    

    对于其他感兴趣的人来说,按照以下步骤进行调试会有所帮助: print(spam, file=sys.stderr) ,然后您可以在测试中作为 captured.err ,参见 captured.out 用于测试。