Как получить доступ к настройке unittest.main(verbosity) в unittest.TestCase - программирование
Подтвердить что ты не робот

Как получить доступ к настройке unittest.main(verbosity) в unittest.TestCase

В соответствии с документацией я могу установить уровень многоуровневости python unittest при вызове unittest.main, например.

unittest.main(verbosity=2)

Как я могу получить доступ к этой информации в unittest.TestCase?

4b9b3361

Ответ 1

Проблема с любым методом, основанным на исправлении или подклассе 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

Ответ 2

Способ достижения этого - подкласс unittest.TestCase и unittest.main в файле. Здесь вы определяете переменную (например, globalverb), которую можно использовать глобально или как класс или Singleton, а затем вы переопределяете 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, из аргументов, переданных в unittest.

Комментарии приветствуются.

Ответ 3

Мне не удалось заставить решение 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())

Ответ 4

Мое решение было совсем другим. Вместо monkeypatching я воспользовался тем, что все мои тесты запускаются с помощью специально созданного запуска script. Он собирает различные переменные конфигурации и настройки, поэтому было довольно просто добавить один дополнительный экспорт.

Это может быть разумное решение для более общих случаев, вместо непосредственного запуска тестов, создайте test-runner.sh(или что-то еще), которые будут выполнять один и тот же вызов оболочки, но с дополнительным экспортом, префиксным для него.

Поскольку одно изображение стоит тысяч слов:

Это мой тестовый бегун:

#!/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=$?

И тогда у меня есть этот метод на unit test:

@property
def verbosity(self):
    return int(os.environ.get('TEST_VERBOSITY', 0))

Ответ 5

Если вы просто хотите получить доступ к параметру -v, вы можете проверить его с помощью self._resultForDoCleanups.showAll в своем тесте (наследуя от unittest.TestCase). Поле истинно, если для этого теста вызывается -v.

Ответ 6

Поднимитесь на стек, найдите экземпляр "TestProgram", созданный unittest.main(), и получите доступ к полю verbosity:

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