### Install WebTest using easy_install
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/index.html
Use easy_install to install the latest stable release of WebTest.
```bash
$ easy_install WebTest
```
--------------------------------
### Install WebTest using pip
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/index.html
Use pip to install the latest stable release of WebTest.
```bash
$ pip install WebTest
```
--------------------------------
### Install WebTest using pip or easy_install
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_sources/index.rst.txt
Use pip or easy_install to install the latest stable release of WebTest.
```sh
$ pip install WebTest
$ easy_install WebTest
```
--------------------------------
### Install and Run tox for Multi-Version Testing
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_sources/contributing.rst.txt
Install tox and use it to run tests across multiple Python versions. Ensure you have the required Python interpreters installed and available in your PATH.
```bash
$ pip install tox
$ tox
```
```bash
$ bin/tox
```
--------------------------------
### Install WebTest development version
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_sources/index.rst.txt
Install the development version of WebTest directly from its GitHub repository.
```sh
$ pip install https://nodeload.github.com/Pylons/webtest/tar.gz/main
```
--------------------------------
### Initialize WebTest Debug App
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_sources/forms.rst.txt
Setup a test application instance for form testing.
```python
>>> from webtest.debugapp import make_debug_app
>>> from webtest.app import TestApp
>>> app = make_debug_app({},
... form='docs/form.html',
... show_form=True)
>>> app = TestApp(app)
```
--------------------------------
### Initialize TestApp with WSGI application
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_sources/testapp.rst.txt
Setup a TestApp instance using a sample WSGI application that handles various content types.
```python
import json
import sys
from webtest.app import TestApp
from webob import Request
from webob import Response
def application(environ, start_response):
req = Request(environ)
if req.path_info.endswith('.html'):
content_type = 'text/html'
body = '
hey!
'.encode('latin-1')
elif req.path_info.endswith('.xml'):
content_type = 'text/xml'
body = 'hey!'.encode('latin-1')
elif req.path_info.endswith('.json'):
content_type = 'application/json'
body = json.dumps({"a": 1, "b": 2}).encode('latin-1')
elif '/resource/' in req.path_info:
content_type = 'application/json'
body = json.dumps(dict(id=1, value='value')).encode('latin-1')
resp = Response(body, content_type=content_type)
return resp(environ, start_response)
app = TestApp(application)
```
--------------------------------
### Perform GET Request
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/app.html
Executes a GET request with optional parameters, headers, and environment overrides.
```python
def get(self, url, params=None, headers=None, extra_environ=None,
status=None, expect_errors=False, xhr=False):
"""
Do a GET request given the url path.
:param params:
A query string, or a dictionary that will be encoded
into a query string. You may also include a URL query
string on the ``url``.
:param headers:
Extra headers to send.
:type headers:
dictionary
:param extra_environ:
Environmental variables that should be added to the request.
:type extra_environ:
dictionary
:param status:
The HTTP status code you expect in response (if not 200 or 3xx).
You can also use a wildcard, like ``'3*'`` or ``'*'``.
:type status:
integer or string
:param expect_errors:
If this is False, then if anything is written to
environ ``wsgi.errors`` it will be an error.
If it is True, then non-200/3xx responses are also okay.
:type expect_errors:
boolean
:param xhr:
```
--------------------------------
### Generate Documentation with Sphinx
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_sources/contributing.rst.txt
Install Sphinx and generate HTML documentation for the project. Navigate to the docs directory and use make html or sphinx-build.
```bash
$ pip install Sphinx
$ cd docs
$ make html
```
```bash
../bin/sphinx-build -b html -d _build/doctrees . _build/html
```
--------------------------------
### Find a Free Port
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/http.html
Use this function to get an available IP address and port for binding a socket. It's useful for dynamically starting servers without port conflicts.
```python
import socket
import os
def get_free_port():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 0))
ip, port = s.getsockname()
s.close()
ip = os.environ.get('WEBTEST_SERVER_BIND', '127.0.0.1')
return ip, port
```
--------------------------------
### GET /path
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/testapp.html
Performs a GET request to the specified path with optional parameters, headers, and environment variables.
```APIDOC
## GET /path
### Description
Performs a GET request to the specified path. Returns a TestResponse object.
### Method
GET
### Endpoint
/path
### Parameters
#### Query Parameters
- **params** (dict) - Optional - Query parameters for the request
- **headers** (dict) - Optional - HTTP headers
- **extra_environ** (dict) - Optional - WSGI environment keys
### Response
#### Success Response (200)
- **TestResponse** (object) - A response object based on webob.response.Response
```
--------------------------------
### Make HTTP requests
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_sources/testapp.rst.txt
Perform GET and POST requests using the TestApp instance.
```python
app.get('/path', [params], [headers], [extra_environ], ...)
```
```python
app.post('/path', {'vars': 'values'}, [headers], [extra_environ],
[upload_files], ...)
```
--------------------------------
### Perform OPTIONS and HEAD Requests
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/app.html
Methods for executing OPTIONS and HEAD requests, mirroring the behavior of the standard GET method.
```python
def options(self, url, headers=None, extra_environ=None,
status=None, expect_errors=False, xhr=False):
"""
Do a OPTIONS request. Similar to :meth:`~webtest.TestApp.get`.
:returns: :class:`webtest.TestResponse` instance.
"""
if xhr:
headers = self._add_xhr_header(headers)
return self._gen_request('OPTIONS', url, headers=headers,
extra_environ=extra_environ, status=status,
upload_files=None,
expect_errors=expect_errors)
```
```python
def head(self, url, params=None, headers=None, extra_environ=None,
status=None, expect_errors=False, xhr=False):
"""
Do a HEAD request. Similar to :meth:`~webtest.TestApp.get`.
:returns: :class:`webtest.TestResponse` instance.
"""
if params:
url = utils.build_params(url, params)
if xhr:
headers = self._add_xhr_header(headers)
return self._gen_request('HEAD', url, headers=headers,
extra_environ=extra_environ, status=status,
upload_files=None,
expect_errors=expect_errors)
```
--------------------------------
### Perform GET request and check response status
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_sources/index.rst.txt
Make an HTTP GET request to the root path ('/') of the wrapped application and assert the response status code and string.
```python
resp = app.get('/')
assert resp.status == '200 OK'
assert resp.status_int == 200
```
--------------------------------
### GET Request Method
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/api.html
Performs a GET request.
```APIDOC
## GET Request
### `get(url, params=None, headers=None, extra_environ=None, status=None, expect_errors=False, xhr=False)`
#### Description
Do a GET request given the url path.
#### Parameters
- **url** (string) - Required - The URL path for the request.
- **params** (string or dict) - Optional - A query string, or a dictionary that will be encoded into a query string. You may also include a URL query string on the `url`.
- **headers** (dict) - Optional - Extra headers to send.
- **extra_environ** (dict) - Optional - Environmental variables to add to the request.
- **status** (integer or string) - Optional - The expected HTTP status code (if not 200 or 3xx). You can also use a wildcard, like `'3*'` or `'*'`.
- **expect_errors** (boolean) - Optional - If this is False, then if anything is written to environ `wsgi.errors` it will be an error. If it is True, then non-200/3xx responses are also okay.
- **xhr** (boolean) - Optional - If this is true, then marks response as ajax. The same as headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }.
#### Returns
`webtest.TestResponse` instance.
```
--------------------------------
### Perform a GET Request
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/api.html
Performs a GET request to the specified URL. Supports query parameters, custom headers, and environment variables.
```python
resp = app.get('/users', params={'limit': 10}, headers={'X-Custom': 'value'})
```
--------------------------------
### Perform an OPTIONS Request
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/api.html
Performs an OPTIONS request to the specified URL. Similar to the get() method.
```python
resp = app.options('/users')
```
--------------------------------
### Test Across Python Versions with Tox
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/contributing.html
Install and execute tests across multiple Python versions using tox.
```bash
$ pip install tox
$ tox
```
```bash
$ bin/tox
py26: commands succeeded
py27: commands succeeded
py32: commands succeeded
py33: commands succeeded
```
--------------------------------
### GET / (Generic Response Inspection)
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_sources/testresponse.rst.txt
Retrieves a response object from the application and demonstrates how to inspect its status, headers, and body content.
```APIDOC
## GET /
### Description
Retrieves a response from the application. The returned object provides attributes for inspecting status, headers, and body content.
### Method
GET
### Endpoint
/
### Response
#### Success Response (200)
- **status** (string) - The text status of the response (e.g., "200 OK").
- **status_int** (integer) - The integer status code (e.g., 200).
- **headers** (dict) - A dictionary-like object of response headers.
- **body** (string) - The raw text body of the response.
- **text** (string) - The unicode text body of the response.
#### Response Example
{
"status": "200 OK",
"status_int": 200,
"body": "hey!
"
}
```
--------------------------------
### Perform HTTP GET request
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/index.html
Make an HTTP GET request to the root path of the wrapped WSGI application using TestApp.
```python
resp = app.get('/')
```
--------------------------------
### Execute a Request with TestApp
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/api.html
Executes a pre-constructed webob Request object. Useful for more complex request setups.
```python
req = webtest.TestRequest.blank('url', ...args...)
resp = app.do_request(req)
```
--------------------------------
### Define a basic WSGI application
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_sources/index.rst.txt
A simple WSGI application that returns a predefined HTML body. This is used as an example to be wrapped by WebTest's TestApp.
```python
def application(environ, start_response):
headers = [('Content-Type', 'text/html; charset=utf8'),
('Content-Length', str(len(body)))]
start_response('200 OK', headers)
return [body]
```
--------------------------------
### Perform a HEAD Request
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/api.html
Performs a HEAD request to the specified URL. Similar to the get() method.
```python
resp = app.head('/users')
```
--------------------------------
### Internal Request Handling Logic
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/app.html
Internal implementation details for request processing, including environment setup and header management.
```python
environ = self._make_environ(extra_environ)
url = str(url)
url = self._remove_fragment(url)
if params:
url = utils.build_params(url, params)
if '?' in url:
url, environ['QUERY_STRING'] = url.split('?', 1)
else:
environ['QUERY_STRING'] = ''
req = self.RequestClass.blank(url, environ)
if xhr:
headers = self._add_xhr_header(headers)
if headers:
req.headers.update(headers)
return self.do_request(req, status=status,
expect_errors=expect_errors)
```
--------------------------------
### GET Authorization
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/api.html
Retrieves the HTTP_AUTHORIZATION environment key value.
```APIDOC
## GET Authorization
### `get_authorization()`
#### Description
Allow to set the HTTP_AUTHORIZATION environ key. Value should look like one of the following:
* `('Basic', ('user', 'password'))`
* `('Bearer', 'mytoken')`
* `('JWT', 'myjwt')`
If value is None the the HTTP_AUTHORIZATION is removed.
```
--------------------------------
### Navigate to URL
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/response.html
Navigates to a given URL, ignoring scheme, host, and fragment. It joins the provided href with the current request URL to resolve relative paths. Supports 'get' or 'post' methods and passes additional arguments to the underlying request method.
```python
scheme, host, path, query, fragment = urlparse.urlsplit(href)
```
```python
scheme = host = fragment = ''
href = urlparse.urlunsplit((scheme, host, path, query, fragment))
```
```python
href = urlparse.urljoin(self.request.url, href)
```
```python
method = method.lower()
assert method in ('get', 'post'), (
```
--------------------------------
### Getting Parsed XML with lxml
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/testresponse.html
Use `response.lxml` to get the response body parsed by the `lxml` library, enabling XPath queries. This requires `lxml` to be installed. An `AttributeError` is raised if the content-type is incorrect.
```python
>>> res = app.get('/index.html')
>>> res.lxml
>>> res.lxml.xpath('//body/div')[0].text
'hey!'
>>> res = app.get('/document.xml')
>>> res.lxml
>>> res.lxml[0].tag
'message'
>>> res.lxml[0].text
'hey!'
```
--------------------------------
### Clone and Set Up webtest Project
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_sources/contributing.rst.txt
Clone the webtest repository and set up a virtual environment for development. This is the initial step for contributing to the project.
```bash
$ git clone https://github.com/Pylons/webtest.git
$ cd webtest
$ virtualenv .
$ . bin/activate
$ python setup.py dev
```
--------------------------------
### Initialize TestApp with different backends
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_sources/testapp.rst.txt
Demonstrates how to instantiate TestApp using specific request backends.
```python
app = TestApp('http://my.cool.websi.te#requests')
```
```python
app = TestApp('http://my.cool.websi.te#restkit')
```
--------------------------------
### Initialize and use debug_app
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/debugapp.html
Demonstrates how to wrap the debug_app with TestApp and inspect the request environment.
```python
>>> 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
```
--------------------------------
### Initialize Upload object
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/forms.html
Demonstrates creating an Upload instance for file submission.
```python
>>> Upload('filename.txt', 'data', 'application/octet-stream')
>>> Upload('filename.txt', 'data')
>>> Upload("README.txt")
```
--------------------------------
### Generate Documentation with Sphinx
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/contributing.html
Build the project documentation using Sphinx.
```bash
$ pip install Sphinx
$ cd docs
$ make html
../bin/sphinx-build -b html -d _build/doctrees . _build/html
Running Sphinx v1.1.3
loading pickled environment... done
...
build succeeded, 3 warnings.
Build finished. The HTML pages are in _build/html.
```
--------------------------------
### goto
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/response.html
Navigates to a specified URL using a defined HTTP method.
```APIDOC
## goto
### Description
Navigates to the provided relative or absolute URL using GET or POST methods.
### Parameters
#### Query Parameters
- **href** (string) - Required - The target URL to navigate to.
- **method** (string) - Optional - The HTTP method to use ('get' or 'post'). Defaults to 'get'.
```
--------------------------------
### Instantiate TestApp
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/api.html
Wraps a WSGI application for testing. Supports extra environment variables, relative paths, and cookie handling.
```python
app = webtest.TestApp(my_wsgi_app, extra_environ={'REMOTE_ADDR': '127.0.0.1'})
```
--------------------------------
### Request Methods API
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/app.html
Provides methods for performing HTTP requests such as GET.
```APIDOC
## GET /
### Description
Performs a GET request to the specified URL.
### Method
GET
### Endpoint
/
### Parameters
#### Query Parameters
- **url** (string) - Required - The URL path to request.
- **params** (object or string) - Optional - Query string parameters or a dictionary to be encoded into a query string.
- **headers** (object) - Optional - Extra headers to send with the request.
- **extra_environ** (object) - Optional - Environmental variables to add to the request.
- **status** (integer or string) - Optional - The expected HTTP status code (e.g., 200, '3*', '*').
- **expect_errors** (boolean) - Optional - If False, errors written to wsgi.errors will cause an exception. If True, non-200/3xx responses are also considered okay.
- **xhr** (boolean) - Optional - Indicates if the request is an XMLHttpRequest.
### Response
#### Success Response (200)
- **body** (string) - The response body.
- **status_code** (integer) - The HTTP status code of the response.
- **headers** (object) - The response headers.
#### Response Example
```json
{
"body": "Hello World",
"status_code": 200,
"headers": {
"Content-Type": "text/html"
}
}
```
```
--------------------------------
### Environment Configuration
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/app.html
Creates a WSGI environment dictionary with default settings and optional overrides.
```python
def _make_environ(self, extra_environ=None):
environ = self.extra_environ.copy()
environ['paste.throw_errors'] = True
if extra_environ:
environ.update(extra_environ)
return environ
```
--------------------------------
### Initialize TestApp
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/app.html
Initialize TestApp to wrap a WSGI application for testing. It can accept a WSGI application, a Paste Deploy URI, or a full URL for proxying. Configuration options include extra environment variables, relative path for file uploads, and cookie handling.
```python
def __init__(self, app, extra_environ=None, relative_to=None,
use_unicode=True, cookiejar=None, parser_features=None,
json_encoder=None, lint=True):
if 'WEBTEST_TARGET_URL' in os.environ:
app = os.environ['WEBTEST_TARGET_URL']
if isinstance(app, str):
if app.startswith('http'):
try:
from wsgiproxy import HostProxy
except ImportError:
raise ImportError(
'Using webtest with a real url requires WSGIProxy2. '
'Please install it with: '
'pip install WSGIProxy2')
if '#' not in app:
app += '#httplib'
url, client = app.split('#', 1)
app = HostProxy(url, client=client)
else:
from paste.deploy import loadapp
app = loadapp(app, relative_to=relative_to)
self.app = app
```
--------------------------------
### Perform a DELETE Request
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/api.html
Performs a DELETE request to the specified URL. Similar to the get() method.
```python
resp = app.delete('/users/1')
```
--------------------------------
### TestApp Initialization
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/api.html
Initializes the TestApp class, wrapping a WSGI application for testing purposes.
```APIDOC
## `webtest.app.TestApp`
### Description
Wraps a WSGI application in a more convenient interface for testing. It uses extended versions of `webob.BaseRequest` and `webob.Response`.
### Parameters
#### Path Parameters
- **app** (WSGI application) - Required - May be a WSGI application or Paste Deploy app, like `'config:filename.ini#test'`. It can also be an actual full URL to an http server and webtest will proxy requests with WSGIProxy2.
- **extra_environ** (dict) - Optional - A dictionary of values that should go into the environment for each request. These can provide a communication channel with the application.
- **relative_to** (string) - Optional - A directory used for file uploads are calculated relative to this. Also `config:` URIs that aren't absolute.
- **cookiejar** (CookieJar instance) - Optional - `cookielib.CookieJar` alike API that keeps cookies across requests.
- **parser_features** (string or list) - Optional - Passed to BeautifulSoup when parsing responses.
- **json_encoder** (A subclass of json.JSONEncoder) - Optional - Passed to json.dumps when encoding json.
- **lint** (boolean) - Optional - If True (default) then check that the application is WSGI compliant.
```
--------------------------------
### Handle File Upload Fields
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/forms.html
Use the `Upload` class to prepare files for upload. You can specify the filename, data, and content type.
```python
>>> from webtest import Upload
>>> form['file'] = Upload('README.rst')
```
```python
>>> form['file'] = Upload('README.rst', b'data')
```
```python
>>> form['file'] = Upload('README.rst', b'data', 'text/x-rst')
```
--------------------------------
### Access XML response body
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/response.html
Parses the response body as an ElementTree object. Requires ElementTree to be installed.
```python
from xml.etree import ElementTree
except ImportError: # pragma: no cover
try:
import ElementTree
except ImportError:
try:
from elementtree import ElementTree # NOQA
except ImportError:
raise ImportError(
"You must have ElementTree installed "
"(or use Python 2.5) to use response.xml")
# ElementTree can't parse unicode => use `body` instead of `testbody`
return ElementTree.XML(self.body)
```
--------------------------------
### Simulate authentication
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_sources/testapp.rst.txt
Configure authentication headers or environment variables for requests.
```python
app.get('/secret', extra_environ=dict(REMOTE_USER='bob'))
```
```python
app = TestApp(my_app, extra_environ=dict(REMOTE_USER='bob'))
```
```python
app = TestApp(my_app)
app.authorization = ('Basic', ('user', 'password'))
```
```python
app = TestApp(my_app)
app.authorization = ('Bearer', 'mytoken')
# or
app.authorization = ('JWT', 'myjwt')
```
--------------------------------
### Accessing Response as XML
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/response.html
Provides the response body parsed as an ElementTree XML object. Requires ElementTree to be installed.
```APIDOC
## GET /response/xml
### Description
Returns the response body parsed as an ElementTree XML object.
### Method
GET
### Endpoint
/response/xml
### Parameters
None
### Request Example
None
### Response
#### Success Response (200)
- **xml_object** (ElementTree.Element) - The parsed XML object.
#### Response Example
```xml
value
```
```
--------------------------------
### Handle Multiple File Uploads
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/forms.html
For file input fields that accept multiple files, provide a list of `Upload` objects.
```python
>>> from webtest import Upload
>>> form['files'] = [
... Upload('README.rst'),
... Upload('LICENSE.rst'),
... ]
```
--------------------------------
### Create and Execute a Request
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/app.html
Use this method to create and execute a request. You can pass an instantiated TestRequest object or a URL with keyword arguments for TestRequest.blank. This is useful for testing custom methods like MKCOL or PUT with a body.
```python
def request(self, url_or_req, status=None, expect_errors=False,
**req_params):
"""
Creates and executes a request. You may either pass in an
instantiated :class:`TestRequest` object, or you may pass in a
URL and keyword arguments to be passed to
:meth:`TestRequest.blank`.
You can use this to run a request without the intermediary
functioning of :meth:`TestApp.get` etc. For instance, to
test a WebDAV method::
resp = app.request('/new-col', method='MKCOL')
Note that the request won't have a body unless you specify it, like::
resp = app.request('/test.txt', method='PUT', body='test')
You can use :class:`webtest.TestRequest`::
req = webtest.TestRequest.blank('/url/', method='GET')
resp = app.do_request(req)
"""
if isinstance(url_or_req, str):
url_or_req = str(url_or_req)
for (k, v) in req_params.items():
if isinstance(v, str):
req_params[k] = str(v)
if isinstance(url_or_req, str):
req = self.RequestClass.blank(url_or_req, **req_params)
else:
req = url_or_req.copy()
for name, value in req_params.items():
setattr(req, name, value)
req.environ['paste.throw_errors'] = True
for name, value in self.extra_environ.items():
req.environ.setdefault(name, value)
return self.do_request(req,
status=status,
expect_errors=expect_errors,
)
```
--------------------------------
### Manage HTTP Authorization
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/app.html
Methods to get and set the HTTP_AUTHORIZATION environment variable using Basic, Bearer, or JWT schemes.
```python
def get_authorization(self):
"""Allow to set the HTTP_AUTHORIZATION environ key. Value should look
like one of the following:
* ``('Basic', ('user', 'password'))``
* ``('Bearer', 'mytoken')``
* ``('JWT', 'myjwt')``
If value is None the the HTTP_AUTHORIZATION is removed
"""
return self.authorization_value
def set_authorization(self, value):
self.authorization_value = value
if value is not None:
invalid_value = (
"You should use a value like ('Basic', ('user', 'password'))"
" OR ('Bearer', 'token') OR ('JWT', 'token')"
)
if isinstance(value, (list, tuple)) and len(value) == 2:
authtype, val = value
if authtype == 'Basic' and val and \
isinstance(val, (list, tuple)):
val = ':'.join(list(val))
val = b64encode(to_bytes(val)).strip()
val = val.decode('latin1')
elif authtype in ('Bearer', 'JWT') and val and \
isinstance(val, (str, str)):
val = val.strip()
else:
raise ValueError(invalid_value)
value = str(f'{authtype} {val}')
else:
raise ValueError(invalid_value)
self.extra_environ.update({
'HTTP_AUTHORIZATION': value,
})
else:
if 'HTTP_AUTHORIZATION' in self.extra_environ:
del self.extra_environ['HTTP_AUTHORIZATION']
authorization = property(get_authorization, set_authorization)
```
--------------------------------
### Handle Simple Select Fields
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/forms.html
Manage single-selection dropdowns. You can get the current value and set a new option by its value.
```python
>>> print(form['select'].value)
option2
```
```python
>>> form['select'] = 'option1'
```
--------------------------------
### Initialize Form Parser
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/forms.html
Instantiate the Form class with a webob.response.TestResponse and the HTML text of the form. The parser_features argument defaults to 'html.parser'.
```python
form = Form(response, text)
```
--------------------------------
### POST /
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/app.html
Performs a POST request to the specified URL with optional parameters, file uploads, and headers.
```APIDOC
## POST /
### Description
Performs a POST request to the specified URL. Supports sending parameters in the body, file uploads, and custom content types.
### Method
POST
### Parameters
#### Query Parameters
- **url** (string) - Required - The target URL path.
- **params** (string/dict) - Optional - Data to be sent in the request body.
- **headers** (dict) - Optional - Custom HTTP headers.
- **upload_files** (list) - Optional - List of (fieldname, filename, file_content) tuples.
- **content_type** (string) - Optional - The HTTP content type (e.g., application/json).
- **xhr** (boolean) - Optional - If true, adds X-REQUESTED-WITH: XMLHttpRequest header.
### Response
#### Success Response (200)
- **TestResponse** (object) - Returns a webtest.TestResponse instance.
```
--------------------------------
### Get a Single Form
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/forms.html
Access the single HTML form on a page using the `.form` attribute. This is suitable when only one form is present.
```python
>>> res = app.get('/form.html')
>>> form = res.form
```
--------------------------------
### Select Options by Text
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/forms.html
Use `.select()` for single selects and `.select_multiple()` for multiple selects to choose options based on their visible text rather than their value attribute.
```python
>>> form['select'].select(text="Option 2")
>>> print(form['select'].value)
option2
```
```python
>>> form['multiple'].select_multiple(texts=["Option 1", "Option 2"])
>>> print(form['multiple'].value)
['option1', 'option2']
```
--------------------------------
### Get a Form by Index or ID
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/forms.html
When multiple forms exist, access them using the `.forms` property by their index or the form's ID attribute.
```python
>>> form = res.forms[0]
```
```python
>>> form = res.forms['myform']
```
--------------------------------
### Accessing Response as PyQuery Object
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/response.html
Returns the response as a PyQuery object, which is useful for querying HTML and XML content. Requires PyQuery to be installed.
```APIDOC
## GET /response/pyquery
### Description
Returns the response body as a PyQuery object. This is only applicable for HTML and XML content types.
### Method
GET
### Endpoint
/response/pyquery
### Parameters
None
### Request Example
None
### Response
#### Success Response (200)
- **pyquery_object** (PyQuery) - The parsed PyQuery object.
#### Response Example
```html
Hello
```
```
--------------------------------
### Get File Upload Fields
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/forms.html
Returns a list of file field tuples, each containing the field name and file name, optionally with file contents.
```python
uploads = []
for name, fields in self.fields.items():
for field in fields:
if isinstance(field, File) and field.value:
```
--------------------------------
### Configuration API
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/app.html
APIs for configuring the testing environment, such as parser features and resetting state.
```APIDOC
## PUT /parser-features
### Description
Changes the parser used by BeautifulSoup for response processing.
### Method
PUT
### Endpoint
/parser-features
### Parameters
#### Request Body
- **parser_features** (string) - Required - The name of the parser to use (e.g., 'html.parser').
### Request Example
```json
{
"parser_features": "lxml"
}
```
### Response
#### Success Response (200)
- **message** (string) - Confirmation message.
#### Response Example
```json
{
"message": "Parser features set successfully."
}
```
## POST /reset
### Description
Resets the state of the application, primarily clearing saved cookies.
### Method
POST
### Endpoint
/reset
### Response
#### Success Response (200)
- **message** (string) - Confirmation message.
#### Response Example
```json
{
"message": "State reset successfully."
}
```
```
--------------------------------
### Handle Multiple Select Fields
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/forms.html
Manage multi-selection dropdowns. You can get the current selection as a list and set new options by providing a list of values.
```python
>>> print(form['multiple'].value)
['option2', 'option3']
```
```python
>>> form['multiple'] = ['option1']
```
--------------------------------
### Initialize TestResponse
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/response.html
The TestResponse class is instantiated by TestApp methods and extends webob.Response. It includes properties for request, forms, and parser features.
```python
import re
from json import loads
from webtest import forms
from webtest import utils
from webtest.compat import print_stderr
from webtest.compat import urlparse
from webtest.compat import to_bytes
from bs4 import BeautifulSoup
import webob
class TestResponse(webob.Response):
"""
Instances of this class are returned by
:class:`~webtest.app.TestApp` methods.
"""
request = None
_forms_indexed = None
parser_features = 'html.parser'
@property
def forms(
self
):
"""
Returns a dictionary containing all the forms in the pages as
:class:`~webtest.forms.Form` objects. Indexes are both in
order (from zero) and by form id (if the form is given an id).
See :doc:`forms` for more info on form objects.
"""
if self._forms_indexed is None:
self._parse_forms()
return self._forms_indexed
@property
def form(
self
):
"""
If there is only one form on the page, return it as a
:class:`~webtest.forms.Form` object; raise a TypeError is
there are no form or multiple forms.
"""
forms_ = self.forms
if not forms_:
raise TypeError(
"You used response.form, but no forms exist"
)
if 1 in forms_:
# There is more than one form
raise TypeError(
"You used response.form, but more than one form exists"
)
return forms_[0]
@property
def testbody(
self
):
self.decode_content()
if self.charset:
try:
return self.text
except UnicodeDecodeError:
return self.body.decode(self.charset, 'replace')
return self.body.decode('ascii', 'replace')
_tag_re = re.compile(r'<(/?)([:a-z0-9_\-]*)(.*?)>', re.S | re.I)
def _parse_forms(
self
):
forms_ = self._forms_indexed = {}
form_texts = [str(f) for f in self.html('form')]
for i, text in enumerate(form_texts):
form = forms.Form(self, text, self.parser_features)
forms_[i] = form
if form.id:
forms_[form.id] = form
def _follow(
self,
**kw
):
location = self.headers['location']
abslocation = urlparse.urljoin(self.request.url, location)
# @@: We should test that it's not a remote redirect
return self.test_app.get(abslocation, **kw)
def follow(
self,
**kw
):
"""
If this response is a redirect, follow that redirect. It is an
error if it is not a redirect response. Any keyword
arguments are passed to :class:`~webtest.app.TestApp.get`. Returns
another :class:`TestResponse` object.
"""
if not (300 <= self.status_int < 400):
raise AssertionError(
"You can only follow redirect responses (not %s)" % self.status
)
return self._follow(**kw)
def maybe_follow(
self,
**kw
):
"""
Follow all redirects. If this response is not a redirect, do nothing.
Any keyword arguments are passed to :class:`webtest.app.TestApp.get`.
Returns another :class:`TestResponse` object.
"""
remaining_redirects = 100 # infinite loops protection
response = self
while 300 <= response.status_int < 400 and remaining_redirects:
response = response._follow(**kw)
remaining_redirects -= 1
if remaining_redirects <= 0:
raise AssertionError("redirects chain looks infinite")
return response
def click(
self,
description=None,
linkid=None,
href=None,
index=None,
verbose=False,
extra_environ=None
):
"""
Click the link as described. Each of ``description``,
``linkid``, and ``url`` are *patterns*, meaning that they are
either strings (regular expressions), compiled regular
expressions (objects with a ``search`` method), or callables
returning true or false.
All the given patterns are ANDed together:
* ``description`` is a pattern that matches the contents of the
anchor (HTML and all -- everything between ```` and
````)
* ``linkid`` is a pattern that matches the ``id`` attribute of
the anchor. It will receive the empty string if no id is
given.
* ``href`` is a pattern that matches the ``href`` of the anchor;
the literal content of that attribute, not the fully qualified
attribute.
If more than one link matches, then the ``index`` link is
followed. If ``index`` is not given and more than one link
matches, or if no link matches, then ``IndexError`` will be
raised.
If you give ``verbose`` then messages will be printed about
each link, and why it does or doesn't match. If you use
```
--------------------------------
### Define a Test Application
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_sources/testresponse.rst.txt
Defines a simple WSGI application that serves different content types based on the request path, used for testing with TestApp.
```python
>>> import json
>>> import sys
>>> from webob import Request
>>> from webob import Response
>>> from webtest.app import TestApp
>>> def application(environ, start_response):
... req = Request(environ)
... if req.path_info.endswith('.html'):
... content_type = 'text/html'
... body = 'hey!
'.encode('latin-1')
... elif req.path_info.endswith('.xml'):
... content_type = 'text/xml'
... body = 'hey!'.encode('latin-1')
... elif req.path_info.endswith('.json'):
... content_type = 'application/json'
... body = json.dumps({"a": 1, "b": 2}).encode('latin-1')
... resp = Response(body, content_type=content_type)
... return resp(environ, start_response)
>>> app = TestApp(application)
```
--------------------------------
### Get Form Field Object
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/forms.html
Retrieves a specific form field object by name. Raises an AssertionError if the field is not found or if multiple fields match the name.
```python
fields = self.fields.get(name)
assert fields is not None, (
"No field by the name %r found" % name)
assert len(fields) == 1, (
"Multiple fields match %r: %s"
% (name, ', '.join(map(repr, fields))))
return fields[0]
```
--------------------------------
### Accessing Response as lxml Object
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/response.html
Returns the response as an lxml object. This method is suitable for HTML and XML content types and requires the lxml library to be installed.
```APIDOC
## GET /response/lxml
### Description
Returns the response body parsed as an lxml object. This is applicable for HTML and XML content types.
### Method
GET
### Endpoint
/response/lxml
### Parameters
None
### Request Example
None
### Response
#### Success Response (200)
- **lxml_object** (lxml.etree._Element or lxml.html.HtmlElement) - The parsed lxml object.
#### Response Example
```html
Title
```
```
--------------------------------
### OPTIONS /url
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/app.html
Performs an OPTIONS request to the specified URL.
```APIDOC
## OPTIONS /url
### Description
Performs an OPTIONS request to the specified URL.
### Method
OPTIONS
### Endpoint
/url
### Parameters
#### Query Parameters
- **url** (string) - Required - The target URL.
- **headers** (dict) - Optional - Request headers.
- **extra_environ** (dict) - Optional - Extra environment variables.
- **status** (int/str) - Optional - Expected status code.
- **expect_errors** (bool) - Optional - Whether to expect errors.
- **xhr** (bool) - Optional - Whether to add XHR headers.
### Response
#### Success Response (200)
- **response** (TestResponse) - Returns a TestResponse instance.
```
--------------------------------
### Get and Set Form Field Values
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/forms.html
Retrieve the current value of a form field or set a new value. For fields with non-unique names, use `.set()` with an index.
```python
>>> print(form['text'].value)
Foo
```
```python
>>> form['text'] = 'Bar'
```
```python
>>> # When names don't point to a single field:
>>> form.set('text', 'Bar', index=0)
```
--------------------------------
### Execute Tests with Pytest
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/contributing.html
Run the test suite using the local pytest binary.
```bash
$ bin/pytest
Doctest: forms.rst ... ok
Doctest: index.rst ... ok
...
test_url_class (tests.test_testing.TestTesting) ... ok
tests.test_testing.test_print_unicode ... °C
ok
Name Stmts Miss Cover Missing
------------------------------------------------
webtest 18 0 100%
webtest.app 603 92 85% 48, 61-62, 94, 98, 212-221, 264-265, 268-272, 347, 379-386, 422, 426-428, 432-434, 455, 463, 471, 473, 488, 496-497, 515, 520-527, 548, 553-554, 558-559, 577, 592, 597-598, 618, 624, 661-664, 742, 808, 872, 940-941, 945-948, 961-964, 975, 982, 995, 1000, 1006, 1010, 1049, 1051, 1095-1096, 1118-1119, 1122-1127, 1135-1136, 1148, 1155-1160, 1175
webtest.compat 50 11 78% 28-34, 55-56, 61-62
webtest.debugapp 58 0 100%
webtest.ext 80 0 100%
webtest.forms 324 23 93% 23, 49, 58, 61, 92, 116, 177, 205, 411, 478, 482-486, 491-493, 522, 538, 558-561
webtest.http 78 0 100%
webtest.lint 215 45 79% 135, 176, 214-216, 219-224, 227-231, 234, 243-244, 247, 250-251, 254, 263-264, 270, 274, 307, 311, 335, 359, 407, 424-427, 441-444, 476-479, 493, 508
webtest.sel 479 318 34% 38-39, 45-46, 64-78, 88-108, 120, 126, 151-153, 156-158, 164-165, 168-191, 194-201, 219-231, 236, 240, 243-259, 263-297, 301-306, 316-326, 331-336, 340, 344, 347-352, 357-359, 364, 392-394, 397-404, 408, 412-417, 421, 425-426, 430, 434, 438, 442, 445, 448-457, 470-480, 483-485, 488, 492, 495, 503, 506, 515-516, 520, 524, 528, 533, 538, 542-544, 547, 560-565, 576, 579, 582, 593-596, 599-602, 605-606, 617-620, 623-642, 668-677, 680-688, 715, 720, 732, 735, 744-754, 757-762, 770-779, 791, 794, 805-809, 813-826, 838-842
webtest.utils 99 11 89% 19-20, 23, 26, 32, 38, 100, 109, 152-154
------------------------------------------------
TOTAL 2004 500 75%
----------------------------------------------------------------------
Ran 70 tests in 14.940s
```
--------------------------------
### Get Form Field Object with Default
Source: https://docs.pylonsproject.org/projects/webtest/en/latest/_modules/webtest/forms.html
Retrieves a form field object by name and optional index. Returns a default value if the field is not found, otherwise raises an AssertionError.
```python
fields = self.fields.get(name)
if fields is None:
if default is utils.NoDefault:
raise AssertionError(
"No fields found matching %r (and no default given)"
% name)
return default
if index is None:
return self[name]
return fields[index]
```