【发布时间】:2014-09-21 10:50:41
【问题描述】:
我有一个使用 Python unittest 模块进行单元测试的大型项目。
我有一种小方法可以控制系统行为的大部分方面。在 UT 下运行时,我需要这种方法返回一个固定的结果,以提供一致的测试运行,但对我来说,为每个 UT 模拟它会很昂贵。
有没有办法让这个单一方法,单元测试感知,以便它可以在单元测试下运行时修改其行为?
【问题讨论】:
标签: python unit-testing
我有一个使用 Python unittest 模块进行单元测试的大型项目。
我有一种小方法可以控制系统行为的大部分方面。在 UT 下运行时,我需要这种方法返回一个固定的结果,以提供一致的测试运行,但对我来说,为每个 UT 模拟它会很昂贵。
有没有办法让这个单一方法,单元测试感知,以便它可以在单元测试下运行时修改其行为?
【问题讨论】:
标签: python unit-testing
我确信还有其他更好的方法,但是您始终可以从 main 设置一个全局标志,而不是在单元测试中,然后在您的方法中访问它。
当然,另一种方法是在单元测试设置中覆盖该方法 - 如果您的方法被称为 brian 并且您有一个 test_brian,那么只需在您的预测试设置期间进行 @987654323 @ 将完成这项工作,您可能需要将模块名称放入前面的语句中。
【讨论】:
您可以在运行时为测试修改函数。例如:
def func():
return random.randint()
import module
def replacement_func():
return 4 # chosen by fair dice roll
module.func = replacement_func
# run unit tests here
现在,每当module 中的代码调用func() 时,它实际上会回调到您的replacement_func()。
【讨论】:
我对@987654323@ 模块了解不多,但是如果您是直接运行该文件进行单元测试,则可以在测试代码中附上以下 if:
if __name__ == "__main__":
if 语句中的任何代码只有在您的特定模块被直接调用时才会被执行,而不是导入到其他东西中。根据文档,这就是您应该首先调用unittest.main() 的方式。
https://docs.python.org/2/library/unittest.html
这假设您没有从命令行运行。
编辑:您可以查看函数堆栈以尝试找到 unittest.main() 函数。
import inspect
def in_unit_test():
current_stack = inspect.stack()
for stack_frame in current_stack:
for program_line in stack_frame[4]: # This element of the stack frame contains
if "unittest" in program_line: # some contextual program lines
return True
return False
https://docs.python.org/2/library/inspect.html
这是一种 hacky 解决方案,但 inspect 模块有很多有用的自省功能。
【讨论】:
True,因为函数名称为 in_unittest,并将由 if "unittest" in program_line: 断言
我的解决方案是在运行unittest 之前设置一个TEST_FLAG=true 环境变量。例如:
TEST_FLAG=true python -m unittest discover -s tests -b
那么只需要检查变量是否被设置。例如:
MONGODB_URI =
os.environ.get('MONGODB_URI') if not os.environ.get('TEST_FLAG')
else os.environ.get('MONGODB_TEST_URI')
【讨论】:
使用tox 我设置了一个这样的环境变量:
[testenv]
setenv = TOX_TESTENV = true
然后在代码中检查是否设置了变量:
import os
if os.env.get('TOX_TESTENV'):
# Code is running under test.
# This is useful to configure log levels for example.
【讨论】:
您可以检查unittest 模块是否已加载。只有在测试运行时才应该加载它。
>>> 'unittest' in sys.modules.keys()
False
>>> from unittest import TestCase
>>> 'unittest' in sys.modules.keys()
True
【讨论】:
.keys()而直接使用'unittest' in sys.modules应该会更高效。