| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- Testing Applications with Paste
- +++++++++++++++++++++++++++++++
- :author: Ian Bicking <ianb@colorstudy.com>
- :revision: $Rev$
- :date: $LastChangedDate$
- .. contents::
- Introduction
- ============
- Paste includes functionality for testing your application in a
- convenient manner. These facilities are quite young, and feedback is
- invited. Feedback and discussion should take place on the
- `Paste-users list
- <http://groups.google.com/group/paste-users>`_.
- These facilities let you test your Paste and WSGI-based applications
- easily and without a server.
- .. include:: include/contact.txt
- The Tests Themselves
- ====================
- The ``app`` object is a wrapper around your application, with many
- methods to make testing convenient. Here's an example test script::
- def test_myapp():
- res = app.get('/view', params={'id': 10})
- # We just got /view?id=10
- res.mustcontain('Item 10')
- res = app.post('/view', params={'id': 10, 'name': 'New item
- name'})
- # The app does POST-and-redirect...
- res = res.follow()
- assert res.request.url == '/view?id=10'
- res.mustcontain('New item name')
- res.mustcontain('Item updated')
- The methods of the ``app`` object (a ``paste.tests.fixture.TestApp``
- object):
- ``get(url, params={}, headers={}, status=None)``:
- Gets the URL. URLs are based in the root of your application; no
- domains are allowed. Parameters can be given as a dictionary, or
- included directly in the ``url``. Headers can also be added.
- This tests that the status is a ``200 OK`` or a redirect header,
- unless you pass in a ``status``. A status of ``"*"`` will never
- fail; or you can assert a specific status (like ``500``).
- Also, if any errors are written to the error stream this will
- raise an error.
- ``post(url, params={}, headers={}, status=None, upload_files=())``:
- POSTS to the URL. Like GET, except also allows for uploading
- files. The uploaded files are a list of ``(field_name, filename,
- file_content)``.
- If you don't want to do a urlencoded post body, you can put a
- ``content-type`` header in your header, and pass the body in as a
- string with ``params``.
- The response object:
- ``header(header_name, [default])``:
- Returns the named header. It's an error if there is more than one
- matching header. If you don't provide a default, it is an error
- if there is no matching header.
- ``all_headers(header_name):``
- Returns a list of all matching headers.
- ``follow(**kw)``:
- Follows the redirect, returning the new response. It is an error
- if this response wasn't a redirect. Any keyword arguments are
- passed to ``app.get`` (e.g., ``status``).
- ``x in res``:
- Returns True if the string is found in the response. Whitespace
- is normalized for this test.
- ``mustcontain(*strings)``:
- Raises an error if any of the strings are not found in the
- response.
- ``showbrowser()``:
- Opens the HTML response in a browser; useful for debugging.
- ``str(res)``:
- Gives a slightly-compacted version of the response.
- ``click(description=None, linkid=None, href=None, anchor=None, index=None, verbose=False)``:
- Clicks the described link (`see docstring for more
- <./class-paste.fixture.TestResponse.html#click>`_)
- ``forms``:
- Return a dictionary of forms; you can use both indexes (refer to
- the forms in order) or the string ids of forms (if you've given
- them ids) to identify the form. See `Form Submissions <#form-submissions>`_ for
- more on the form objects.
- Request objects:
- ``url``:
- The url requested.
- ``environ``:
- The environment used for the request.
- ``full_url``:
- The url with query string.
- Form Submissions
- ================
- You can fill out and submit forms from your tests. First you get the
- form::
- res = testapp.get('/entry_form')
- form = res.forms[0]
- Then you fill it in fields::
- # when there's one unambiguous name field:
- form['name'] = 'Bob'
- # Enter something into the first field named 'age'
- form.set('age', '45', index=1)
- Finally you submit::
- # Submit with no particular submit button pressed:
- form.submit()
- # Or submit a button:
- form.submit('submit_button_name')
- Framework Hooks
- ===============
- Frameworks can detect that they are in a testing environment by the
- presence (and truth) of the WSGI environmental variable
- ``"paste.testing"``.
- More generally, frameworks can detect that something (possibly a test
- fixture) is ready to catch unexpected errors by the presence and truth
- of ``"paste.throw_errors"`` (this is sometimes set outside of testing
- fixtures too, when an error-handling middleware is in place).
- Frameworks that want to expose the inner structure of the request may
- use ``"paste.testing_variables"``. This will be a dictionary -- any
- values put into that dictionary will become attributes of the response
- object. So if you do ``env["paste.testing_variables"]['template'] =
- template_name`` in your framework, then ``response.template`` will be
- ``template_name``.
|