Часть 2: концепция, установка и простое «hello world» приложение
Безусловно, тестирование помогает обеспечить будущее качество и облегчает рефакторинг. И это же, конечно, делает разработку более быстрой, в особенности при использовании умных редакторов и IDE. Перезапуск вашего приложения и щёлканье в вашем браузере это грустьпичаль(drag).
В этом шаге используется тот же код, что и в шаге первом, но мы добавим немного тестов.
Создаем директорию в правильном месте.
Копируем нижеследующее, во вновь созданный файл
Копируем следующее в
После этого мы должны увидеть следующий результат:
Юнит-тесты это сложно. Юнит-тесты с фреймворком это ещё сложнее. Культура Pyramid, несмотря на это, нацелена на полное покрытие тестами, и Pyramid работает очень усердно, чтобы делать написание тестов полезным занятием.
Даже если вы не делаете полное покрытие тестами, вы обнаружите что большинство базовых юнит-тестов ловят стандартные ошибки быстрее чем открытие вашего браузера, для проверки, при каждом изменении кода. Это немного похоже на установку вашего редактора, или IDE, чтобы запустить pylint который позволяет вам знать до сохранения (намного меньше, перед выполнением) есть ли у вас ошибки.
Функциональные тесты проще к написанию, и для UX-людей, помогают в части рассматриваемой проблемы.
Большинство веб-систем обладают языком шаблонов, для генерации HTML. Это дает UX-человеку возможность сконцентрироваться на вещи, которую они знают (разметка) и вкраплениями в коде, а не наоборот.
Pyramid doesn’t have too much of an opinion on templating languages. This tutorial does though. We’re Chameleon/ZPT folks. Так давайте же сделаем “hello world”, используя шаблон страницы.
Вспомнить что в разделе установки сказано сделать
Копировать нижеследующее в
Вслед за чем должны увидеть:
Пробуем запустить:
И открываем
Если вы редактируете тему, необходимо ли вам делать перезапуск приложения, чтобы увидеть изменения?
Какие другие значения возможны для рендерера, на @view_config?
Этот шаг дает представление о разборе кода. Есть несколько различных путей чтобы сделать конфигурацию в Pyramid: императивный (который мы видели в первом шаге: Hello World в Pyramid), сканирующий (близкий ко многим современным веб-фреймворкам), и наш старый друг ZCML. The choice is mainly one of style, though there are some sharp edges in some cases.
Note the coolness… все что вам следует делать это вернуть словарь в ваше представление, и ваш шаблон вызывается on the way out the door, с этими данными.
История конфигурирования в Zope2, Zope3, BFG, потом Pyramid
How things worked before renderers
Следом идет часть 4.
Шаг 02: юнит- и функциональное тестирование
Безусловно, тестирование помогает обеспечить будущее качество и облегчает рефакторинг. И это же, конечно, делает разработку более быстрой, в особенности при использовании умных редакторов и IDE. Перезапуск вашего приложения и щёлканье в вашем браузере это грустьпичаль(drag).
В этом шаге используется тот же код, что и в шаге первом, но мы добавим немного тестов.
Цели
- Покрыть код юнит-тестами
- Создать функциональные тесты на ответы
Технические требования
- Написать юнит-тест в Pyramid-стиле
- Использовать WebTest, чтобы включить функциональный тест, в модуль тестов
- Использовать nose и nosetests просмотрщик, для запуска тестов
Шаги
$ cd ../../creatingux; mkdir step02; cd step02
Создаем директорию в правильном месте.
Копируем нижеследующее, во вновь созданный файл
step02/application.py
:from wsgiref.simple_server import make_serverЭто тот же самый код, который мы видели в шаге первом.
from pyramid.config import Configurator
from pyramid.response import Response
def hello_world(request):
return Response('hello!')
def main():
config = Configurator()
config.add_view(hello_world)
app = config.make_wsgi_app()
return app
if __name__ == '__main__':
app = main()
server = make_server('0.0.0.0', 8080, app)
server.serve_forever()
Копируем следующее в
step02/tests.py
:import unittest
class ProjectorViewsUnitTests(unittest.TestCase):
def test_hello_world(self):
from application import hello_world
result = hello_world({})
self.assertEqual(result.body, 'hello!')
class ProjectorFunctionalTests(unittest.TestCase):
def setUp(self):
from application import main
app = main()
from webtest import TestApp
self.testapp = TestApp(app)
def test_it(self):
res = self.testapp.get('/', status=200)
self.failUnless('hello' in res.body)
$ nosetests
После этого мы должны увидеть следующий результат:
..
--------------------------------------------------------
Ran 2 tests in 0.301s
OK
Дополнительные вопросы
- Как nose узнает, что тесты в файле tests.py?
- Запускает ли WebTest реальный HTTP-сервер, чтобы послать HTTP-запрос?
- Если ваш код выдает ошибку, обрабатывает ли Pyramid её корректно?
Анализ
Юнит-тесты это сложно. Юнит-тесты с фреймворком это ещё сложнее. Культура Pyramid, несмотря на это, нацелена на полное покрытие тестами, и Pyramid работает очень усердно, чтобы делать написание тестов полезным занятием.
Даже если вы не делаете полное покрытие тестами, вы обнаружите что большинство базовых юнит-тестов ловят стандартные ошибки быстрее чем открытие вашего браузера, для проверки, при каждом изменении кода. Это немного похоже на установку вашего редактора, или IDE, чтобы запустить pylint который позволяет вам знать до сохранения (намного меньше, перед выполнением) есть ли у вас ошибки.
Функциональные тесты проще к написанию, и для UX-людей, помогают в части рассматриваемой проблемы.
Тезисы
- Pyramid (и repoze.bfg до неё) и верность тестовому покрытию
- Философия юнит-тестирования против функциональных тестов, против док-тестов
- The challenge in setup/teardown regarding configuration, registries, and machinery under the surface (both the frameworks and yours!)
Шаг 03: Hello World в Chameleon
Большинство веб-систем обладают языком шаблонов, для генерации HTML. Это дает UX-человеку возможность сконцентрироваться на вещи, которую они знают (разметка) и вкраплениями в коде, а не наоборот.
Pyramid doesn’t have too much of an opinion on templating languages. This tutorial does though. We’re Chameleon/ZPT folks. Так давайте же сделаем “hello world”, используя шаблон страницы.
Цели
- Самый простой возможный шаг, чтобы понять про шаблон
Техническое задание
- Передвинуть представление(views) в отдельный модуль
- Поменять application.py, чтобы найти модуль, для объявления представлений
- Продемонстрировать свежесть рендеринга и ориентированных на данные представлений, особенно для тестирования
- Привести тесты к виду ориентированных на данные
Шаги
Вспомнить что в разделе установки сказано сделать
$ export PYRAMID_RELOAD_TEMPLATES=1
, что позволяет вам редактировать шаблоны и не иметь необходимостью перезагружать ваше Pyramid-приложение.$ cd ../../creatingux; mkdir step03; cd step03
Копировать нижеследующее в
step03/application.py
:from wsgiref.simple_server import make_serverКопировать следующее в
from pyramid.config import Configurator
def main():
config = Configurator()
config.scan("views")
app = config.make_wsgi_app()
return app
if __name__ == '__main__':
app = main()
server = make_server('0.0.0.0', 8080, app)
server.serve_forever()
step03/views.py
:from pyramid.view import view_configИ далее, уже разметку HTML-шаблона в
@view_config(renderer="hello.pt")
def hello_view(request):
return {"tutorial": "Little Dummy"}
step03/hello.pt
:<html>И вот это туда —
<head>
<title>Hello</title>
</head>
<body>
<p>Hello, ${tutorial}</p>
</body>
</html>
step03/tests.py
:import unittestИ последнее, пишем:
class ProjectorViewsUnitTests(unittest.TestCase):
def test_hello_view(self):
from views import hello_view
result = hello_view({})
self.assertEqual(result['tutorial'], 'Little Dummy')
class ProjectorFunctionalTests(unittest.TestCase):
def setUp(self):
from application import main
app = main()
from webtest import TestApp
self.testapp = TestApp(app)
def test_it(self):
res = self.testapp.get('/', status=200)
self.failUnless('Hello' in res.body)
$ nosetests
Вслед за чем должны увидеть:
..
----------------------------------------------------------------
Ran 2 tests in 0.885s
OK
Пробуем запустить:
$ python application.py
И открываем
127.0.0.1:8080
в своем браузере.Дополнительные вопросы
Если вы редактируете тему, необходимо ли вам делать перезапуск приложения, чтобы увидеть изменения?
Какие другие значения возможны для рендерера, на @view_config?
Анализ
Этот шаг дает представление о разборе кода. Есть несколько различных путей чтобы сделать конфигурацию в Pyramid: императивный (который мы видели в первом шаге: Hello World в Pyramid), сканирующий (близкий ко многим современным веб-фреймворкам), и наш старый друг ZCML. The choice is mainly one of style, though there are some sharp edges in some cases.
Note the coolness… все что вам следует делать это вернуть словарь в ваше представление, и ваш шаблон вызывается on the way out the door, с этими данными.
Тезисы
История конфигурирования в Zope2, Zope3, BFG, потом Pyramid
How things worked before renderers
Следом идет часть 4.