如何在测试中伪造 Popen? [英] How to fake Popen in test?

查看:53
本文介绍了如何在测试中伪造 Popen?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've successfully Faked other module with my own Fake implementation or using monkeypatch. But in this case using both fake implementation or monkeypatch failed for subprocess.Popen:

  • 使用 monkeypatch 失败.结果还是真开了窗口标题,而不是foo".
  • Using monkeypatch, failed. The result still the real opened windows title, not "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)

  • 使用伪造也失败了,我试图模仿 原创 但是它仍然失败.output 的结果仍然是真实的窗口标题,而不是foo"
    • Using faking also failed, I've tried to mimic the original but it still failed. The result of output still the real windows titles, not "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 因为我仍然想检查输出.

      The test above using print instead of assert cause I still want to check the output.

      提前致谢.

      更新解决方案

      根据 munk 评论.非常感谢他.

      According to munk comments. Great thanks to him.

      两种解决方案都有效:

      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直接地.您正在更改错误的符号表.

      You're patching subprocess.Popen, but in your function under test you're using Popen directly. You're changing the wrong symbol table.

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

      If your function is in foo.py, you want to patch foo.Popen or change your function to use subprocess.Popen.

      这篇关于如何在测试中伪造 Popen?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆