22

根据文档,我可以在调用时设置 python unittest 的详细级别unittest.main,例如

unittest.main(verbosity=2)

如何在 ? 中访问此信息unittest.TestCase

4

8 回答 8

8

任何基于补丁或子类化的方法的问题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
于 2015-10-01T08:49:52.207 回答
4

实现此目的的一种方法是子类化unittest.TestCaseunittest.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 中使用详细、详细或任何其他数字和信息,从传递给单元测试的参数。

欢迎评论。

于 2012-12-07T12:43:25.833 回答
3

我无法让 Martjin Pieters 的解决方案发挥作用,我认为是因为 unittest.main 在初始化时运行测试,然后将其结果分配给全局。

相反,我将我的初始化替换为:

    def new_parseArgs(self, argv):
        全局 old_parseArgs,verbosity
        old_parseArgs(self, argv)
        冗长 = self.verbosity

    如果 __name__ == '__main__':
        # monkeypatch unittest.TestProgram.parseArgs() 以节省冗长
        # 在全局变量中
        old_parseArgs = unittest.TestProgram.parseArgs
        unittest.TestProgram.parseArgs = new_parseArgs

        单元测试.main()

在需要了解详细程度的测试用例中,我使用如下内容:

            全局冗长

    ...

            如果详细程度 >= 2:
                print("键的顺序:%s" % dd.keys())
于 2015-03-23T11:18:18.917 回答
1

我的解决方案完全不同。我没有使用猴子补丁,而是利用我所有的测试都是通过特制的启动脚本触发的。它收集了各种配置变量和设置环境,因此只需添加一个额外的导出就非常简单了。

对于更通用的情况,这可能是一个明智的解决方案,而不是直接运行测试,而是创建 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))
于 2016-03-10T15:55:41.420 回答
0

如果您只想访问该-v选项,您可以self._resultForDoCleanups.showAll在测试中检查它(继承自unittest.TestCase)。-v如果为该测试调用该字段,则该字段为真。

于 2017-06-11T23:38:47.233 回答
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
于 2016-09-30T20:25:32.653 回答
0

这仅在通过命令行开关设置详细程度时才有效。

我将以下内容放在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()
于 2021-12-06T13:59:24.503 回答
0

如果您总是从命令行运行,则只需解析来自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标志,只需添加另一个调用以add_argument使用该argparse方法,再次基于源代码:

    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
于 2020-07-04T01:14:03.313 回答