response = werkzeug.Response(
'You may not have gone where you intended to go,\n'
'but I think you have ended up where you needed to be.',
status=404
)
return response
Для того чтобы протестировать этот фрагмент, снова используйте класс werkzeug.Client:
>>> client = werkzeug.Client(send_to_endpoint, response_wrapper=werkzeug.Response)
>>> print(client.get("/").data.decode())
You got the index.
>>>
>>> print(client.get("Arthur").data.decode())
What is the air-speed velocity of an unladen swallow?
>>>
>>> print(client.get("42").data.decode())
Other: 42
>>>
>>> print(client.get("time/lunchtime").data.decode()) # no match
You may not have gone where you intended to go,
but I think you have ended up where you needed to be.
Читаем код Werkzeug
При хорошем тестовом покрытии вы можете узнать, что делает библиотека, взглянув на ее юнит-тесты. Проблема в том, что в этом случае вы смотрите на «отдельные деревья», а не на «лес», то есть исследуете странные варианты использования, предназначенные для того, чтобы гарантировать, что код не даст сбой (вместо того чтобы исследовать связи между модулями). Это годится для инструмента вроде Werkzeug, содержащего модульные, слабо связанные компоненты.
Поскольку мы уже знаем, как работают маршрутизация и обертки для запроса и ответа, то теперь можем прочесть файлы werkzeug/test_routing.py и werkzeug/test_wrappers.py.
Когда мы в первый раз откроем файл werkzeug/test_routing.py, можем быстро взглянуть на связи между модулями, поискав импортированные объекты во всем файле.
Рассмотрим все операторы импорта.
Цель этого анализа — исследование связей между модулями. Мы обнаружили, что 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,
super(TwoValueConverter, self).__init__(
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('
], 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=
Как правило, чтение тестов позволяет более подробно ознакомиться с возможностями библиотеки. Теперь понятно, для чего нужна библиотека Werkzeug, поэтому можно двигаться дальше.
Tox в Werkzeug