### Install zest.releaser
Source: https://github.com/pylons/webtest/blob/main/RELEASING.rst
Install the recommended version of zest.releaser via pip.
```bash
$ pip install zest.releaser[recommanded]
```
--------------------------------
### Install WebTest
Source: https://github.com/pylons/webtest/blob/main/docs/index.md
Commands to install the stable or development versions of WebTest.
```sh
$ pip install WebTest
$ easy_install WebTest
```
```sh
$ pip install https://nodeload.github.com/Pylons/webtest/tar.gz/main
```
--------------------------------
### Initialize WebTest App
Source: https://github.com/pylons/webtest/blob/main/docs/forms.md
Setup the test application with a debug form.
```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)
```
--------------------------------
### Making GET Requests with TestApp
Source: https://github.com/pylons/webtest/blob/main/docs/testapp.md
Demonstrates how to make a GET request to a specified path using the TestApp. The method returns a TestResponse object for further assertions.
```python
app.get('/path', [params], [headers], [extra_environ], ...)
```
--------------------------------
### TestApp.get() - Make GET Requests
Source: https://context7.com/pylons/webtest/llms.txt
Performs HTTP GET requests with optional query parameters, headers, and environment variables. Returns a TestResponse object.
```APIDOC
## TestApp.get() - Make GET Requests
### Description
Performs HTTP GET requests with optional query parameters, headers, and environment variables. Returns a `TestResponse` object.
### Method
`app.get(url, params=None, headers=None, extra_environ=None, status=None, expect_errors=False, xhr=False)`
### Parameters
#### Path Parameters
None
#### Query Parameters
- **params** (dict or OrderedDict) - Optional - Dictionary of query parameters.
- **headers** (dict) - Optional - Dictionary of custom headers.
- **extra_environ** (dict) - Optional - Dictionary of extra WSGI environment variables.
- **status** (int, str, or None) - Optional - Expected status code(s). Can be an integer, a string like '4*', or '*' for any status.
- **expect_errors** (bool) - Optional - If True, exceptions are not raised for non-2xx/3xx status codes.
- **xhr** (bool) - Optional - If True, sets the X-Requested-With header to 'XMLHttpRequest'.
#### Request Body
None
### Request Example
```python
from webtest import TestApp
# Assuming my_wsgi_app and app are defined as in the TestApp example
# Simple GET request
response = app.get('/')
assert response.status == '200 OK'
assert response.status_int == 200
# GET with query parameters
response = app.get('/search', params={'q': 'python', 'page': 1})
# GET with custom headers
response = app.get('/api/data', headers={'Accept': 'application/json'})
# GET with extra environment variables
response = app.get('/protected', extra_environ={'REMOTE_USER': 'admin'})
# Expect specific status code
response = app.get('/not-found', status=404)
# Accept any status code
response = app.get('/might-fail', status='*')
# Accept any 4xx status
response = app.get('/client-error', status='4*')
# AJAX request
response = app.get('/api/data', xhr=True)
```
### Response
#### Success Response (200)
`TestResponse` object containing the response details.
#### Response Example
```json
{
"example": "TestResponse object"
}
```
```
--------------------------------
### Perform HTTP GET Request
Source: https://github.com/pylons/webtest/blob/main/docs/index.md
Executes a GET request against the wrapped application.
```default
>>> resp = app.get('/')
```
--------------------------------
### Make GET Requests with TestApp
Source: https://context7.com/pylons/webtest/llms.txt
Perform HTTP GET requests using TestApp. Supports query parameters, custom headers, environment variables, and specific status code expectations.
```python
from webtest import TestApp
app = TestApp(my_wsgi_app)
# Simple GET request
response = app.get('/')
assert response.status == '200 OK'
assert response.status_int == 200
# GET with query parameters
response = app.get('/search', params={'q': 'python', 'page': 1})
# GET with custom headers
response = app.get('/api/data', headers={'Accept': 'application/json'})
# GET with extra environment variables
response = app.get('/protected', extra_environ={'REMOTE_USER': 'admin'})
# Expect specific status code
response = app.get('/not-found', status=404)
# Accept any status code
response = app.get('/might-fail', status='*')
# Accept any 4xx status
response = app.get('/client-error', status='4*')
# AJAX request
response = app.get('/api/data', xhr=True)
```
--------------------------------
### Get HTML lxml Objects with resp.lxml
Source: https://github.com/pylons/webtest/blob/main/docs/changelog.rst
Users with `lxml` installed can now obtain HTML lxml objects directly from `resp.lxml`. This requires `lxml` version 2.0 or later and provides a convenient way to parse and manipulate HTML responses.
```python
html_doc = resp.lxml
```
--------------------------------
### TestApp.put(), patch(), delete(), options(), head() - Other HTTP Methods
Source: https://context7.com/pylons/webtest/llms.txt
Perform PUT, PATCH, DELETE, OPTIONS, and HEAD requests using TestApp. These methods are analogous to GET and POST for different HTTP verbs.
```python
from webtest import TestApp
app = TestApp(my_wsgi_app)
# PUT request
response = app.put('/api/resource/1', params={'field': 'value'})
# PATCH request with partial update
response = app.patch('/api/resource/1', params={'status': 'active'})
# DELETE request
response = app.delete('/api/resource/1')
# OPTIONS request (useful for CORS preflight)
response = app.options('/api/resource')
print(response.headers.get('Allow')) # GET, POST, PUT, DELETE
# HEAD request (gets headers only)
response = app.head('/api/resource')
print(response.content_length)
```
--------------------------------
### Parse Response as HTML with BeautifulSoup
Source: https://github.com/pylons/webtest/blob/main/docs/testresponse.md
Access the response body as a BeautifulSoup object. Requires BeautifulSoup to be installed.
```python
>>> res = app.get('/index.html')
>>> res.html
hey!
>>> res.html.__class__
```
--------------------------------
### TestResponse.html - Parse HTML with BeautifulSoup
Source: https://context7.com/pylons/webtest/llms.txt
Access the response body as a BeautifulSoup object for HTML parsing and DOM traversal. Requires BeautifulSoup to be installed.
```python
from webtest import TestApp
app = TestApp(my_wsgi_app)
response = app.get('/page.html')
# Get BeautifulSoup object
soup = response.html
print(soup) # ...
```
--------------------------------
### Parse Response with PyQuery
Source: https://github.com/pylons/webtest/blob/main/docs/testresponse.md
Access the response body using PyQuery for CSS-style selectors. Requires PyQuery to be installed.
```python
>>> res.pyquery('message')
[]
>>> res.pyquery('message').text()
'hey!'
```
--------------------------------
### Retrieving JSON Response Body
Source: https://github.com/pylons/webtest/blob/main/docs/testapp.md
Demonstrates how to retrieve and parse the JSON body of a GET request response using the `.json` attribute of the TestResponse object.
```python
resp = app.get('/resource/1/')
print(resp.request)
resp.json == {'id': 1, 'value': 'value'}
```
--------------------------------
### Parse Response with lxml
Source: https://github.com/pylons/webtest/blob/main/docs/testresponse.md
Access the response body using the lxml library for powerful XML parsing and XPath queries. Requires lxml to be installed.
```python
>>> res = app.get('/index.html')
>>> res.lxml
>>> res.lxml.xpath('//body/div')[0].text
'hey!'
```
```python
>>> res = app.get('/document.xml')
>>> res.lxml
>>> res.lxml[0].tag
'message'
>>> res.lxml[0].text
'hey!'
```
--------------------------------
### Parse HTML/XML with lxml
Source: https://context7.com/pylons/webtest/llms.txt
Access the response body as an lxml object for XPath queries and advanced XML processing. Requires the lxml library to be installed.
```python
from webtest import TestApp
app = TestApp(my_wsgi_app)
# HTML response with lxml
response = app.get('/page.html')
doc = response.lxml
# XPath queries
titles = doc.xpath('//h1/text()')
links = doc.xpath('//a/@href')
content = doc.xpath('//div[@id="content"]')[0].text
# XML response
response = app.get('/data.xml')
xml = response.lxml
print(xml.tag) # Root element tag
messages = xml.xpath('//message/text()')
```
--------------------------------
### Form - Getting Forms from Response
Source: https://context7.com/pylons/webtest/llms.txt
Access HTML forms from the response for filling and submission. Forms can be accessed by index or id.
```APIDOC
## Form - Getting Forms from Response
Access HTML forms from the response for filling and submission. Forms can be accessed by index or id.
```python
from webtest import TestApp
app = TestApp(my_wsgi_app)
response = app.get('/register')
# Get the only form on the page
form = response.form
# Get form by index (0-based)
form = response.forms[0]
# Get form by id
form = response.forms['registration-form']
# Access all forms
for i, form in response.forms.items():
print(f"Form {i}: action={form.action}, method={form.method}")
# Form attributes
print(form.id) # 'registration-form'
print(form.action) # '/api/register'
print(form.method) # 'POST'
print(form.enctype) # 'multipart/form-data'
```
```
--------------------------------
### Initialize TestApp with a sample application
Source: https://github.com/pylons/webtest/blob/main/docs/testresponse.md
Sets up a basic WSGI application and wraps it in a TestApp instance for testing.
```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)
```
--------------------------------
### Generate HTML Documentation
Source: https://github.com/pylons/webtest/blob/main/docs/contributing.md
Navigate to the docs directory and generate HTML documentation using make. The output will be in the _build/html directory.
```bash
$ cd docs
$ make html
```
--------------------------------
### Configure zest.releaser
Source: https://github.com/pylons/webtest/blob/main/RELEASING.rst
Add these settings to your ~/.pypirc file to automate release configuration.
```ini
[zest.releaser]
no-input = true
create-wheel = yes
```
--------------------------------
### Execute fullrelease
Source: https://github.com/pylons/webtest/blob/main/RELEASING.rst
Run the fullrelease script to initiate the release process.
```bash
$ fullrelease
```
--------------------------------
### Initialize TestApp
Source: https://github.com/pylons/webtest/blob/main/docs/index.md
Wraps a WSGI application instance with TestApp to enable testing capabilities.
```default
>>> from webtest import TestApp
>>> app = TestApp(application)
```
--------------------------------
### Making POST Requests with TestApp
Source: https://github.com/pylons/webtest/blob/main/docs/testapp.md
Illustrates how to perform a POST request with a dictionary or string body, optional headers, environment variables, and file uploads.
```python
app.post('/path', {'vars': 'values'}, [headers], [extra_environ],
[upload_files], ...)
```
--------------------------------
### Clone and Sync Webtest Repository
Source: https://github.com/pylons/webtest/blob/main/docs/contributing.md
Clone the webtest repository and synchronize dependencies using uv.
```bash
$ git clone https://github.com/Pylons/webtest.git
$ cd webtest
$ uv sync
```
--------------------------------
### Specifying HTTP Client Backend
Source: https://github.com/pylons/webtest/blob/main/docs/testapp.md
Demonstrates how to specify an alternative HTTP client backend (e.g., urllib3, requests, restkit) for proxying requests by appending an anchor to the target URL.
```default
app = TestApp('http://my.cool.websi.te#urllib3')
```
```default
app = TestApp('http://my.cool.websi.te#requests')
```
```default
app = TestApp('http://my.cool.websi.te#restkit')
```
--------------------------------
### Testing Non-WSGI Applications with a URL
Source: https://github.com/pylons/webtest/blob/main/docs/testapp.md
Illustrates how to test an application running on a real web server by passing its URL to the TestApp constructor. This can be configured using the `WEBTEST_TARGET_URL` environment variable.
```default
app = TestApp('http://my.cool.websi.te')
```
```default
os.environ['WEBTEST_TARGET_URL'] = 'http://my.cool.websi.te'
app = TestApp(wsgiapp) # will use the WEBTEST_TARGET_URL instead of the wsgiapp
```
--------------------------------
### Simulating Authentication with REMOTE_USER
Source: https://github.com/pylons/webtest/blob/main/docs/testapp.md
Explains how to simulate user authentication by setting the `REMOTE_USER` environment variable for individual requests or for the entire TestApp instance.
```python
app.get('/secret', extra_environ=dict(REMOTE_USER='bob'))
```
```python
app = TestApp(my_app, extra_environ=dict(REMOTE_USER='bob'))
```
--------------------------------
### Define a WSGI Application
Source: https://github.com/pylons/webtest/blob/main/docs/testapp.md
Defines a sample WSGI application that responds to different file extensions and paths with specific content types and bodies.
```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)
```
--------------------------------
### Create TestApp Wrapper
Source: https://context7.com/pylons/webtest/llms.txt
Wrap a WSGI application with TestApp for testing. Supports custom environment variables, cookie jars, and testing remote servers.
```python
from webtest import TestApp
# Basic WSGI application
def my_wsgi_app(environ, start_response):
status = '200 OK'
headers = [('Content-Type', 'text/html')]
start_response(status, headers)
return [b'
Hello World
']
# Wrap the application
app = TestApp(my_wsgi_app)
# With custom environment variables
app = TestApp(my_wsgi_app, extra_environ={'REMOTE_USER': 'testuser'})
# With custom cookie jar
from http.cookiejar import CookieJar
app = TestApp(my_wsgi_app, cookiejar=CookieJar())
# Test a remote server (requires WSGIProxy2)
app = TestApp('http://localhost:8080')
```
--------------------------------
### Process Release Text
Source: https://github.com/pylons/webtest/blob/main/RELEASING.rst
Command line utility to strip indentation and replace version placeholders in the release notes.
```bash
cat RELEASING.rst | sed 's/3.0.x/version/' | sed 's/ //'
```
--------------------------------
### TestApp - Create Test Application Wrapper
Source: https://context7.com/pylons/webtest/llms.txt
The TestApp class wraps a WSGI application to provide a convenient testing interface. It handles cookies automatically, validates WSGI compliance, and provides methods for all HTTP verbs.
```APIDOC
## TestApp - Create Test Application Wrapper
### Description
The `TestApp` class wraps a WSGI application to provide a convenient testing interface. It handles cookies automatically, validates WSGI compliance, and provides methods for all HTTP verbs.
### Method
`TestApp(wsgi_app, extra_environ=None, cookiejar=None, ...) `
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Request Example
```python
from webtest import TestApp
# Basic WSGI application
def my_wsgi_app(environ, start_response):
status = '200 OK'
headers = [('Content-Type', 'text/html')]
start_response(status, headers)
return [b'
Hello World
']
# Wrap the application
app = TestApp(my_wsgi_app)
# With custom environment variables
app = TestApp(my_wsgi_app, extra_environ={'REMOTE_USER': 'testuser'})
# With custom cookie jar
from http.cookiejar import CookieJar
app = TestApp(my_wsgi_app, cookiejar=CookieJar())
# Test a remote server (requires WSGIProxy2)
app = TestApp('http://localhost:8080')
```
### Response
#### Success Response (200)
`TestApp` object wrapping the WSGI application.
#### Response Example
```json
{
"example": "TestApp object"
}
```
```
--------------------------------
### TestApp.post() - Make POST Requests
Source: https://context7.com/pylons/webtest/llms.txt
Performs HTTP POST requests with form data, JSON, or file uploads. Supports various content types and multipart encoding.
```APIDOC
## TestApp.post() - Make POST Requests
### Description
Performs HTTP POST requests with form data, JSON, or file uploads. Supports various content types and multipart encoding.
### Method
`app.post(url, params='', headers=None, extra_environ=None, content_type=None, upload_files=None, expect_errors=False, ...)`
### Parameters
#### Path Parameters
None
#### Query Parameters
- **params** (dict, OrderedDict, str, or list of tuples) - Optional - Data to send in the request body. Can be form parameters, raw data, or file upload specifications.
- **headers** (dict) - Optional - Dictionary of custom headers.
- **extra_environ** (dict) - Optional - Dictionary of extra WSGI environment variables.
- **content_type** (str) - Optional - The Content-Type header for the request. If not provided and `params` is a dict, it defaults to 'application/x-www-form-urlencoded'. If `upload_files` is used, it defaults to 'multipart/form-data'.
- **upload_files** (list of tuples) - Optional - List of files to upload. Each tuple can be `(field_name, filename, file_content, content_type)` or `(field_name, path_to_file)`.
- **expect_errors** (bool) - Optional - If True, exceptions are not raised for non-2xx/3xx status codes.
### Request Example
```python
from webtest import TestApp, Upload
from collections import OrderedDict
# Assuming my_wsgi_app and app are defined as in the TestApp example
# POST with form data (dictionary)
response = app.post('/login', params={'username': 'john', 'password': 'secret'})
# POST with form data (string)
response = app.post('/api/raw', params='raw data body')
# POST with file upload
response = app.post('/upload', upload_files=[
('document', 'report.pdf', b'PDF content here', 'application/pdf')
])
# File upload with filename only (reads from disk)
response = app.post('/upload', upload_files=[('document', 'path/to/file.pdf')])
# Using Upload helper for file fields
response = app.post('/upload', params=OrderedDict([
('title', 'My Document'),
('file', Upload('filename.txt', b'file contents', 'text/plain'))
]))
# POST with custom content type
response = app.post('/api/xml', params='value',
content_type='application/xml')
# Expect errors allowed
response = app.post('/validate', params={'data': 'invalid'}, expect_errors=True)
```
### Response
#### Success Response (200)
`TestResponse` object containing the response details.
#### Response Example
```json
{
"example": "TestResponse object"
}
```
```
--------------------------------
### Test Across Multiple Python Versions with Tox
Source: https://github.com/pylons/webtest/blob/main/docs/contributing.md
Use tox with uvx to test the project across various Python versions. Ensure Python 3.9, 3.10, 3.11, and 3.12 are available in your PATH.
```bash
$ uvx --with tox-uv tox
```
--------------------------------
### Setting HTTP Authorization Header
Source: https://github.com/pylons/webtest/blob/main/docs/testapp.md
Shows how to set the `HTTP_AUTHORIZATION` header for requests by assigning a tuple to the `.authorization` property of the TestApp instance.
```python
app = TestApp(my_app)
app.authorization = ('Basic', ('user', 'password'))
```
```python
app = TestApp(my_app)
app.authorization = ('Bearer', 'mytoken')
```
```python
app = TestApp(my_app)
app.authorization = ('JWT', 'myjwt')
```
--------------------------------
### Authentication Configuration
Source: https://context7.com/pylons/webtest/llms.txt
Configures HTTP authentication schemes for TestApp requests.
```APIDOC
## [SET_AUTH] [TestApp.authorization]
### Description
Configures authentication for all requests. Supports Basic, Bearer, and JWT schemes.
### Request Example
app.authorization = ('Basic', ('username', 'password'))
app.authorization = ('Bearer', 'token_string')
app.authorization = ('JWT', 'token_string')
```
--------------------------------
### Handle Test Failures with AppError
Source: https://context7.com/pylons/webtest/llms.txt
Shows how to catch application errors and configure expected status codes to prevent test failures.
```python
from webtest import TestApp, AppError
app = TestApp(my_wsgi_app)
# Catch unexpected status codes
try:
response = app.get('/nonexistent')
except AppError as e:
print(f"Request failed: {e}")
# Bad response: 404 Not Found (not 200 OK or 3xx redirect for ...)
# Expect specific status to avoid error
response = app.get('/nonexistent', status=404)
# Expect any status
response = app.get('/might-fail', status='*')
# Allow application errors to be captured
response = app.get('/buggy-page', expect_errors=True)
print(response.errors) # Any wsgi.errors output
```
--------------------------------
### Select Fields
Source: https://github.com/pylons/webtest/blob/main/docs/forms.md
Manage single and multiple select dropdowns.
```python
>>> print(form['select'].value)
option2
>>> form['select'] = 'option1'
```
```python
>>> print(form['multiple'].value)
['option2', 'option3']
>>> form['multiple'] = ['option1']
```
```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']
```
```python
>>> form['select'].force_value(['optionX'])
>>> form['multiple'].force_value(['optionX'])
```
--------------------------------
### Define a Basic WSGI Application
Source: https://github.com/pylons/webtest/blob/main/docs/index.md
A simple WSGI application function that returns a response with headers and body content.
```default
>>> def application(environ, start_response):
... headers = [('Content-Type', 'text/html; charset=utf8'),
... ('Content-Length', str(len(body)))]
... start_response('200 OK', headers)
... return [body]
```
--------------------------------
### Accept MultiDict-like Params
Source: https://github.com/pylons/webtest/blob/main/docs/changelog.rst
The `params` argument in requests can now accept any object with an `items` method, such as `MultiDict`. This provides flexibility in how request parameters are passed to the application.
```python
from webob.multidict import MultiDict
params = MultiDict([('key1', 'value1'), ('key2', 'value2')])
app.get('/path', params=params)
```
--------------------------------
### Handle Multiple Select Fields in Forms
Source: https://github.com/pylons/webtest/blob/main/docs/changelog.rst
WebTest now supports `