### 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 `