【问题标题】:How to fake Popen in test?如何在测试中伪造 Popen?
【发布时间】:2019-05-08 14:32:19
【问题描述】:

我已经用我自己的 Fake 实现或使用成功地伪造了其他模块 monkeypatch。但在这种情况下,使用假实现或monkeypatch subprocess.Popen 失败:

  • 使用monkeypatch,失败。结果还是真开 windows 标题,而不是“foo”。
class TestController:

    def test_get_all_windows(self, ctrl_fixture, monkeypatch):

        def fake_communicate(a):
            return "foo"

        monkeypatch.setattr(subprocess.Popen, 'communicate', fake_communicate)
        output = ctrl_fixture.get_all_windows()
        print(output)

  • 使用伪装也失败了,我试图模仿original但是 它仍然失败。 output 的结果还是真实的windows 标题,而不是“foo”
class FakePopen(object):
    def __init__(self, args, stdout=None):
        super().__init__()      
        self.args = args
        self.stdout = stdout

    def communicate(self):
        return "foo"

class TestController:
    def test_get_all_windows(self, ctrl_fixture, monkeypatch, mocker):

        def fake_communicate(a):
            return "foo"
        subprocess.Popen = FakePopen
        subprocess.Popen.communicate = fake_communicate
        output = ctrl_fixture.get_all_windows()
        print(output)

我的功能是:

    def get_all_windows(self):
        all_windows = ""
        all_windows_proc = Popen(["wmctrl", "-l"], stdout=PIPE)
        all_windows_dirty, err = all_windows_proc.communicate()
        for line in all_windows_dirty.splitlines():
            windows_name = line.split(None, 3)[-1].decode()
            all_windows += "{}\n".format(windows_name)
        return all_windows

上面的测试使用print 而不是assert,因为我仍然想检查输出。

提前致谢。

更新解决方案

根据munkcmets。非常感谢他。

两种解决方案都有效:

def test_get_all_windows_one(self, ctrl, monkeypatch):

    window_title = b"0x006000ab  0 machine-name foo_window_title"

    def fake_communicate(a):
        return window_title, "err"

    Lupr.controllers.controller.Popen = FakePopen
    Lupr.controllers.controller.Popen.communicate = fake_communicate

    output = ctrl.get_all_windows()
    assert output == "foo_window_title\n"

def test_get_all_windows_two(self, ctrl, monkeypatch):

    window_title = b"0x006000ab  0 machine-name foo_window_title"

    def fake_communicate(a):
        return window_title, "err"

    monkeypatch.setattr(Lupr.controllers.controller, "Popen", FakePopen)
    monkeypatch.setattr(
        Lupr.controllers.controller.Popen, "communicate", fake_communicate
    )
    output = ctrl.get_all_windows()
    assert output == "foo_window_title\n"

【问题讨论】:

  • 您正在修补subprocess.Popen,但在您的测试函数中,您直接使用Popen。您正在更改错误的符号表。如果您的函数在foo.py 中,您需要修补foo.Popen 或更改您的函数以使用subprocess.Popen
  • 哇,工作就像一个魅力,非常感谢。您能否将评论作为答案,以便我将其标记为已解决?

标签: python pytest popen


【解决方案1】:

您正在修补subprocess.Popen,但在您的测试函数中,您直接使用Popen。您正在更改错误的符号表。

如果您的函数在foo.py 中,您需要修补foo.Popen 或更改您的函数以使用subprocess.Popen

【讨论】:

    猜你喜欢
    • 2019-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-11
    • 1970-01-01
    • 1970-01-01
    • 2017-06-07
    • 1970-01-01
    相关资源
    最近更新 更多