[英]how to access the unittest.main(verbosity) setting in a unittest.TestCase
根据文档,我可以在调用unittest.main
时设置 python unittest 的详细级别,例如
unittest.main(verbosity=2)
如何在unittest.TestCase
中访问此信息?
任何基于修补或子类化unittest.TestProgram
的方法的问题在于,您必须在启动unittest.TestProgram
之前将补丁安装到位。 但如果您的测试用例是通过发现运行的,那将是不可能的:
python -m unittest discover -v
在发现案例中有效的一种方法是使用inspect
模块搜索堆栈,直到找到unittest.TestProgram
上的方法:
import inspect
import unittest
def unittest_verbosity():
"""Return the verbosity setting of the currently running unittest
program, or 0 if none is running.
"""
frame = inspect.currentframe()
while frame:
self = frame.f_locals.get('self')
if isinstance(self, unittest.TestProgram):
return self.verbosity
frame = frame.f_back
return 0
实现此目的的一种方法是在文件中子类unittest.TestCase
和unittest.main
。 在这里,您定义一个变量(例如globalverb
),可以全局使用或作为类或单例使用,然后覆盖unittest.main
:
def main(*args, **kwargs):
# parse arguments etc to get the verbosity number or whatever
# ...
# set this number to the defined class
globalverb = verbose_number
return unittest.main(*args, **kwargs)
稍后,您将unittest.TestCase
子类化:
class MyTestCase(unittest.TestCase):
def my_special_function(self):
if globalverb ...
通过这种方法,可以在(派生的)TestCase 中使用 verbose、verbosity 或任何其他数字和信息,从传递给单元测试的参数中获取。
欢迎评论。
我无法让 Martjin Pieters 的解决方案工作,我认为是因为 unittest.main 在初始化时运行测试,然后将其结果分配给全局。
相反,我将初始化替换为:
def new_parseArgs(self, argv): global old_parseArgs,verbosity old_parseArgs(self, argv) verbosity = self.verbosity if __name__ == '__main__': # monkeypatch unittest.TestProgram.parseArgs() to save verbosity # in a global variable old_parseArgs = unittest.TestProgram.parseArgs unittest.TestProgram.parseArgs = new_parseArgs unittest.main()
在需要知道详细程度的测试用例中,我使用类似的东西:
global verbosity ... if verbosity >= 2: print("Keys' order: %s" % dd.keys())
我的解决方案完全不同。 我没有使用 monkeypatching,而是利用我所有的测试都是通过特制的启动脚本触发的。 它收集各种配置变量和设置环境,因此只需添加一个额外的导出就非常简单。
对于更一般的情况,这可能是明智的解决方案,而不是直接运行测试,而是创建 test-runner.sh(或其他),它将进行完全相同的 shell 调用,但带有额外的 export 前缀。
因为一图胜千言:
这是我的测试跑步者:
#!/usr/bin/env bash
VERBOSE=false
while getopts ":vt:" opt; do
case $opt in
t)
TEST_TO_RUN=$OPTARG
;;
v)
VERBOSE=true
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done
ENVS=""
ENVS+=" PYTHONPATH=$PYTHONPATH:$PWD"
PARAMS=""
PARAMS+=" -s --nologcapture --with-id"
PARAMS+=" --cov-config=.apirc --cov-report html --with-cov"
SERVER_PRIMER="coverage run --rcfile=.apirc"
if [[ ! -z "$TEST_TO_RUN" ]]; then
PARAMS+=" $TEST_TO_RUN"
fi
if [[ "$VERBOSE" = true ]]; then
PARAMS+=" -v"
ENVS+=" TEST_VERBOSITY=2"
fi
eval "$ENVS nosetests $PARAMS"
RESULT_TEST=$?
然后我在单元测试中使用了这个方法:
@property
def verbosity(self):
return int(os.environ.get('TEST_VERBOSITY', 0))
爬上堆栈,找到由 unittest.main() 创建的“TestProgram”实例,并访问详细字段:
class MyTestCase(unittest.TestCase):
def test_verbosity(self):
"""Return current verbosity"""
for f in inspect.getouterframes(inspect.currentframe() ):
args, _,_, local_dict = inspect.getargvalues(f[0])
if args:
first_arg = args[0]
first_value = local_dict[first_arg]
if type(first_value).__name__ == "TestProgram":
return first_value.verbosity
如果您只想访问-v
选项,您可以在测试中使用self._resultForDoCleanups.showAll
检查它(继承自unittest.TestCase
)。 如果为该测试调用-v
,则该字段为真。
如果你总是从命令行运行,你可以只解析来自sys.argv
的参数。 您可以手动执行此操作(在列表中查找出现的“-v”、“-vv”等),但我通常更喜欢在源代码中查找相关的解析器并使用相同的版本(带有虚假的选项被剥离)。 在您的情况下,它看起来像这样:
相关代码似乎在这里。 我们可以提取那段代码并得到以下内容:
import argparse
verbosity_parser = argparse.ArgumentParser(add_help=False)
verbosity_parser.add_argument(
'-v', '--verbose', dest='verbosity',
action='store_const', const=2,
help='Verbose output') # We could remove this if we want
args, rest = verbosity_parser.parse_known_args()
verbosity = args.verbosity
我刚刚意识到解析器是多么简单。 我习惯了有多个冗长级别的 Django。 在这种情况下,您可能只检查{'-v', '--verbose'} & set(sys.argv)
或类似的东西。
如果您还想处理--quiet
标志,只需再次使用argparse
方法添加对add_argument
的调用,再次基于源代码:
parser.add_argument('-q', '--quiet', dest='verbosity',
action='store_const', const=0,
help='Quiet output') # this could be removed
如果我们愿意,我们还可以处理似乎是隐式默认值的内容:
if verbosity is None:
verbosity = 1
这仅在通过命令行开关设置详细程度时有效。
我将以下内容放在test.py
文件的顶部:
verbose = sum(arg.count('v')
for arg in sys.argv if arg.startswith("-") and not arg.startswith("--"))
在其他地方,在代码中我可以检查verbose
的值并相应地进行跟踪。 例子:
if verbose > 2:
sys.stderr.write("Some very noisy message\n")
sys.stderr.flush()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.