python 模块级代码中的测试分支
Testing branches in module-level code in python
我们有一个 python 模块,调用者可以使用它来 运行 Mac OS X 上的一些实用命令。命令的路径及其用法不同在 OS 和我们的模块的版本之间是为了对用户隐藏它。我们在导入模块时确定一次OS的版本,像这样(helper.py
,简化以证明这一点):
import platform
from distutils.version import StrictVersion
print('Importing helper module...')
os_version, _, _ = platform.mac_ver()
if StrictVersion(os_version) < StrictVersion('10.10'):
utility1 = 'utility 1 for 10.9 and below'
else:
utility1 = 'utility 1 for 10.10 and above'
def run_utility1():
return 'Running ' + utility1
def run_utility2():
# ...
pass
# ... more cool functions ...
现在我们要向该模块添加测试。具体来说,我们想确保 OS X 的所有版本的实用程序 运行s 都是正确的。我想到的方法是在不同的测试中 patch
platform.mac_ver()
return 一个不同的 OS 版本,并且 assert
我们 运行 正在使用正确的实用程序。像这样:
import mock
import unittest
class HelperTests(unittest.TestCase):
def test_10_9_utility_is_correct(self):
with mock.patch('platform.mac_ver', return_value=('10.9', 'foo', 'foo')):
import helper
result = helper.run_utility1()
print(result)
assert result == 'Running utility 1 for 10.9 and below'
def test_10_10_utility_is_correct(self):
with mock.patch('platform.mac_ver', return_value=('10.10', 'foo', 'foo')):
import helper
result = helper.run_utility1()
print(result)
assert result == 'Running utility 1 for 10.10 and above'
if __name__ == '__main__':
unittest.main()
但这会导致:
Testing started at 12:16 PM ...
Importing helper module...
Running utility 1 for 10.10 and above
Running utility 1 for 10.10 and above
Process finished with exit code 0
Failure
Traceback (most recent call last):
File "helper_test.py", line 13, in test_10_9_utility_is_correct
assert result == 'Running utility 1 for 10.9 and below'
AssertionError
似乎 test_10_10_utility_is_correct
先 运行ning(这是由于测试工具中的方法按字母顺序排列吗?),将 mac_ver()
修补为 return 10.10
然后导入 helper
。当 test_10_9_utility_is_correct
运行s helper
没有再次导入时,它会失败,因为它认为它在 10.10.
我知道 python 不会两次导入模块,这太棒了。但这是否意味着我们不能在测试中使用模块级代码中的分支,因为它只会 运行 一次?如果有办法,怎么做?
我考虑过将模块级 OS 版本检查代码包装在一个函数中。这将使模拟变得容易,但随后所有其他函数都必须首先调用它,这似乎是不必要的,因为 OS 版本不太可能在调用之间改变。我还考虑过将每个测试方法移动到它自己的测试模块中,这会导致 helper
被多次导入,但这看起来很笨拙。 helper.py
?
中给出的两个分支有没有另一种方法来练习
将你的初始化代码放在一个函数中怎么样?
您必须像这样声明您的全局变量:
import platform
from distutils.version import StrictVersion
utility1 = None
def init_module():
global utility1 # declare it global to modify it
print('Importing helper module...')
os_version, _, _ = platform.mac_ver()
if StrictVersion(os_version) < StrictVersion('10.10'):
utility1 = 'utility 1 for 10.9 and below'
else:
utility1 = 'utility 1 for 10.10 and above'
init_module() #Call the init function when importing the module
def run_utility1():
return 'Running ' + utility1
然后在每次新测试时,您可以调用 init 函数:
import mock
import unittest
import helper
class HelperTests(unittest.TestCase):
def test_10_9_utility_is_correct(self):
with mock.patch('platform.mac_ver', return_value=('10.9', 'foo', 'foo')):
helper.init_module()
result = helper.run_utility1()
print(result)
assert result == 'Running utility 1 for 10.9 and below'
def test_10_10_utility_is_correct(self):
with mock.patch('platform.mac_ver', return_value=('10.10', 'foo', 'foo')):
helper.init_module()
result = helper.run_utility1()
print(result)
assert result == 'Running utility 1 for 10.10 and above'
if __name__ == '__main__':
unittest.main()
我们有一个 python 模块,调用者可以使用它来 运行 Mac OS X 上的一些实用命令。命令的路径及其用法不同在 OS 和我们的模块的版本之间是为了对用户隐藏它。我们在导入模块时确定一次OS的版本,像这样(helper.py
,简化以证明这一点):
import platform
from distutils.version import StrictVersion
print('Importing helper module...')
os_version, _, _ = platform.mac_ver()
if StrictVersion(os_version) < StrictVersion('10.10'):
utility1 = 'utility 1 for 10.9 and below'
else:
utility1 = 'utility 1 for 10.10 and above'
def run_utility1():
return 'Running ' + utility1
def run_utility2():
# ...
pass
# ... more cool functions ...
现在我们要向该模块添加测试。具体来说,我们想确保 OS X 的所有版本的实用程序 运行s 都是正确的。我想到的方法是在不同的测试中 patch
platform.mac_ver()
return 一个不同的 OS 版本,并且 assert
我们 运行 正在使用正确的实用程序。像这样:
import mock
import unittest
class HelperTests(unittest.TestCase):
def test_10_9_utility_is_correct(self):
with mock.patch('platform.mac_ver', return_value=('10.9', 'foo', 'foo')):
import helper
result = helper.run_utility1()
print(result)
assert result == 'Running utility 1 for 10.9 and below'
def test_10_10_utility_is_correct(self):
with mock.patch('platform.mac_ver', return_value=('10.10', 'foo', 'foo')):
import helper
result = helper.run_utility1()
print(result)
assert result == 'Running utility 1 for 10.10 and above'
if __name__ == '__main__':
unittest.main()
但这会导致:
Testing started at 12:16 PM ...
Importing helper module...
Running utility 1 for 10.10 and above
Running utility 1 for 10.10 and above
Process finished with exit code 0
Failure
Traceback (most recent call last):
File "helper_test.py", line 13, in test_10_9_utility_is_correct
assert result == 'Running utility 1 for 10.9 and below'
AssertionError
似乎 test_10_10_utility_is_correct
先 运行ning(这是由于测试工具中的方法按字母顺序排列吗?),将 mac_ver()
修补为 return 10.10
然后导入 helper
。当 test_10_9_utility_is_correct
运行s helper
没有再次导入时,它会失败,因为它认为它在 10.10.
我知道 python 不会两次导入模块,这太棒了。但这是否意味着我们不能在测试中使用模块级代码中的分支,因为它只会 运行 一次?如果有办法,怎么做?
我考虑过将模块级 OS 版本检查代码包装在一个函数中。这将使模拟变得容易,但随后所有其他函数都必须首先调用它,这似乎是不必要的,因为 OS 版本不太可能在调用之间改变。我还考虑过将每个测试方法移动到它自己的测试模块中,这会导致 helper
被多次导入,但这看起来很笨拙。 helper.py
?
将你的初始化代码放在一个函数中怎么样?
您必须像这样声明您的全局变量:
import platform
from distutils.version import StrictVersion
utility1 = None
def init_module():
global utility1 # declare it global to modify it
print('Importing helper module...')
os_version, _, _ = platform.mac_ver()
if StrictVersion(os_version) < StrictVersion('10.10'):
utility1 = 'utility 1 for 10.9 and below'
else:
utility1 = 'utility 1 for 10.10 and above'
init_module() #Call the init function when importing the module
def run_utility1():
return 'Running ' + utility1
然后在每次新测试时,您可以调用 init 函数:
import mock
import unittest
import helper
class HelperTests(unittest.TestCase):
def test_10_9_utility_is_correct(self):
with mock.patch('platform.mac_ver', return_value=('10.9', 'foo', 'foo')):
helper.init_module()
result = helper.run_utility1()
print(result)
assert result == 'Running utility 1 for 10.9 and below'
def test_10_10_utility_is_correct(self):
with mock.patch('platform.mac_ver', return_value=('10.10', 'foo', 'foo')):
helper.init_module()
result = helper.run_utility1()
print(result)
assert result == 'Running utility 1 for 10.10 and above'
if __name__ == '__main__':
unittest.main()