PK *H·Bç e¬xh xh webtest-2.0.1/index.html
author: | Ian Bicking <ianb@colorstudy.com> |
---|---|
maintainer: | Gael Pasgrimaud <gael@gawel.org> |
WebTest is an extraction of paste.fixture.TestApp, rewriting portions to use WebOb. It is under active development as part of the Pylons cloud of packages.
Feedback and discussion should take place on the Pylons discuss list, and bugs should go into the Github tracker.
This library is licensed under an MIT-style license.
You can use pip or easy_install to get the latest stable release:
$ pip install WebTest
$ easy_install WebTest
Or if you want the development version:
$ pip install https://nodeload.github.com/Pylons/webtest/tar.gz/master
WebTest helps you test your WSGI-based web applications. This can be any application that has a WSGI interface, including an application written in a framework that supports WSGI (which includes most actively developed Python web frameworks – almost anything that even nominally supports WSGI should be testable).
With this you can test your web applications without starting an HTTP server, and without poking into the web framework shortcutting pieces of your application that need to be tested. The tests WebTest runs are entirely equivalent to how a WSGI HTTP server would call an application. By testing the full stack of your application, the WebTest testing model is sometimes called a functional test, integration test, or acceptance test (though the latter two are not particularly good descriptions). This is in contrast to a unit test which tests a particular piece of functionality in your application. While complex programming tasks are often is suited to unit tests, template logic and simple web programming is often best done with functional tests; and regardless of the presence of unit tests, no testing strategy is complete without high-level tests to ensure the entire programming system works together.
WebTest helps you create tests by providing a convenient interface to run WSGI applications and verify the output.
The most important object in WebTest is TestApp, the wrapper for WSGI applications. To use it, you simply instantiate it with your WSGI application. (Note: if your WSGI application requires any configuration, you must set that up manually in your tests.)
The main class it TestApp which wrap your WSGI application and allow you to perform HTTP request on it.
Here is a basic application:
>>> def application(environ, start_response):
... headers = [('Content-Type', 'text/html; charset=utf8'),
... ('Content-Length', str(len(body)))]
... start_response('200 Ok', headers)
... return [body]
Wrap it into a TestApp:
>>> from webtest import TestApp
>>> app = TestApp(application)
Then you can get the response of a HTTP GET:
>>> resp = app.get('/')
And check the result. Like like reponse’s status:
>>> assert resp.status == '200 Ok'
>>> assert resp.status_int == 200
Response’s headers:
>>> assert resp.content_type == 'text/html'
>>> assert resp.content_length > 0
Or response’s body:
>>> resp.mustcontain('<html>')
>>> assert 'form' in resp
WebTest can do much more. In particular it can handle Form handling and json.
Copyright (c) 2010 Ian Bicking and Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
webtest.debugapp.debug_app is a faker WSGI app to help to test webtest.
Examples of use :
>>> import webtest
>>> from webtest.debugapp import debug_app
>>> app = webtest.TestApp(debug_app)
>>> res = app.post('/', params='foobar')
>>> print(res.body)
CONTENT_LENGTH: 6
CONTENT_TYPE: application/x-www-form-urlencoded
HTTP_HOST: localhost:80
...
wsgi.url_scheme: 'http'
wsgi.version: (1, 0)
-- Body ----------
foobar
Here, you can see, foobar in body when you pass foobar in app.post params argument.
You can also define the status of response :
>>> res = app.post('/?status=302', params='foobar')
>>> print(res.status)
302 Found
To make a request, use:
app.get('/path', [params], [headers], [extra_environ], ...)
This call to get() does a request for /path, with any params, extra headers or WSGI environment keys that you indicate. This returns a TestResponse object, based on webob.response.Response. It has some additional methods to make it easier to test.
If you want to do a POST request, use:
app.post('/path', {'vars': 'values'}, [headers], [extra_environ],
[upload_files], ...)
Specifically the second argument of post() is the body of the request. You can pass in a dictionary (or dictionary-like object), or a string body (dictionary objects are turned into HTML form submissions).
You can also pass in the keyword argument upload_files, which is a list of [(fieldname, filename, field_content)]. File uploads use a different form submission data type to pass the structured data.
You can use put() and delete() for PUT and DELETE requests.
Webtest provide some facilities to test json apis.
The *_json methods will transform data to json before POST/PUT and add the correct Content-Type for you.
Also Response have an attribute .json to allow you to retrieve json contents as a python dict.
Doing POST request with webtest.TestApp.post_json():
>>> resp = app.post_json('/resource/', dict(id=1, value='value'))
>>> print(resp.request)
POST /resource/ HTTP/1.0
Content-Length: 27
Content-Type: application/json
...
>>> resp.json == {'id': 1, 'value': 'value'}
True
Doing GET request with webtest.TestApp.get() and using webtest.response.json:
To just parse body of the response, use Response.json:
>>> resp = app.get('/resource/1/')
>>> print(resp.request)
GET /resource/1/ HTTP/1.0
...
>>> resp.json == {'id': 1, 'value': 'value'}
True
The best way to simulate authentication is if your application looks in environ['REMOTE_USER'] to see if someone is authenticated. Then you can simply set that value, like:
app.get('/secret', extra_environ=dict(REMOTE_USER='bob'))
If you want all your requests to have this key, do:
app = TestApp(my_app, extra_environ=dict(REMOTE_USER='bob'))
You can use WebTest to test an application on a real web server. Just pass an url to the TestApp instead of a WSGI application:
app = TestApp('http://my.cool.websi.te')
You can also use the WEBTEST_TARGET_URL env var to switch from a WSGI application to a real server without having to modify your code:
os.environ['WEBTEST_TARGET_URL'] = 'http://my.cool.websi.te'
app = TestApp(wsgiapp) # will use the WEBTEST_TARGET_URL instead of the wsgiapp
By default the proxy will use httplib but you can use other backends by adding an anchor to your url:
app = TestApp('http://my.cool.websi.te#urllib3')
app = TestApp('http://my.cool.websi.te#requests')
app = TestApp('http://my.cool.websi.te#restkit')
A key concept behind WebTest is that there’s lots of things you shouldn’t have to check everytime you do a request. It is assumed that the response will either be a 2xx or 3xx response; if it isn’t an exception will be raised (you can override this for a request, of course). The WSGI application is tested for WSGI compliance with a slightly modified version of wsgiref.validate (modified to support arguments to InputWrapper.readline) automatically. Also it checks that nothing is printed to the environ['wsgi.errors'] error stream, which typically indicates a problem (one that would be non-fatal in a production situation, but if you are testing is something you should avoid).
To indicate another status is expected, use the keyword argument status=404 to (for example) check that it is a 404 status, or status="*" to allow any status.
If you expect errors to be printed, use expect_errors=True.