From 13d7b2aa6ccf1a27b265f3d0fc2eaacfd3dfedeb Mon Sep 17 00:00:00 2001 From: michaelboulton Date: Sat, 11 May 2024 16:50:02 +0100 Subject: [PATCH 1/3] Remove requirement for 'name' in variable files (#923) * Remove requirement for 'name' in variable files * Add test case --- tavern/_core/schema/tests.jsonschema.yaml | 3 --- tests/integration/test_include.tavern.yaml | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/tavern/_core/schema/tests.jsonschema.yaml b/tavern/_core/schema/tests.jsonschema.yaml index 371f42f3..75f43486 100644 --- a/tavern/_core/schema/tests.jsonschema.yaml +++ b/tavern/_core/schema/tests.jsonschema.yaml @@ -44,9 +44,6 @@ definitions: type: object additionalProperties: false - required: - - name - properties: name: type: string diff --git a/tests/integration/test_include.tavern.yaml b/tests/integration/test_include.tavern.yaml index 4e2d45c7..f0dc11b9 100644 --- a/tests/integration/test_include.tavern.yaml +++ b/tests/integration/test_include.tavern.yaml @@ -14,6 +14,26 @@ stages: status_code: 200 json: !include 881_1.json +--- +test_name: Test using variables directly + +includes: + - !include common.yaml + - variables: + full_path: "echo" + +stages: + - name: Send included json + request: + url: "{host}/{full_path}" + method: POST + json: + hell: o + response: + status_code: 200 + json: + hell: o + --- test_name: Test including json with key From 512eed67f293a4469c026ec1de6c95f13da010dd Mon Sep 17 00:00:00 2001 From: Michael Boulton Date: Sat, 11 May 2024 16:51:02 +0100 Subject: [PATCH 2/3] Bump to 2.11.0 --- CHANGELOG.md | 2 ++ docs/source/conf.py | 2 +- pyproject.toml | 4 ++-- tavern/__init__.py | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f527e01..f3fe81b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -444,3 +444,5 @@ This is technically not a operational change but I'm adding a new tag so it can ## 2.10.1 minor changes to fix tavern_flask plugin (2024-03-27) ## 2.10.2 Fix missing schema check for redirect query params (2024-04-13) + +## 2.10.3 Allow using referenced 'finally' stages (2024-04-13) diff --git a/docs/source/conf.py b/docs/source/conf.py index d2cb3496..2e78961b 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -72,7 +72,7 @@ # The short X.Y version. version = "1.0" # The full version, including alpha/beta/rc tags. -release = "2.10.3" +release = "2.11.0" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/pyproject.toml b/pyproject.toml index e48a730f..ece3b1ef 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,7 +23,7 @@ keywords = ["testing", "pytest"] name = "tavern" description = "Simple testing of RESTful APIs" -version = "2.10.3" +version = "2.11.0" dependencies = [ "PyYAML>=6.0.1,<7", @@ -194,7 +194,7 @@ exclude = ["*_pb2.py", "*_pb2_grpc.py", "*_pb2.pyi"] docstring-code-format = true [tool.tbump.version] -current = "2.10.3" +current = "2.11.0" regex = ''' (?P\d+) diff --git a/tavern/__init__.py b/tavern/__init__.py index 75d74f68..c9e43d01 100644 --- a/tavern/__init__.py +++ b/tavern/__init__.py @@ -1,3 +1,3 @@ """Stop pytest warning about module already imported: PYTEST_DONT_REWRITE""" -__version__ = "2.10.3" +__version__ = "2.11.0" From 3113eab4071fb54e1d9fb6d4a56a89ab560b5c64 Mon Sep 17 00:00:00 2001 From: michaelboulton Date: Sun, 16 Jun 2024 15:05:32 +0100 Subject: [PATCH 3/3] Add test (#938) --- tavern/_core/dict_util.py | 2 +- tests/integration/Dockerfile | 2 +- tests/integration/server.py | 9 ++++ .../test_env_var_format.tavern.yaml | 15 ------- tests/integration/test_format.tavern.yaml | 31 ++++++++++++++ tests/unit/test_helpers.py | 41 ++++++++++++++++--- 6 files changed, 78 insertions(+), 22 deletions(-) delete mode 100644 tests/integration/test_env_var_format.tavern.yaml create mode 100644 tests/integration/test_format.tavern.yaml diff --git a/tavern/_core/dict_util.py b/tavern/_core/dict_util.py index f65eaeee..07c5364a 100644 --- a/tavern/_core/dict_util.py +++ b/tavern/_core/dict_util.py @@ -27,7 +27,7 @@ logger: logging.Logger = logging.getLogger(__name__) -def _check_and_format_values(to_format: str, box_vars: Mapping[str, Any]) -> str: +def _check_and_format_values(to_format: str, box_vars: Box) -> str: formatter = string.Formatter() would_format = formatter.parse(to_format) diff --git a/tests/integration/Dockerfile b/tests/integration/Dockerfile index edd2733d..7c964d8b 100644 --- a/tests/integration/Dockerfile +++ b/tests/integration/Dockerfile @@ -1,6 +1,6 @@ FROM python:3.10-alpine -RUN pip3 install 'pyjwt>=2.4.0,<3' 'flask>=2.2.3' +RUN pip3 install 'pyjwt>=2.4.0,<3' 'flask>=2.2.3' "python-box>=6,<7" ENV FLASK_DEBUG=1 ENV PYTHONUNBUFFERED=0 diff --git a/tests/integration/server.py b/tests/integration/server.py index 02c5b86d..9316b3a1 100644 --- a/tests/integration/server.py +++ b/tests/integration/server.py @@ -12,6 +12,7 @@ from urllib.parse import unquote_plus, urlencode import jwt +from box import Box from flask import Flask, Response, jsonify, make_response, redirect, request, session from itsdangerous import URLSafeTimedSerializer @@ -471,6 +472,14 @@ def get_606_dict(): return jsonify({}) +@app.route("/sub-path-query", methods=["POST"]) +def sub_path_query(): + r = request.get_json(force=True) + sub_path = r["sub_path"] + + return jsonify({"result": Box(r, box_dots=True)[sub_path]}) + + @app.route("/magic-multi-method", methods=["GET", "POST", "DELETE"]) def get_any_method(): return jsonify({"method": request.method}) diff --git a/tests/integration/test_env_var_format.tavern.yaml b/tests/integration/test_env_var_format.tavern.yaml deleted file mode 100644 index 6da19342..00000000 --- a/tests/integration/test_env_var_format.tavern.yaml +++ /dev/null @@ -1,15 +0,0 @@ ---- -test_name: Test getting format vars from environment variables - -includes: - - !include common.yaml - -stages: - - name: Make requests using environment variables - request: - url: "{tavern.env_vars.TEST_HOST}/{first_part}/{second_part}" - method: GET - response: - status_code: 200 - json: - status: OK diff --git a/tests/integration/test_format.tavern.yaml b/tests/integration/test_format.tavern.yaml new file mode 100644 index 00000000..7a9920ed --- /dev/null +++ b/tests/integration/test_format.tavern.yaml @@ -0,0 +1,31 @@ +--- +test_name: Test getting format vars from environment variables + +includes: + - !include common.yaml + +stages: + - name: Make requests using environment variables + request: + url: "{tavern.env_vars.TEST_HOST}/{first_part}/{second_part}" + method: GET + response: + status_code: 200 + json: + status: OK + +--- +test_name: Test slicing request vars + +stages: + - name: Make request and expect part of list in it to be returned + request: + url: "{global_host}/sub-path-query" + method: POST + json: + sub_path: "a.b[0].c" + "a": { "b": [{ "c": 3 }] } + response: + status_code: 200 + json: + result: !int "{tavern.request_vars.json.a.b[0].c}" diff --git a/tests/unit/test_helpers.py b/tests/unit/test_helpers.py index a322e967..fd8104a0 100644 --- a/tests/unit/test_helpers.py +++ b/tests/unit/test_helpers.py @@ -8,6 +8,7 @@ import _pytest import pytest import yaml +from box import Box from tavern._core import exceptions from tavern._core.dict_util import _check_and_format_values, format_keys @@ -291,12 +292,10 @@ def test_validate_schema_incorrect(self, nested_response): class TestCheckParseValues: - @pytest.mark.parametrize( - "item", [[134], {"a": 2}, yaml, yaml.load, yaml.SafeLoader] - ) + @pytest.mark.parametrize("item", [yaml, yaml.load, yaml.SafeLoader]) def test_warns_bad_type(self, item): with patch("tavern._core.dict_util.logger.warning") as wmock: - _check_and_format_values("{fd}", {"fd": item}) + _check_and_format_values("{fd}", Box({"fd": item})) wmock.assert_called_with( "Formatting '%s' will result in it being coerced to a string (it is a %s)", @@ -304,13 +303,45 @@ def test_warns_bad_type(self, item): type(item), ) + @pytest.mark.parametrize( + "item", + [ + [134], + {"a": 2}, + ], + ) + def test_warns_bad_type_box(self, item): + box = Box({"fd": item}) + with patch("tavern._core.dict_util.logger.warning") as wmock: + _check_and_format_values("{fd}", box) + + wmock.assert_called_with( + "Formatting '%s' will result in it being coerced to a string (it is a %s)", + "fd", + type(box["fd"]), + ) + @pytest.mark.parametrize("item", [1, "a", 1.3, format_keys("{s}", {"s": 2})]) def test_no_warn_good_type(self, item): with patch("tavern._core.dict_util.logger.warning") as wmock: - _check_and_format_values("{fd}", {"fd": item}) + _check_and_format_values("{fd}", Box({"fd": item})) assert not wmock.called + def test_format_with_array_access(self): + """Test accessing using array indexing format""" + + assert "hello" == _check_and_format_values( + "{a.b.c[0].d}", Box({"a": {"b": {"c": [{"d": "hello"}]}}}) + ) + + def test_format_with_dict_access(self): + """Test accessing using dict indexing format""" + + assert "hello" == _check_and_format_values( + "{a[b].c[0].d}", Box({"a": {"b": {"c": [{"d": "hello"}]}}}) + ) + class TestFormatWithJson: @pytest.mark.parametrize(