реклама
Бургер менюБургер меню

Кеннет Рейтц – Автостопом по Python (страница 35)

18

Функция strict_eq() используется довольно часто и определена в файле werkzeug/tests/__init__.py. Предназначена для тестирования и нужна только потому, что в Python 2 существовало явное преобразование между строками в формате Unicode и byte, но на это нельзя полагаться в Python 3.

werkzeug.routing — это тестируемый модуль.

Объект Response применяется всего в одной функции test_dispatch() для подтверждения, что werkzeug.routing.MapAdapter.dispatch() передает правильную информацию, отправленную приложению WSGI.

Эти объекты словаря используются по одному разу. ImmutableDict нужен для того, чтобы подтвердить, что неизменяемый каталог, указанный в werkzeug.routing.Map, действительно неизменяем, а MultiDict — чтобы предоставить несколько значений с ключами строителю URL и подтвердить, что был собран правильный URL.

Функция create_environ() предназначена для тестирования: создает среду WSGI без реального запроса HTTP.

Цель этого анализа — исследование связей между модулями. Мы обнаружили, что werkzeug.routing лишь импортирует некоторые специальные структуры данных. Остальная часть юнит-тестов показывает область действия модуля маршрутизации. Например, вы можете использовать символы, не входящие в ASCII:

def test_environ_nonascii_pathinfo():

····environ = create_environ(u'/лошадь')

····m = r.Map([

········r.Rule(u'/', endpoint='index'),

········r.Rule(u'/лошадь', endpoint='horse')

····])

····a = m.bind_to_environ(environ)

····strict_eq(a.match(u'/'), ('index', {}))

····strict_eq(a.match(u'/лошадь'), ('horse', {}))

····pytest.raises(r.NotFound, a.match, u'/барсук')

Существуют тесты для сборки и анализа URL и даже утилиты для поиска ближайшего совпадения, которое не является полным. Вы можете выполнить пользовательскую обработку в процессе преобразования типов путей и строк URL:

def test_converter_with_tuples():

····'''

····Регрессионные тесты для https://github.com/pallets/werkzeug/issues/709

····'''

····class TwoValueConverter(r.BaseConverter):

········def __init__(self, *args, **kwargs):

············super(TwoValueConverter, self).__init__(*args, **kwargs)

············self.regex = r'(\w\w+)/(\w\w+)'

········def to_python(self, two_values):

············one, two = two_values.split('/')

············return one, two

········def to_url(self, values):

············return "%s/%s" % (values[0], values[1])

····map = r.Map([

········r.Rule('/<two: foo>/', endpoint='handler')

····], converters={'two': TwoValueConverter})

····a = map.bind('example.org', '/')

····route, kwargs = a.match('/qwert/yuiop/')

····assert kwargs['foo'] == ('qwert', 'yuiop')

Аналогично немногое импортируется в файле werkzeug/test_wrappers.py. В тесте показывается функциональность, доступная объекту Request, — cookies, кодировки, аутентификация, безопасность, таймауты кэша и даже мультиязычные кодировки:

def test_modified_url_encoding():

····class ModifiedRequest(wrappers.Request):

········url_charset = 'euc-kr'

····req = ModifiedRequest.from_values(u'/?foo= '.encode('euc-kr'))

····strict_eq(req.args['foo'], u' ')

Как правило, чтение тестов позволяет более подробно ознакомиться с возможностями библиотеки. Теперь понятно, для чего нужна библиотека Werkzeug, поэтому можно двигаться дальше.

Tox (https://tox.readthedocs.io/) — инструмент командной строки, который использует виртуальные среды для запуска тестов. Вы можете запускать их на своем компьютере (tox в командной строке), если установлены интерпретаторы Python. Интегрирован с GitHub, поэтому, если у вас есть файл tox.ini на высшем уровне репозитория, как у Werkzeug, он автоматически будет запускать тесты при каждом коммите.

Рассмотрим конфигурационный файл Werkzeug tox.ini целиком:

[tox]

envlist = py{26,27,py,33,34,35}-normal, py{26,27,33,34,35}-uwsgi

·

[testenv]

passenv = LANG

deps=

# General

····pyopenssl

····greenlet

····pytest

····pytest-xprocess

····redis

····requests

····watchdog

····uwsgi: uwsgi

·

# Python 2

····py26: python-memcached

····py27: python-memcached

····pypy: python-memcached