py.test examples for Grok ========================= In typical Zope/Grok development we have three kinds of tests: - unit-tests - integration-tests - funktional-tests With the help of py.test we can create and run all of these tests in an easy way for Grok. In this tutorial we will demonstrate the usage of zope.pytest with this three kinds of tests. Buildout -------- Let's start by extending the default ``buildout.cfg`` generated by `grokproject` to use zope.pytest. To find all relevant packages of pytest we have to add http://pypi.testrun.org/simple/py/ to the find_links. Then we can add a new section called ``pytest``. Don't forget to add it to the global parts too! Here is the pytest section:: [pytest] recipe = z3c.recipe.scripts eggs = example pytest arguments = ['src/example'] + sys.argv[1:] Please notice that ``example`` is the name of the package generated by `grokproject`. After running ``bin/buildout`` we should have a new executable called ``bin/py.test`` which can search for tests in the directory ``src/example``. Unit Tests ---------- To run unit tests with `pytest` we have to create a file with the prefix ``test_``. So, let's create a file ``test_unit.py`` with the following content: .. code-block:: python class TestClass: def test_one(self): x = "this" assert 'h' in x def test_two(self): x = "servus" assert x == "hello" Now we can run this test with ``bin/py.test``. We should get one failing test:: ==================================== FAILURES ===================================== _______________________________ TestClass.test_two ________________________________ self = def test_two(self): x = "servus" > assert x == "hello" E assert 'servus' == 'hello' E - servus E + hello src/pytt/tests/test_unit.py:9: AssertionError ======================= 1 failed, 3 passed in 1.14 seconds ======================== Integration Tests ----------------- For integration tests we need a bit more setup. To be more precise we have to load the Zope Component Architecture before respective tests are actually run. To run the integration test we need a bit of code that registers something in the Zope Component Architecture. Take a look at this example in ``app.py``: .. code-block:: python import grok class Example(grok.Application, grok.Container): pass class Index(grok.View): def render(self): return "Hello World" Now we have some code to test. We have to create another module which contains our test and whose name is prefixed with ``test_``. This time we name it ``test_integration.py``: .. code-block:: python import example import pytest from zope import component from example.app import Example from zope.publisher.browser import TestRequest from zope.pytest import create_app, configure def pytest_funcarg__app(request): return create_app(request, Example()) def pytest_funcarg__config(request): return configure(request, pytt, 'ftesting.zcml') def test_integration(app, config): zope_req = TestRequest() view = component.getMultiAdapter( (Example(), zope_req), name=u"index") assert "Hello World" in view() The interesting bits are the two ``pytest_funcarg__`` functions: - ``pytest_funcarg__app`` This function creates a test ZODB with our `Example` application in the ZODB root. - ``pytest_funcarg__config`` This function sets up the Zope Component Registry which groks in this case the contents of our app.py. Now you can run ``bin/py.test`` again and will see that pytest will discover and execute this ``test_integration`` module. Functional Tests ---------------- We take again the example in the app.py file for demonstrating the functional tests with zope.pytest in grok. Functional tests showing the perspective of a user. This means we test here with a kind of a browser. We take for this infrae.testbrowser. We have to include it in our setup.py install_requires. Again we creat a module called test_functional.py. .. code-block:: python import example import pytest from example.app import Example from zope.pytest import create_app, configure from infrae.testbrowser.browser import Browser def pytest_funcarg__app(request): return create_app(request, Example()) def pytest_funcarg__config(request): return configure(request, pytt, 'ftesting.zcml') def test_with_infrae_testbrowser(config, app): browser = Browser(app) browser.options.handle_errors = False browser.open('http://localhost/test') assert browser.status == '200 Ok' We use again the pytest_funcarg functions to setup a ZODB and the Zope Component Architecture. In our test function we create an instance of Browser with our app as argument. Now we can open our Index site in the browser and check for example the HTTP Response Status. You can run now again bin/py.test and look on the running test.