Django manage.py: возможно ли передать аргумент командной строки (для модульного тестирования)

Можно ли передать аргументы командной строки сценарию Django manage.py, в частности, для модульных тестов? т.е. если я что-то вроде

manage.py test myapp -a do_this

Могу ли я получить значение do_this в функции setUp модульного теста?

PS @Martin попросил обоснование использования аргументов командной строки в тестах:

  • Некоторые обширные тесты занимают много времени и не нужно запускать перед каждой фиксацией. Я хочу сделать их необязательными.

  • Иногда отладочные сообщения, напечатанные в моих тестовых случаях, должны быть необязательными

  • Иногда я просто хочу, чтобы тесты сошли с ума и попробовали намного больше перестановок данных.

Все вышеперечисленное было бы весьма удобно с параметрами командной строки. Время от времени тестирование может быть намного более обширным или подробным, иначе оно будет быстрым.

Ответ 1

Я использую обходные переменные среды в моем проекте (работает только в unix-подобных оболочках)

berry$ myvar=myval ./manage.py test 

в вашем модуле прочитайте это значение, используя

os.environ.get('myvar')

Ответ 2

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

Чтобы обойти это, я использовал argparse для извлечения дополнительных параметров в аргумент командной строки. Например, мой файл manage.py теперь выглядит примерно так:

#!/usr/bin/env python
import os
import sys
import argparse


if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")

    argv = sys.argv
    cmd = argv[1] if len(argv) > 1 else None
    if cmd in ['test']:  # limit the extra arguments to certain commands
        parser = argparse.ArgumentParser(add_help=False)
        parser.add_argument('--foo', default='bar')
        args, argv = parser.parse_known_args(argv)
        # We can save the argument as an environmental variable, in
        # which case it to retrieve from within 'project.settings',
        os.environ['FOO'] = args.foo
        # or we can save the variable to settings directly if it
        # won't otherwise be overridden.
        from django.conf import settings
        settings.foo = args.foo

    from django.core.management import execute_from_command_line

    # parse_known_args strips the extra arguments from argv,
    # so we can safely pass it to Django.
    execute_from_command_line(argv)

argparse - действительно хорошая библиотека с множеством функций. Там хороший учебник по нему в документах Python.

Ответ 3

В качестве альтернативного manage.py test -a do_this для управления.py manage.py test -a do_this вы можете использовать определенный файл настроек

manage.py --settings=project.test_settings test

и определите в этом файле все, что захотите.

# test_setting.py
SPECIFIC_OPTION = "test"

# tests.py
from django.conf import settings
...
def setUp(self):
    if settings.SPECIFIC_OPTION:
        ....

Если вам нужны действительно динамические параметры, возможно, вы можете использовать sys.argv в test_settings.py, но это действительно грязный хак.

Ответ 4

Django позволяет добавлять пользовательские параметры командной строки из класса testrunner. Вы можете создать подкласс класса testrunner по умолчанию и добавить свои собственные параметры, а затем позволить django использовать ваш собственный testrunner следующим образом.

Например, создайте testrunner.py в каталоге проекта Django, содержащем:

from django.test.runner import DiscoverRunner

class TestRunner(DiscoverRunner):
    def __init__(self, option=None, **kwargs):
        super().__init__(**kwargs)

        print("Passed option: {}".format(option))

    @classmethod
    def add_arguments(cls, parser):
        DiscoverRunner.add_arguments(parser)

        parser.add_argument('-o', '--option', help='Example option')

Это testrunner, который происходит от лидера по умолчанию (поэтому он работает так же, как и по умолчанию), за исключением того, что он сообщает django добавить дополнительный параметр командной строки (в add_arguments() класса add_arguments()) и обрабатывает значение этой дополнительной опции в конструктор. Чтобы запустить этот новый бегун, пропустите его имя следующим образом:

./manage.py test --testrunner=testrunner.TestRunner -o foo

Конечно, вы можете поместить этот класс в другое место, если вы передадите ему полное имя импорта в командной строке.

Обратите внимание, что вы должны использовать --testrunner=foo, вы не можете использовать два отдельных аргумента (--testrunner foo), так как дополнительные аргументы не работают. Исправлено исправление: https://github.com/django/django/pull/10307

Этот пример просто печатает значение параметра, но вы хотите каким-то образом передать его в свой тестовый файл. Я не мог найти никакой быстрой информации о том, как передавать параметры для unittest testcases, но вы могли бы просто использовать глобальную (модульный уровень) переменную или переменную класса для этого (что не так привлекательно и элегантно, но легко и просто работает).