В соответствии с документацией я могу установить уровень многоуровневости python unittest при вызове unittest.main
, например.
unittest.main(verbosity=2)
Как я могу получить доступ к этой информации в unittest.TestCase
?
В соответствии с документацией я могу установить уровень многоуровневости python unittest при вызове unittest.main
, например.
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
), которую можно использовать глобально или как класс или 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.
Комментарии приветствуются.
Мне не удалось заставить решение 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 я воспользовался тем, что все мои тесты запускаются с помощью специально созданного запуска 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))
Если вы просто хотите получить доступ к параметру -v
, вы можете проверить его с помощью self._resultForDoCleanups.showAll
в своем тесте (наследуя от unittest.TestCase
). Поле истинно, если для этого теста вызывается -v
.
Поднимитесь на стек, найдите экземпляр "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