{"id":4323,"library":"webtest","title":"WebTest","description":"WebTest is a Python library that wraps any WSGI application, making it easy to send test requests without starting an HTTP server. It provides convenient full-stack testing for WSGI-compatible frameworks. An extraction of `paste.fixture.TestApp`, rewritten to use `WebOb`, it is under active development as part of the Pylons cloud of packages and is currently at version 3.0.7.","status":"active","version":"3.0.7","language":"en","source_language":"en","source_url":"https://github.com/Pylons/webtest","tags":["testing","wsgi","web","http","functional testing"],"install":[{"cmd":"pip install WebTest","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Core dependency for request and response objects.","package":"webob","optional":false},{"reason":"Used for parsing HTML forms in responses (e.g., `response.html`, form handling).","package":"beautifulsoup4","optional":true},{"reason":"Used for parsing HTML/XML responses via `response.lxml`.","package":"lxml","optional":true},{"reason":"Used for parsing HTML responses via `response.pyquery`.","package":"pyquery","optional":true},{"reason":"Used for proxying requests to actual HTTP servers when `TestApp` is instantiated with a URL.","package":"wsgiproxy2","optional":true}],"imports":[{"note":"While `webtest.app.TestApp` works, the idiomatic and stable import is directly from the `webtest` package.","wrong":"from webtest.app import TestApp","symbol":"TestApp","correct":"from webtest import TestApp"}],"quickstart":{"code":"from webtest import TestApp\n\ndef simple_app(environ, start_response):\n    status = '200 OK'\n    headers = [('Content-type', 'text/plain')]\n    start_response(status, headers)\n    return [b'Hello, world!']\n\napp = TestApp(simple_app)\nresp = app.get('/')\n\nassert resp.status == '200 OK'\nassert 'Hello, world!' in resp.text\n\nprint(f\"Status: {resp.status}\")\nprint(f\"Body: {resp.text}\")","lang":"python","description":"Initializes `TestApp` with a basic WSGI application and performs a GET request, asserting the response status and content."},"warnings":[{"fix":"Upgrade Python environment to 3.6 or newer (preferably 3.9+). Review code for Python 2/3.5 specific syntax.","message":"Version 3.0.0 dropped support for Python 2.7 and Python 3.5. Applications must use Python 3.6+ (3.9+ officially supported).","severity":"breaking","affected_versions":"3.0.0 and later"},{"fix":"Update usage of `click` methods, adapt to the new cookiejar API if targeting Python 3.3+, and install `webtest-selenium` or `webtest-casperjs` if those integrations are still required.","message":"Version 2.0 introduced several breaking changes, including the removal of `anchor` from `TestResponse.click` and `button` from `TestResponse.clickbutton`. The cookiejar API changed for Python 3.3. Selenium and CasperJS integrations were moved to separate, optional packages (`webtest-selenium`, `webtest-casperjs`).","severity":"breaking","affected_versions":"2.0 and later"},{"fix":"If expecting an error status (e.g., 404, 500), pass `status=EXPECTED_STATUS_CODE` (e.g., `status=404`) or `expect_errors=True` to the request method (e.g., `app.get('/nonexistent', status=404)` or `app.post('/error', expect_errors=True)`).","message":"By default, `TestApp.get()`, `post()`, and other request methods raise an `AppError` if the response status code is not 2xx or 3xx (success or redirect).","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure the necessary parsing library is installed (`pip install beautifulsoup4 lxml pyquery`) and that the response's `Content-Type` header matches the expected format (e.g., `text/html` for `.html`, `application/json` for `.json`).","message":"Accessing parsed response attributes like `resp.html`, `resp.xml`, `resp.lxml`, `resp.pyquery`, or `resp.json` requires the respective parsing library (BeautifulSoup4, lxml, PyQuery, or `json` module for `json`) to be installed. An `ImportError` or `AttributeError` may be raised if the library is missing or the content-type is incorrect.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-11T00:00:00.000Z","next_check":"2026-07-10T00:00:00.000Z"}