### Install Development Dependencies Source: https://github.com/taverntesting/tavern/blob/master/README.md Install the library, all extras, and other development options within your virtual environment. ```bash uv sync --all-extras --all-packages ``` -------------------------------- ### Start gRPC Server Source: https://github.com/taverntesting/tavern/blob/master/example/grpc/README.md Build and start the gRPC server using Docker Compose. This command is used to set up the testing environment. ```bash docker compose up --build ``` -------------------------------- ### Install Tavern Source: https://github.com/taverntesting/tavern/blob/master/docs/source/examples.md Install Tavern using pip. This command is typically run before executing tests. ```bash $ pip install tavern ``` -------------------------------- ### Install Tavern Source: https://github.com/taverntesting/tavern/blob/master/README.md Install Tavern using pip. This is the first step to using Tavern for API testing. ```bash pip install tavern ``` -------------------------------- ### Full MQTT and HTTP Test Example Source: https://github.com/taverntesting/tavern/blob/master/docs/source/mqtt.md This example demonstrates a multi-stage test combining HTTP requests with MQTT publishing and delays, showcasing how to test systems with both protocols. ```yaml --- test_name: Make sure posting publishes mqtt message includes: - !include common.yaml # More realistic broker connection options paho-mqtt: &mqtt_spec client: transport: websockets connect: host: an.mqtt.broker.com port: 4687 tls: enable: true auth: username: joebloggs password: password123 stages: - name: step 1 - get device state with lights off request: url: "{host}/get_device_state" params: device_id: 123 method: GET headers: content-type: application/json response: status_code: 200 json: lights: "off" headers: content-type: application/json - name: step 2 - publish an mqtt message saying that the lights are now on mqtt_publish: topic: /device/123/lights qos: 1 payload: "on" delay_after: 2 - name: step 3 - get device state, lights now on request: url: "{host}/get_device_state" params: device_id: 123 method: GET headers: content-type: application/json response: status_code: 200 json: lights: "on" headers: content-type: application/json ``` -------------------------------- ### Install pre-commit Hooks Source: https://github.com/taverntesting/tavern/blob/master/CONTRIBUTING.md Install the pre-commit git hooks to automatically run checks before each commit. ```bash pre-commit install ``` -------------------------------- ### Run Unit Tests with Tox Source: https://github.com/taverntesting/tavern/blob/master/README.md Install tox and run unit tests within your virtual environment. ```bash pip install tox tox ``` -------------------------------- ### Example Response Structure Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/types.md This is an example of a server response structure that will be used to demonstrate strict key checking. ```json { "first": 1, "second": { "nested": 2 } } ``` -------------------------------- ### Base Dockerfile for Tavern Source: https://github.com/taverntesting/tavern/blob/master/docs/source/cookbook.md A basic Dockerfile to set up a Python environment with Tavern installed. Use this as a starting point for your Dockerized integration tests. ```dockerfile # tavern.Dockerfile FROM python:3.11-slim RUN pip3 install tavern ``` -------------------------------- ### Run Flask Development Server Source: https://github.com/taverntesting/tavern/blob/master/docs/source/examples.md Start the Flask development server for the Python application. Ensure the FLASK_APP environment variable is set. ```bash $ export FLASK_APP=server.py $ flask run ``` -------------------------------- ### Command Line Global Configuration Usage Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/config.md Examples of how to pass a global configuration file to Tavern using the command line with `tavern-ci` or `py.test`. ```bash # These will all work $ tavern-ci --tavern-global-cfg=integration_tests/local_urls.yaml $ tavern-ci --tavern-global-cfg integration_tests/local_urls.yaml $ py.test --tavern-global-cfg=integration_tests/local_urls.yaml $ py.test --tavern-global-cfg integration_tests/local_urls.yaml ``` -------------------------------- ### Running Tavern Tests with tavern-ci Source: https://github.com/taverntesting/tavern/blob/master/README.md Shows how to install Tavern and execute a test file using the 'tavern-ci' command-line interface, printing the output to standard output. This is an alternative to using pytest. ```bash pip install tavern tavern-ci --stdout test_minimal.tavern.yaml ``` ```text 2017-11-08 16:17:00,152 [INFO]: (tavern.core:55) Running test : Get some fake data from the JSON placeholder API 2017-11-08 16:17:00,153 [INFO]: (tavern.core:69) Running stage : Make sure we have the right ID 2017-11-08 16:17:00,239 [INFO]: (tavern.core:73) Response: '' ({ "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", "json": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto" }) 2017-11-08 16:17:00,239 [INFO]: (tavern.printer:9) PASSED: Make sure we have the right ID [200] ``` -------------------------------- ### YAML Anchors Example (Problematic) Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/config.md This example demonstrates a common YAML structure with anchors and aliases. However, standard YAML parsers will fail if an alias is used across different documents, as shown in the traceback. ```yaml --- first: &top_anchor a: b c: d second: *top_anchor --- third: <<: *top_anchor c: overwritten e: f ``` -------------------------------- ### Running Tavern Tests with Pytest Source: https://github.com/taverntesting/tavern/blob/master/docs/source/examples.md This example shows how to run Tavern tests using the pytest command-line tool. It displays the typical output when tests are collected and executed. ```bash $ py.test ============================= test session starts ============================== platform linux -- Python 3.5.2, pytest-3.2.0, py-1.4.34, pluggy-0.4.0 rootdir: /home/developer/project/tests, inifile: setup.cfg plugins: tavern-0.0.1 collected 4 items test_server.tavern.yaml .. ===================== 2 passed, 2 skipped in 0.07 seconds ====================== ``` -------------------------------- ### Example Test Output with INFO Logging Source: https://github.com/taverntesting/tavern/blob/master/docs/source/debugging.md This is a sample output from running a Tavern test with INFO level logging enabled, showing the test execution flow and highlighting a key mismatch error. ```text _______________________________________________________________ /home/michael/code/tavern/example/http/tests/test_hello.tavern.yaml::Test authenticated /hello ________________________________________________________________ Format variables: test_login_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0LXVzZXIiLCJhdWQiOiJ0ZXN0c2VydmVyIiwiZXhwIjoxNzcwNTkyODMxfQ.5AZfT6_G0EpEI_mnR5t_JItDvmBvrILa9yK5XaJpbQY' service:s = 'http://localhost:5000' Source test stage (line 18): - name: Authenticated /hello request: url: "{service:s}/hello/Jim" method: GET headers: Content-Type: application/json Authorization: "Bearer {test_login_token}" response: status_code: 200 headers: content-type: application/json json: data: "this test should fail" Formatted stage: name: Authenticated /hello request: headers: Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0LXVzZXIiLCJhdWQiOiJ0ZXN0c2VydmVyIiwiZXhwIjoxNzcwNTkyODMxfQ.5AZfT6_G0EpEI_mnR5t_JItDvmBvrILa9yK5XaJpbQY Content-Type: application/json method: GET url: http://localhost:5000/hello/Jim response: headers: content-type: application/json json: data: this test should fail status_code: 200 Errors: E tavern._core.exceptions.TestFailError: Test 'Authenticated /hello' failed: - Key mismatch: (expected["data"] = 'this test should fail' (type = ), actual["data"] = 'Hello, Jim' (type = )) ---------------------------------------------------------------------------------------------------- Captured stderr call ----------------------------------------------------------------------------------------------------- 22:28:52 [INFO]: (tavern._core.run:177) Running test : Test authenticated /hello 22:28:52 [INFO]: (tavern._core.run:370) Running stage : Unauthenticated /hello 22:28:52 [INFO]: (tavern._plugins.common.response:64) Response: '' 22:28:52 [INFO]: (tavern._core.run:370) Running stage : Login and acquire token 22:28:53 [INFO]: (tavern._plugins.common.response:64) Response: '' 22:28:53 [INFO]: (tavern._core.run:370) Running stage : Authenticated /hello 22:28:53 [INFO]: (tavern._plugins.common.response:64) Response: '' 22:28:53 [ERROR]: (tavern.response:42) Key mismatch: (expected["data"] = 'this test should fail' (type = ), actual["data"] = 'Hello, Jim' (type = )) Traceback (most recent call last): File "/home/michael/code/tavern/tavern/_core/dict_util.py", line 418, in check_keys_match_recursive assert actual_val == expected_val # noqa ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AssertionError During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/home/michael/code/tavern/tavern/_core/dict_util.py", line 418, in check_keys_match_recursive assert actual_val == expected_val # noqa ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AssertionError The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/home/michael/code/tavern/tavern/response.py", line 107, in recurse_check_key_match check_keys_match_recursive(expected_block, block, [], strict) ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/michael/code/tavern/tavern/_core/dict_util.py", line 466, in check_keys_match_recursive check_keys_match_recursive( ~~~~~~~~~~~~~~~~~~~~~~~~~~ expected_val[key], ^^^^^^^^^^^^^^^^^^ ... <2 lines>... strict, ^^^^^^^^ ) ^ File "/home/michael/code/tavern/tavern/_core/dict_util.py", line 553, in check_keys_match_recursive raise exceptions.KeyMismatchError(f"Key mismatch: ({full_err()})") from e tavern._core.exceptions.KeyMismatchError: Key mismatch: (expected["data"] = 'this test should fail' (type = ), actual["data"] = 'Hello, Jim' (type = )) ``` -------------------------------- ### Run Integration Tests with Tox Source: https://github.com/taverntesting/tavern/blob/master/README.md Ensure Docker is installed, then run integration tests using a specific tox configuration file. This may take a while. ```bash tox -c tox-integration.ini ``` -------------------------------- ### Tavern YAML Test File Structure Source: https://github.com/taverntesting/tavern/blob/master/README.md Defines a single test stage with an HTTP GET request and expected response status code and JSON body. This is a basic example of a Tavern test case. ```yaml stages: - name: Make sure we have the right ID request: url: https://jsonplaceholder.typicode.com/posts/1 method: GET response: status_code: 200 json: id: 1 userId: 1 title: "sunt aut facere repellat provident occaecati excepturi optio reprehenderit" body: "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto" ``` -------------------------------- ### Basic GraphQL Query Source: https://github.com/taverntesting/tavern/blob/master/docs/source/graphql.md A simple example of making a basic GraphQL query to retrieve user data by ID. ```yaml stages: - name: Get user by ID graphql_request: url: "{graphql_server_url}/graphql" query: | query GetUser($id: ID!) { user(id: $id) { id name email } } variables: id: "1" ``` -------------------------------- ### KeyError Example in Tavern Source: https://github.com/taverntesting/tavern/blob/master/docs/source/debugging.md This example illustrates a common scenario where Tavern encounters a KeyError when trying to access a non-existent key in a response. The logs will show the KeyError, and the TestFailError will provide a more user-friendly explanation. ```text When tavern tries to access `a_key` in the response it gets a `KeyError` (shown in the logs), and the `TestFailError` in the stack trace gives a more human-readable explanation as to why the test failed. ``` -------------------------------- ### Combine Parametrize Styles for Multiple Keys and Single Key Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/marks.md This example combines the previous two parametrization styles. It uses specific combinations for 'fruit' and 'edible' and then independently parametrizes 'price', leading to a total of 3 combinations * 2 prices = 6 tests. ```yaml --- test_name: Test post a new fruit and price marks: - parametrize: key: - fruit - edible vals: - [ rotten, apple ] - [ fresh, orange ] - [ unripe, pear ] - parametrize: key: price vals: - expensive - cheap stages: - name: Create a new fruit entry request: url: "{host}/fruit" method: POST json: fruit_type: "{price} {edible} {fruit}" response: status_code: 201 ``` -------------------------------- ### Configure Custom Backend Entry Point Source: https://github.com/taverntesting/tavern/blob/master/docs/source/plugins/custom.md Define the entry point for your custom backend in pyproject.toml. The entry point name must start with 'tavern_'. ```toml [project.entry-points.tavern_your_backend_name] my_implementation = 'your.package.path:your_backend_module' ``` -------------------------------- ### Minimal Tavern Test Example Source: https://github.com/taverntesting/tavern/blob/master/README.md A basic Tavern test file using YAML syntax to fetch data from a placeholder API. This demonstrates the fundamental structure of a Tavern test. ```yaml --- # Every test file has one or more tests... test_name: Get some fake data from the JSON placeholder API ``` -------------------------------- ### Run Tavern Tests with CLI Source: https://github.com/taverntesting/tavern/blob/master/docs/source/examples.md Execute Tavern tests using the tavern-ci command-line interface. This command is installed with Tavern. ```bash $ tavern-ci test_minimal.tavern.yaml ``` -------------------------------- ### Running Tavern Tests with Pytest Source: https://github.com/taverntesting/tavern/blob/master/README.md Demonstrates how to install Tavern with pytest support and run a test file named 'test_minimal.tavern.yaml' using the py.test command. This shows the typical output of a successful test run. ```bash pip install tavern[pytest] py.test test_minimal.tavern.yaml -v ``` ```text =================================== test session starts =================================== platform linux -- Python 3.5.2, pytest-3.4.2, py-1.5.2, pluggy-0.6.0 -- /home/taverntester/.virtualenvs/tavernexample/bin/python3 cachedir: .pytest_cache rootdir: /home/taverntester/myproject, inifile: plugins: tavern-0.7.2 collected 1 item test_minimal.tavern.yaml::Get some fake data from the JSON placeholder API PASSED [100%] ================================ 1 passed in 0.14 seconds ================================= ``` -------------------------------- ### External JSON Test Data Example Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/config.md Example of a JSON file containing a large array of objects, suitable for inclusion in Tavern tests. ```json [ { "_id": "5c965b1373f3fe071a9cb2b7", "index": 0, "guid": "ef3f8c42-522a-4d6b-84ec-79a07009460d", "isActive": false, "balance": "$3,103.47", "picture": "http://placehold.it/32x32", "age": 26, "eyeColor": "green", "name": "Cannon Wood", "gender": "male", "company": "CANDECOR", "email": "cannonwood@candecor.com", "phone": "+1 (944) 549-2826", "address": "528 Woodpoint Road, Snowville, Kansas, 140", "about": "Dolore in consequat exercitation esse esse velit eu velit aliquip ex. Reprehenderit est consectetur excepteur sint sint dolore. Anim minim dolore est ut fugiat. Occaecat tempor tempor mollit dolore anim commodo laboris commodo aute quis ex irure voluptate. Sunt magna tempor veniam cillum exercitation quis minim est eiusmod aliqua.\r\n", "registered": "2015-12-27T11:30:18 -00:00", "latitude": -2.515302, "longitude": -98.678105, "tags": [ "proident", "aliqua", "velit", "labore", "consequat", "esse", "ea" ], "friends": [ { "id": 0, "etc": [] } ] } ] ``` -------------------------------- ### Parametrize Multiple Keys for Cartesian Product Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/marks.md This example shows how to parametrize two separate keys, 'fruit' and 'edible', independently. This will result in a Cartesian product of all possible combinations (3 fruits * 3 edible states = 9 tests). ```yaml --- test_name: Test post a new fruit marks: - parametrize: key: fruit vals: - apple - orange - pear - parametrize: key: edible vals: - rotten - fresh - unripe stages: - name: Create a new fruit entry request: url: "{host}/fruit" method: POST json: fruit_type: "{edible} {fruit}" response: status_code: 201 ``` -------------------------------- ### Pytest Autouse Fixture Example Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/external_code.md This example shows how to define an 'autouse' Pytest fixture with session scope. Autouse fixtures are automatically applied to tests without explicit declaration. ```python @pytest.fixture(scope="session", autouse=True) def a_thing(): return "abc" ``` -------------------------------- ### Example Test for Custom Backend Source: https://github.com/taverntesting/tavern/blob/master/example/custom_backend/README.md This YAML snippet defines a Tavern test case that utilizes custom backend stages to touch a file and then verify its existence. ```yaml --- test_name: Test file touched stages: - name: Touch file and check it exists # The 'request' for this stage touches a file touch_file: filename: hello.txt # The 'response' checks that the file exists file_exists: filename: hello.txt ``` -------------------------------- ### Custom Authorization Header (JWT Example) Source: https://github.com/taverntesting/tavern/blob/master/docs/source/http.md Specify a custom 'Authorization' header for authentication schemes not covered by default, such as JWT. The example demonstrates logging in and then using a JWT to access an API, with JWT validation handled by an external function. ```yaml --- test_name: Check we can login then use a JWT to access the API includes: - !include common.yaml stages: - name: login request: url: "{host}/login" json: user: test-user password: correct-password method: POST headers: content-type: application/json response: status_code: 200 json: $ext: &verify_token function: tavern.helpers:validate_jwt extra_kwargs: jwt_key: "token" key: CGQgaG7GYvTcpaQZqosLy4 options: verify_signature: true verify_aud: true verify_exp: true audience: testserver headers: content-type: application/json save: json: test_login_token: token - name: Get user info request: url: "{host}/userinfo" method: GET headers: Authorization: "Bearer {test_login_token:s}" response: status_code: 200 json: user_id: 123 headers: content-type: application/json ``` -------------------------------- ### GraphQL Query with Custom Headers Source: https://github.com/taverntesting/tavern/blob/master/docs/source/graphql.md Example of making an authenticated GraphQL query that includes custom headers like Authorization and Content-Type. ```yaml stages: - name: Authenticated query graphql_request: url: "{graphql_server_url}/graphql" headers: Authorization: "Bearer {auth_token}" Content-Type: "application/json" # Automatically added if not present query: | query GetUserData { me { id name } } ``` -------------------------------- ### Simple gRPC Test with Precompiled Stubs Source: https://github.com/taverntesting/tavern/blob/master/docs/source/grpc.md An example of a basic gRPC test that loads precompiled protobuf stubs from a Python module. This is useful when you have existing compiled stubs in your project. ```yaml test_name: Test grpc connection without the 'connect' block includes: - !include common.yaml grpc: proto: module: helloworld_v1_precompiled_pb2_grpc stages: - name: Echo text grpc_request: host: "{grpc_host}:{grpc_port}" service: helloworld.v1.Greeter/SayHello body: name: "John" grpc_response: status: "OK" body: message: "Hello, John!" ``` -------------------------------- ### Test with Multiple Expected Status Codes Source: https://github.com/taverntesting/tavern/blob/master/docs/source/http.md Use this when a server might return different status codes based on its state. This example checks for either a 200 or a 404. ```yaml --- test_name: Make sure that the server will either return a 200 or a 404 stages: - name: Try to get user request: url: "{host}/users/joebloggs" method: GET response: status_code: - 200 - 404 ``` -------------------------------- ### Minimal Tavern Test Source: https://github.com/taverntesting/tavern/blob/master/docs/source/examples.md A basic Tavern test case using the JSON Placeholder API to fetch and verify data. Ensure Tavern is installed via pip. ```yaml test_name: Get some fake data from the JSON placeholder API stages: - name: Make sure we have the right ID request: url: https://jsonplaceholder.typicode.com/posts/1 method: GET response: status_code: 200 json: id: 1 userId: 1 title: "sunt aut facere repellat provident occaecati excepturi optio reprehenderit" body: "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto" ``` -------------------------------- ### Example YAML for a Failing Test Source: https://github.com/taverntesting/tavern/blob/master/docs/source/debugging.md This YAML defines a test case that is expected to fail due to a key mismatch in the response. It includes request details and the expected response structure. ```yaml # Log in ... - name: post a number request: url: "{host}/numbers" json: name: smallnumber number: 123 method: POST headers: content-type: application/json Authorization: "bearer {test_login_token:s}" response: status_code: 201 headers: content-type: application/json # This key will not actually be present in the response json: a_key: missing ``` -------------------------------- ### Parametrize with Random Different Data Types Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/marks.md This example demonstrates parametrizing a single key 'value_to_send' with various data types, including strings, lists, and dictionaries. This allows for testing how the API handles diverse input types within the same test structure. ```yaml --- test_name: Test parametrizing random different data types in the same test marks: - parametrize: key: value_to_send vals: ``` -------------------------------- ### Publishing JSON Payload via MQTT Source: https://github.com/taverntesting/tavern/blob/master/docs/source/mqtt.md This example shows how to publish a JSON object as an MQTT payload. Instead of 'payload', use the 'json' key to automatically serialize a YAML object into a JSON string. ```yaml mqtt_publish: topic: /device/123/ping json: thing_1: abc thing_2: 123 ``` -------------------------------- ### Tavern Logging Configuration with Colorlog Source: https://github.com/taverntesting/tavern/blob/master/docs/source/debugging.md This YAML configuration sets up detailed logging for Tavern tests using colorlog for colored output and dictConfig for Python integration. Install 'colorlog' and 'PyYAML' packages to use this. ```yaml --- version: 1 formatters: default: # colorlog is really useful (): colorlog.ColoredFormatter format: "% (asctime)s [%(bold)s%(log_color)s%(levelname)s%(reset)s]: (%(bold)s%(name)s:%(lineno)d%(reset)s) %(message)s" style: "%" datefmt: "%X" log_colors: DEBUG: cyan INFO: green WARNING: yellow ERROR: red CRITICAL: red,bg_white handlers: stderr: class: colorlog.StreamHandler formatter: default loggers: tavern: handlers: - stderr level: INFO propagate: false ``` -------------------------------- ### Using Environment Variables for Authorization Source: https://github.com/taverntesting/tavern/blob/master/docs/source/basics.md Access environment variables for sensitive data like authorization tokens. This example shows how to use a CI commit auth token. ```yaml --- test_name: Test getting user information requires auth stages: - name: Get information without auth fails request: method: GET url: "www.example.com/get_info" response: status_code: 401 json: error: "No authorization" - name: Get information with admin token request: method: GET url: "www.example.com/get_info" headers: Authorization: "Basic {tavern.env_vars.SECRET_CI_COMMIT_AUTH}" response: status_code: 200 json: name: "Joe Bloggs" ``` -------------------------------- ### YAML Anchors for Reusing Data Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/config.md Define reusable YAML fragments using anchors (`&`) and reuse them with `*` or `<<: *` for extending objects. This example shows how to define an anchor and reuse it in multiple places. ```yaml # input.yaml --- first: &top_anchor a: b c: d second: *top_anchor third: <<: *top_anchor c: overwritten e: f ``` -------------------------------- ### Per-Test Strictness Settings Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/types.md Configure specific strictness rules like headers and JSON parsing on a per-test basis. This example enables strict header checking and disables strict JSON checking. ```yaml --- test_name: Make sure the headers match what I expect exactly strict: - headers:on - json:off stages: - name: Try to get user request: url: "{host}/users/joebloggs" method: GET response: status_code: 200 headers: content-type: application/json content-length: 20 x-my-custom-header: chocolate json: # As long as "id: 1" is in the response, this will pass and other keys will be ignored id: 1 ``` -------------------------------- ### HTTP and MQTT Plugin Entry Points in setup.cfg Source: https://github.com/taverntesting/tavern/blob/master/docs/source/plugins.md Configure setuptools entry points for Tavern to discover custom HTTP and MQTT plugins. 'tavern_http' and 'tavern_mqtt' are the entry point names, followed by the plugin name and the path to the plugin's class or module. ```ini # setup.cfg # A http plugin. tavern_http is the entry point that Tavern searches for, # 'requests' is the name of your plugin which is selected using the # --tavern-http-backend command line flag. This points to a class in the # tavernhook module. tavern_http = requests = tavern._plugins.rest.tavernhook:TavernRestPlugin # An MQTT plugin. Like above, tavern_mqtt is the entry point name and # 'paho-mqtt' is the name of the plugin. This points to a module. tavern_mqtt = paho-mqtt = tavern._plugins.mqtt.tavernhook ``` -------------------------------- ### Error Case: Non-Dictionary Return from External Function Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/marks.md This commented-out example shows an invalid use case where an external function is expected to return a dictionary but is configured to return a string, which would raise an error. ```yaml # This would raise an error - and: this $ext: function: ext_functions:return_string ``` -------------------------------- ### Example of using xfail mark in Tavern Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/marks.md This snippet demonstrates how to mark a test as 'xfail' in a Tavern test file. This test is expected to fail, and the 'xfail' mark will prevent it from causing the overall test suite to fail. ```yaml --- test_name: Get user middle name from endpoint on v1 api stages: - name: Get from endpoint request: url: "{host}/api/v1/users/{user_id}/get-middle-name" method: GET response: status_code: 200 json: middle_name: Jimmy --- test_name: Get user middle name from endpoint on v2 api fails marks: - xfail stages: - name: Try to get from v2 api request: url: "{host}/api/v2/users/{user_id}/get-middle-name" method: GET response: status_code: 200 json: middle_name: Jimmy ``` -------------------------------- ### Build Documentation with mystmd Source: https://github.com/taverntesting/tavern/blob/master/CONTRIBUTING.md Build the project documentation into HTML format using mystmd. ```bash uv tool run --from mystmd myst build --html ``` -------------------------------- ### Basic MQTT Test with Publish/Response Source: https://github.com/taverntesting/tavern/blob/master/docs/source/mqtt.md This snippet demonstrates a simple MQTT test case. It requires a 'paho-mqtt' block for client configuration and uses 'mqtt_publish' and 'mqtt_response' to send and receive messages. ```yaml # test_mqtt.tavern.yaml --- test_name: Test mqtt message response paho-mqtt: client: transport: websockets client_id: tavern-tester connect: host: localhost port: 9001 timeout: 3 stages: - name: step 1 - ping/pong mqtt_publish: topic: /device/123/ping payload: ping mqtt_response: topic: /device/123/pong payload: pong timeout: 5 ``` -------------------------------- ### Example Tavern Test Response Block Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/types.md This is how the expected response structure would be defined in a Tavern test. ```yaml ... response: json: first: 1 second: nested: 2 ``` -------------------------------- ### Create Virtual Environment with uv Source: https://github.com/taverntesting/tavern/blob/master/CONTRIBUTING.md Use this command to create a new virtual environment for the project. ```shell uv venv ``` -------------------------------- ### Python Tincture Functions Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/external_code.md Example Python functions that can be used as tinctures. 'time_request' measures the duration of a stage, and 'print_response' logs details about the response. ```python import logging import time logger = logging.getLogger(__name__) def time_request(stage): t0 = time.time() yield t1 = time.time() logger.info("Request for stage %s took %s", stage, t1 - t0) def print_response(_, extra_print="affa"): logger.info("STARTING:") (expected, response) = yield logger.info("Response is %s (%s)", response, extra_print) ``` -------------------------------- ### Parametrization with Lists and Dictionaries Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/marks.md Demonstrates parametrization using lists for simple values and nested structures, and dictionaries for more complex data. ```yaml - a - [ b, c ] - more: stuff - yet: [ more, stuff ] ``` -------------------------------- ### Global Configuration with Command-Line Arguments Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/config.md Use the --tavern-global-cfg flag to specify global configuration files that apply to all tests. Arguments after '--' are treated as test files. ```bash $ tavern-ci --tavern-global-cfg common.yaml test_urls.yaml -- test_server.tavern.yaml $ py.test --tavern-global-cfg common.yaml local_docker_urls.yaml -- test_server.tavern.yaml ``` -------------------------------- ### Sync Dependencies with uv Source: https://github.com/taverntesting/tavern/blob/master/CONTRIBUTING.md Synchronize the virtual environment with all specified dependencies, extras, packages, and groups. ```shell uv sync --all-extras --all-packages --all-groups ``` -------------------------------- ### Basic Test with Includes Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/config.md A simple Tavern test case demonstrating the use of an include file for external variables and configuration. ```yaml --- test_name: Check server is up includes: - !include includes.yaml stages: - name: Check healthz endpoint request: method: GET url: "{protocol:s}://{host:s}:{port:d}" response: status_code: 200 ``` -------------------------------- ### Custom Python function for response verification Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/external_code.md Example of a Python function that asserts a specific JSON field in the response. This function can be referenced in the Tavern YAML test. ```python # testing_utils.py def message_says_hello(response): """Make sure that the response was friendly """ assert response.json().get("message") == "hello world" ``` -------------------------------- ### Specify Specific Cookies to Send Source: https://github.com/taverntesting/tavern/blob/master/docs/source/http.md When multiple cookies are available, use the 'cookies' key in the request block to specify which one(s) to send. This example sends only 'tavern-cookie-1'. ```yaml --- test_name: Test receiving and sending cookie includes: - !include common.yaml stages: - name: Expect multiple cookies returned request: url: "{host}/get_cookie" method: POST response: status_code: 200 cookies: - tavern-cookie-1 - tavern-cookie-2 - name: Only send one cookie request: url: "{host}/expect_cookie" method: GET cookies: - tavern-cookie-1 response: status_code: 200 json: status: ok ``` -------------------------------- ### Run All Files Check with pre-commit Source: https://github.com/taverntesting/tavern/blob/master/CONTRIBUTING.md Execute pre-commit hooks on all files in the repository to ensure code quality and formatting. ```bash pre-commit run --all-files ``` -------------------------------- ### Pytest INI Configuration (Correct Method) Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/config.md Demonstrates the correct way to specify global configuration files in the `pytest.ini` file for use with pytest. ```ini [pytest] tavern-global-cfg = integration_tests/local_urls.yaml ``` -------------------------------- ### Using client certificate and key Source: https://github.com/taverntesting/tavern/blob/master/docs/source/http.md Provide both a client certificate and its corresponding private key for secure requests. This is necessary when the server requires both for authentication. ```yaml --- test_name: Access an API which requires a client certificate stages: - name: Get user info request: url: "{host}/userinfo" method: GET cert: - "/path/to/certificate" - "/path/to/key" response: ... ``` -------------------------------- ### GraphQL Configuration with Global Headers Source: https://github.com/taverntesting/tavern/blob/master/docs/source/graphql.md Shows how to configure default headers for all GraphQL requests within a test file using the top-level 'gql' block. ```yaml gql: headers: string: string # Default headers for all requests ``` ```yaml --- test_name: Query with global authorization header gql: headers: Authorization: "Bearer test-token" stages: - name: Query with authorization header graphql_request: ... ``` -------------------------------- ### Send No Cookies in a Request Source: https://github.com/taverntesting/tavern/blob/master/docs/source/http.md To explicitly send no cookies with a request, use an empty array for the 'cookies' key. This example demonstrates a scenario where sending no cookies results in access denial. ```yaml --- test_name: Test receiving and sending cookie includes: - !include common.yaml stages: - name: get cookie for domain request: url: "{host}/get_cookie" method: POST response: status_code: 200 cookies: - tavern-cookie-1 - name: Send no cookies request: url: "{host}/expect_cookie" method: GET cookies: [ ] response: status_code: 403 json: status: access denied ``` -------------------------------- ### Parametrization with External Functions Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/marks.md Shows how to use external functions for dynamic data generation within parametrization. The `$ext` key is used to specify the function and its arguments. ```yaml - $ext: function: ext_functions:return_string ``` -------------------------------- ### Two Tests with Separate Includes Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/config.md Demonstrates how to structure two distinct tests that include different configuration files, allowing for variations in test data or environment settings. ```yaml # two_tests.tavern.yaml --- test_name: Check server A responds properly includes: - !include includesA.yaml stages: - name: Check thing is processed correctly request: method: GET url: "{host:s}/" json: &input_data name: "{name:s}" house_number: "{house_number:d}" street: "{street:s}" town: "{town:s}" postcode: "{postcode:s}" country: "{country:s}" planet: "{planet:s}" galaxy: "{galaxy:s}" universe: "{universe:s}" response: status_code: 200 json: hashed: "{expected_hash:s}" --- test_name: Check server B responds properly includes: - !include includesB.yaml stages: - name: Check thing is processed correctly request: method: GET url: "{host:s}/" json: <<: *input_data response: status_code: 200 json: hashed: "{expected_hash:s}" ``` -------------------------------- ### Watch for Documentation Changes and Rebuild Source: https://github.com/taverntesting/tavern/blob/master/CONTRIBUTING.md Automatically rebuild the documentation when files in the 'docs/' folder or 'myst.yml' change. ```bash uv tool run watchfiles "uv tool run --from mystmd myst build --html" --filter all docs myst.yml ``` -------------------------------- ### Basic Session Class Implementation Source: https://github.com/taverntesting/tavern/blob/master/docs/source/plugins.md A minimal session class implementation for testing. It requires __enter__ and __exit__ methods to function as a context manager. ```python class MySession: def __enter__(self): pass def __exit__(self, *args): pass ``` -------------------------------- ### Per-Stage Strictness Control Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/types.md Disable strict key checking for a specific stage within a test. This example disables strict checking for the 'log in' stage while keeping it enabled for the test overall. ```yaml --- # Enable strict checking for this test, but disable it for the login stage test_name: Login and create a new user # Force re-enable strict checking, in case it was turned off globally strict: - json:on stages: - name: log in request: url: "{host}/users/joebloggs" method: GET response: # Disable all strict key checking just for this stage strict: False status_code: 200 json: logged_in: True # Ignores any extra metadata like user id, last login, etc. - name: Create a new user request: url: "{host}/users/joebloggs" method: POST json: &create_user first_name: joe last_name: bloggs email: joe@bloggs.com response: status_code: 200 # Because strict was set 'on' at the test level, this must match exactly json: <<: *create_user id: 1 ``` -------------------------------- ### Running Tavern Tests with tavern-ci Source: https://github.com/taverntesting/tavern/blob/master/docs/source/examples.md Demonstrates using the `tavern-ci` command-line tool to run Tavern tests, often used in bash scripting or cron jobs. It shows a successful execution with an exit code of 0. ```bash $ tavern-ci test_server.tavern.yaml $ echo $? ``` -------------------------------- ### Configure Strict Checking in Pytest Config Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/types.md Configure default strict checking behavior in the pytest configuration file. This example disables strict checking for the JSON body but enables it for headers. ```ini [pytest] tavern-strict = json:off headers:on ``` -------------------------------- ### gRPC Connection via grpc.connect Block Source: https://github.com/taverntesting/tavern/blob/master/docs/source/grpc.md Specifies the gRPC connection details (host and port) within the top-level 'grpc.connect' block. The connection is established at the start of the test and closed at the end. ```yaml grpc: connect: host: localhost port: 50052 ``` -------------------------------- ### Server A Specific Configuration Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/config.md A configuration file for Server A, specifying environment-specific variables like the host URL. ```yaml # includesA.yaml --- name: server A information description: server A specific information variables: host: www.server-a.com ``` -------------------------------- ### Parametrize Multiple Keys with Specific Combinations Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/marks.md This snippet demonstrates how to parametrize multiple keys ('fruit' and 'edible') but control the combinations. Instead of a Cartesian product, specific pairs of values are provided, resulting in fewer tests. ```yaml --- test_name: Test post a new fruit marks: - parametrize: key: - fruit - edible vals: - [ rotten, apple ] - [ fresh, orange ] - [ unripe, pear ] # NOTE: we can specify a nested list like this as well: # - # - unripe # - pear stages: - name: Create a new fruit entry request: url: "{host}/fruit" method: POST json: fruit_type: "{edible} {fruit}" response: status_code: 201 ``` -------------------------------- ### Loading gRPC Proto Definitions from Source Folder Source: https://github.com/taverntesting/tavern/blob/master/docs/source/grpc.md Loads gRPC protobuf definitions by specifying a source folder containing `.proto` files. Tavern will attempt to compile these using `protoc`. Requires `protobuf>=5,<6`. ```yaml grpc: proto: source: path/to/protos ``` -------------------------------- ### Simple Python Server for Testing Source: https://github.com/taverntesting/tavern/blob/master/docs/source/examples.md A Flask-based Python server with a '/double' route that doubles a number provided in a JSON request. Run this server using Flask. ```python # server.py from flask import Flask, jsonify, request app = Flask(__name__) @app.route("/double", methods=["POST"]) def double_number(): r = request.get_json() try: number = r["number"] except (KeyError, TypeError): return jsonify({"error": "no number passed"}), 400 try: double = int(number) * 2 except ValueError: return jsonify({"error": "a number was not passed"}), 400 return jsonify({"double": double}), 200 ``` -------------------------------- ### Override Cookie Value in Request Source: https://github.com/taverntesting/tavern/blob/master/docs/source/http.md Override the value of an existing cookie or set a new one by using a mapping of 'cookie name: cookie value' in the 'cookies' block. This example overrides 'tavern-cookie-2' to 'abc'. ```yaml - name: Override cookie value request: url: "{host}/expect_cookie" method: GET cookies: - tavern-cookie-2: abc response: status_code: 200 json: status: ok ``` -------------------------------- ### Configuring Advanced gRPC Connection Options Source: https://github.com/taverntesting/tavern/blob/master/docs/source/grpc.md Passes generic gRPC connection options as key-value pairs under the 'options' block within 'grpc.connect'. Refer to gRPC documentation for available options. ```yaml grpc: connect: options: grpc.max_send_message_length: 10000000 ``` -------------------------------- ### Tavern Test with Marks Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/marks.md Example of a Tavern test case defining marks and using fixtures. The 'endpoint_1' and 'endpoint_2' marks, along with 'usefixtures: read_uuid', indicate that the 'read_uuid' fixture should be used and can be conditionally controlled by these marks. ```yaml test_name: endpoint 1 test marks: - endpoint_1 - usefixtures: - read_uuid stages: ... --- test_name: endpoint 2 test marks: - endpoint_2 - usefixtures: - read_uuid stages: ... ``` -------------------------------- ### Generate Allure Report using PNPM Source: https://github.com/taverntesting/tavern/blob/master/docs/source/core_concepts/reports.md Use this command to generate an HTML test report after running Tavern tests with the allure-pytest integration. Ensure you have the allure-pytest plugin installed and have run your tests with the --alluredir flag. ```bash pnpx allure generate ``` -------------------------------- ### Build Specific Tavern Version Docker Image Source: https://github.com/taverntesting/tavern/blob/master/docs/source/cookbook.md Command to build a Docker image for a specific Tavern version. It sets the TAVERNVER build argument and tags the image accordingly. ```shell export TAVERNVER=0.24.0 docker build --build-arg TAVERNVER=$TAVERNVER --file tavern.Dockerfile --tag tavern:$TAVERNVER . ``` -------------------------------- ### Python Code to Load Logging Configuration Source: https://github.com/taverntesting/tavern/blob/master/docs/source/debugging.md This Python code snippet loads the YAML logging configuration defined in 'log_spec.yaml' using PyYAML and applies it using Python's logging.config.dictConfig. Ensure this code runs before your tests, for example, in conftest.py. ```python from logging import config import yaml with open("log_spec.yaml", "r") as log_spec_file: as_dict = yaml.load(log_spec_file.read(), Loader=yaml.SafeLoader) config.dictConfig(as_dict) ``` -------------------------------- ### Build Tavern Docker Image Source: https://github.com/taverntesting/tavern/blob/master/docs/source/cookbook.md Command to build the Docker image for Tavern. This command tags the image as 'tavern:latest'. ```shell docker build --file tavern.Dockerfile --tag tavern:latest . ```