【问题标题】:How to unit-test code that uses python-multiprocessing如何对使用 python-multiprocessing 的代码进行单元测试
【发布时间】:2015-10-14 14:51:45
【问题描述】:

我有一些代码使用 multiprocessing.Pool 来分叉工作人员并并行执行任务。我正在尝试找到正确的方法来运行此代码的单元测试。

注意我不是试图并行测试串行代码测试用例,我知道像鼻子支持这样的包。

如果我编写一个测试所述并行代码的测试函数,并尝试通过以下方式用鼻子运行测试:nosetests tests/test_function.py 非并行测试正确执行,但是当多处理尝试分叉时并行测试失败,因为 main 不可导入:

      File "C:\python-2.7.10.amd64\lib\multiprocessing\forking.py", line 488, in prepare
assert main_name not in sys.modules, main_name
AssertionError: __main__
    assert main_name not in sys.modules, main_name
AssertionError:     _assert main_name not in sys.modules, main_name
_main__AssertionError
: __main__

这只是重复,直到我终止任务。如果我将tests/test_function.py 修改为包含以下内容,我可以成功运行测试:

if __name__ == '__main__':
    import nose
    nose.main()

然后用python tests\test_function.py执行

那么,与单元测试包集成的“正确”方法是什么(不必是鼻子)?

环境:Windows 7 64 位上的 Python 2.7.10 amd64

2020 年更新:使用 python 3 和 pytest,这不是问题,建议升级!

【问题讨论】:

    标签: python unit-testing nose python-multiprocessing


    【解决方案1】:

    我更喜欢使用python mock 在单元测试中模拟多处理。因为单元测试应该是独立的可重复的。这就是为什么我通常会创建多处理类的模拟版本(ProcessPool)。只是为了确保我的测试以正确的方式执行。

    【讨论】:

      【解决方案2】:

      看起来像(见http://7fttallrussian.blogspot.com/2014/04/fix-for-bug-with-unittest-and.html

      直到 2.7.6 的所有 Python(即到目前为止的所有 2.x,2014 年 4 月 17 日)中都存在一个错误,该错误在 Windows 上使用 unittest 和 multiprocessing 模块时会中断。 ... 它已在新的 Python 3.x 中修复,但尚未向后移植到 2.x

      我看到有人建议:

      • 补丁多处理模块本身(第一个链接的博文有一个补丁链接。我目前不能在这里发布两个以上的链接)
      • 或在测试模块中实施类似的解决方法:an example of workaround in a test

      “测试中的变通方法示例”中的代码(未进行重大修改):

      import unittest
      import sys
      class TestSample(unittest.TestCase):
          def test(self):
      
              # To fix the Windows forking system it's necessary to point __main__ to
              # the module we want to execute in the forked process
              old_main =                          sys.modules["__main__"]
              old_main_file =                     sys.modules["__main__"].__file__
              sys.modules["__main__"] =           sys.modules["app"]
              sys.modules["__main__"].__file__ =  sys.modules["app"].__file__
      
              # do your testing here
      
              sys.modules["__main__"] =           old_main
              sys.modules["__main__"].__file__ =  old_main_file
      

      免责声明:我自己还没有尝试过这两种解决方案(至少目前还没有)。我遇到了他们和这个问题,同时试图解决不同的问题。如果我尝试任何这些解决方案,我会修改这篇文章。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多