04.09

Тестирование Django-приложений

В статье рассмотрены 2 вещи:

  1. как сделать дистрибутив django-приложения, с возможностью запуска его тестов до установки;
  2. как автоматизировать процесс тестирования приложения в разных окружениях с помощью tox.
Приводятся примеры скриптов и конфигурационных файлов, ссылки на документацию.

Дистрибутив приложения с возможностью тестирования

По сути любое повторно используемое django-приложение является пакетом python. Для простой установки пакета с помощью distribute или setuptool он должен содержать мета-информацию в setup.py. Библиотекой setuptools предусмотрена возможность тестирования пакета до его установки, с помощью выполнения внутри пакета команды

python setup.py test

Это возможно, если в функцию setup передан аргумент test_suite. Данный аргумент должен указывать на функцию или другой исполняемый объект, осуществляющий запуск тестов для данного пакета (подробный пример рассмотрен ниже).

Другими полезными опциями для организации тестирования являются tests_require и test_loader.

С помощью tests_require можно передать список пакетов необходимых для запуска тестов. Данный аргумент похож на install_requires, но пакеты, указанные в нем, если они отсутсвуют в системе, не устанавливаются. Перед запуском тестов они будут автоматически скачаны и распакованы в папку с приложением. К их зависимостям применяется тот же сценарий. Это полезно, если для тестирования используются дополнительные библиотеки, которые не требуются для работы приложения.

С помощью test_loader можно указать для поиска тестов свой алгоритм. Он должен содержаться в классе с методом loadTestsFromNames(). Подробней смотрите в документации по setuptools.

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

1. Пакет приложения кроме самого приложения содержит проект, настроенный для тестирования данного приложения. Исполняемый объект, указанный в test_suite, запускает тесты, используя настройки этого проекта. Пример из статьи Эрика Холшера:

#This file mainly exists to allow python setup.py test to work.
import os, sys
os.environ['DJANGO_SETTINGS_MODULE'] = 'test_project.settings'
test_dir = os.path.dirname(__file__)
sys.path.insert(0, test_dir)

from django.test.utils import get_runner
from django.conf import settings

def runtests():
    test_runner = get_runner(settings)
    failures = test_runner([], verbosity=1, interactive=True)
    sys.exit(failures)

if __name__ == '__main__':
    runtests()

2. Если приложение очень простое и нет необходимости в демо-проекте, то все необходимые настройки проекта можно указать в скрипте для запуска тестов:

#!/usr/bin/env python
from django.conf import settings
from django.core.management import call_command

APP_NAME = 'my_app'

settings.configure(
	INSTALLED_APPS=(
		'django.contrib.contenttypes',
		'django.contrib.sites',
		APP_NAME,
	),
	# Django replaces all of this, but it still wants it. *shrugs*
	DATABASE_ENGINE='sqlite3',
	DATABASE_NAME=':memory:',
	ROOT_URLCONF='%s.urls' % APP_NAME,
	USE_L10N=True,
	DATE_FORMAT="d.m.Y",
	DATETIME_FORMAT="d.m.Y  H:i",
	TIME_FORMAT="H:i",
	SITE_ID=1,
)

def runtests():
	import django.test.utils
	runner_class = django.test.utils.get_runner(settings)
	test_runner = runner_class(verbosity=1, interactive=True)
	failures = test_runner.run_tests([APP_NAME])
	sys.exit(failures)

if __name__ == '__main__':
	runtests()

Важным моментом в данном примере является импорт django.test.utils. Настройки Django-проекта должны быть установлены до его импорта, иначе получим ошибку, что Django не может найти файл с настройками проекта.

Тестирование приложения в разных окружениях

Допустим нам нужна гарантия, что приложение будет стабильно работать с разными версиями интерпритатора python. Мы можем установить необходимые версии в систему и для тестирования нашего приложения развернуть несколько виртуальных окружений с помощью virtualenv. В процессе разработки приложения перед запуском тестов необходимо в каждую виртуальную среду развернуть новую версию приложения и запустить тесты отдельно для каждого окружения. Автоматизировать данный процесс можно с помощью tox. Конечно гораздо круче для этого использовать Jenkins или другую систему непрерывной интеграции, но для разработчика от tox результат тестирования будет получен быстрее (обычно чтобы код попал на сервер интеграции, необходимо сначало добавить его в репозиторий).

Для тестирования приложения с помощью tox необходимо к его дистрибутиву добавить файл tox.ini, содержащий настройки для развертывания виртуальных окружений. Для каждого окружения можно указать набор зависимостей и команды, которые будут выполнены в процессе тестирования.

Пример конфигурации с двумя окружениями и построением отчета по покрытию кода тестами (отчет строится только для одного окружения, тесты выполняются для обоих):

[tox]
downloadcache = .tox/_download/
envlist = py26, py27

[testenv]
deps =
	mock
commands =
	{envpython} setup.py test

[testenv:py27]
deps =
	coverage
	mock
commands =
    coverage run --branch --source=news_line setup.py test
    coverage report --omit=news_line/tests.py,news_line/migrations/*
    coverage html --omit=news_line/tests.py,news_line/migrations/* -d reports/coverage/

Запуск тестов производится с помощью команды tox.

Что происходит после запуска:

  • tox создает дистрибутив приложения;
  • разворачивает, указанные в конфиге виртуальные окружения;
  • устанавливает дистрибутив приложения;
  • запускает тесты для дистрибутива (команды, указанные в конфиге окружения).
Выполнение каждого этапа сопровождается выводом на экран и в файлы журналов.

 

Подробней про tox можно почитать в его документации:

Раздел: Django Тэги: setup.py, setuptools, tox, тесты

Коментарии

#109.09.2015, 18:47 kjhjhkj@mail.ru пишет:

3

Оставьте комментарий

© 2010 Алексей Камедов

При копировании материалов блога ссылка на источник обязательна.