Guide: Pyramid for People - Part 3
Part 2: concept, installation and simple hello world application
Of course, testing helps ensure future quality and facilitates refactoring. And this, of course, makes development faster, especially when using smart editors and IDEs . Restarting your application and clicking in your browser is a drag.
This step uses the same code as the first step, but we will add some tests.
Create a directory in the right place.
Copy the following into the newly created file
Copy the following into
After that, we should see the following result:
Unit tests are difficult. Unit tests with the framework are even more complicated. The Pyramid culture, however, aims to be fully covered by tests, and Pyramid works very hard to make writing tests a useful activity.
Even if you do not do full test coverage, you will find that most basic unit tests catch standard errors faster than opening your browser to check for code changes every time. This is a bit like installing your editor, or IDE, to run pylint which lets you know before saving (much less before executing) if you have any errors.
Functional tests are easier to write, and for UX people, they help in the part of the problem under consideration.
Most web systems have a template language for generating HTML. This gives the UX-man the opportunity to concentrate on the thing that they know (markup) and interspersed in the code, and not vice versa.
Pyramid doesn't have too much of an opinion on templating languages. This tutorial does though. We're Chameleon / ZPT folks. So let's make “hello world” using the page template.
Recall that the installation section tells you to do this
Copy the following to
After what we should see: Try to run: And open in your browser.
If you are editing a theme, do you need to restart the application to see the changes?
What other values are possible for the renderer on @view_config?
This step provides insight into code parsing. There are several different ways to make configuration in Pyramid: imperative (which we saw in the first step: Hello World in Pyramid), crawling (close to many modern web frameworks), and our old friend ZCML. The choice is mainly one of style, though there are some sharp edges in some cases.
Note the coolness ... all you have to do is return the dictionary to your view, and your template is called on the way out the door, with this data.
History of configuration in Zope2, Zope3, BFG, then Pyramid
How things worked before renderers
Next comes part 4 .
Step 02: Unit and Functional Testing
Of course, testing helps ensure future quality and facilitates refactoring. And this, of course, makes development faster, especially when using smart editors and IDEs . Restarting your application and clicking in your browser is a drag.
This step uses the same code as the first step, but we will add some tests.
Goals
- Coat code with unit tests
- Create functional tests for answers
Technical requirements
- Write a pyramid-style unit test
- Use WebTest to include a functional test in the test module
- Use nose and nosetests viewer to run tests
Steps
$ cd ../../creatingux; mkdir step02; cd step02
Create a directory in the right place.
Copy the following into the newly created file
step02/application.py
:from wsgiref.simple_server import make_serverThis is the same code that we saw in step one.
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 ()
Copy the following into
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
After that, we should see the following result:
..
--------------------------------------------------------
Ran 2 tests in 0.301s
OK
Additional questions
- How does nose know what tests are in tests.py?
- Does WebTest start a real HTTP server to send an HTTP request?
- If your code throws an error, does Pyramid handle it correctly?
Analysis
Unit tests are difficult. Unit tests with the framework are even more complicated. The Pyramid culture, however, aims to be fully covered by tests, and Pyramid works very hard to make writing tests a useful activity.
Even if you do not do full test coverage, you will find that most basic unit tests catch standard errors faster than opening your browser to check for code changes every time. This is a bit like installing your editor, or IDE, to run pylint which lets you know before saving (much less before executing) if you have any errors.
Functional tests are easier to write, and for UX people, they help in the part of the problem under consideration.
Abstracts
- Pyramid (and repoze.bfg before it) and fidelity to test coverage
- Unit testing philosophy against functional tests, against dock tests
- The challenge in setup / teardown regarding configuration, registries, and machinery under the surface (both the frameworks and yours!)
Step 03: Hello World in Chameleon
Most web systems have a template language for generating HTML. This gives the UX-man the opportunity to concentrate on the thing that they know (markup) and interspersed in the code, and not vice versa.
Pyramid doesn't have too much of an opinion on templating languages. This tutorial does though. We're Chameleon / ZPT folks. So let's make “hello world” using the page template.
Goals
- The easiest possible step to understand about the template.
Technical task
- Move a view to a separate module
- Change application.py to find the module to declare views
- Demonstrate the freshness of rendering and data-oriented views, especially for testing
- Bring tests to data-oriented
Steps
Recall that the installation section tells you to do this
$ export PYRAMID_RELOAD_TEMPLATES=1
, which allows you to edit templates and not have to restart your Pyramid application. $ cd ../../creatingux; mkdir step03; cd step03
Copy the following to
step03/application.py
:from wsgiref.simple_server import make_serverCopy the following to
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_configAnd further, the markup of the HTML template is already in
@view_config (renderer = "hello.pt")
def hello_view (request):
return {"tutorial": "Little Dummy"}
step03/hello.pt
:And here it is -
</strong>Hello<strong> Hello, $ {tutorial}
step03/tests.py
:import unittestAnd finally, we write:
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
After what we should see: Try to run: And open in your browser.
..
----------------------------------------------------------------
Ran 2 tests in 0.885s
OK
$ python application.py
127.0.0.1:8080
Additional questions
If you are editing a theme, do you need to restart the application to see the changes?
What other values are possible for the renderer on @view_config?
Analysis
This step provides insight into code parsing. There are several different ways to make configuration in Pyramid: imperative (which we saw in the first step: Hello World in Pyramid), crawling (close to many modern web frameworks), and our old friend ZCML. The choice is mainly one of style, though there are some sharp edges in some cases.
Note the coolness ... all you have to do is return the dictionary to your view, and your template is called on the way out the door, with this data.
Abstracts
History of configuration in Zope2, Zope3, BFG, then Pyramid
How things worked before renderers
Next comes part 4 .