python 跨平台测试:模拟 os.name

python cross platform testing: mocking os.name

模拟 os.name 的正确方法是什么?

我正在尝试对一些使用 os.name 构建适合平台的字符串的跨平台代码进行单元测试。我 运行 在 Windows 机器上运行,但想测试可以在 posix 或 windows.

上 运行 的代码

我试过:

production_code.py

from os import name as os_name

def platform_string():
    if 'posix' == os_name:
      return 'posix-y path'
    elif 'nt' == os_name:
      return 'windows-y path'
    else:
      return 'unrecognized OS'

test_code.py

import production as production 
from nose.tools import patch, assert_true

class TestProduction(object):
    def test_platform_string_posix(self):
    """
    """
    with patch.object(os, 'name') as mock_osname:
        mock_osname = 'posix'
        result = production.platform_string()
    assert_true('posix-y path' == result)

这失败了,因为 os 不在 test_code.py 的全局范围内。如果 'os' 在 test_code.py 中被 import 编辑,那么我们总是会得到 os.name=='nt'.

我也试过:

def test_platform_string_posix(self):
    """
    """
    with patch('os.name', MagicMock(return_value="posix")):
        result = production.platform_string()
    assert_true('posix-y path' == result)

在测试中,但这似乎不起作用,因为 os.name 是一个属性而不是具有 return 值的方法。

编辑: 针对评论的澄清

  1. mock docs (1st paragraph) 看起来直接猴子修补 os.name 可能会变得混乱,例如提出断言
  2. 我们真的只是在os.name的基础上改变路径。虽然测试将在 windows 和 posix 机器上进行 运行,但我想要能够提供全面覆盖的东西,而无需在每次进行小编辑时都为机器提供资源。

根据 Where to patch,您应该在 production_code 中修补 os_name。通过

from os import name as os_name

您正在 production_code 模块中创建 os.name 的引用 os_name:之后(在导入时加载)更改 os.name 无效 os_name参考。

class TestProduction(object):
    @patch("production_code.os_name","posix")
    def test_platform_string_posix(self):
        assert_equal('posix-y path', production.platform_string())