From 00dc24916618d39cc66fcc3f68f264fca3bb819d Mon Sep 17 00:00:00 2001 From: GT <77ripdrive@gmail.com> Date: Wed, 6 Jan 2021 15:32:08 +0300 Subject: [PATCH 01/19] fix for tests --- README.md | 16 +++++++++++++++- pyproject.toml | 6 ++++++ tests/features/cucumbers.feature | 2 +- tests/features/zippopo.feature | 7 ++++--- tests/test_json_schema_base.py | 6 +++--- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index e24ab93..0104053 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ pip3 install --user poetry ``` -#### for Windows with Powershell +#### for Windows with Powershell ```sh (Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py -UseBasicParsing).Content | python - @@ -36,3 +36,17 @@ or pre-commit sample-config > .pre-commit-config.yaml pre-commit run -a ``` + +#### To run tests, clone the project and run + +```sh +poetry install +poetry run pytest +``` + +#### To run marked tests with tag @api_service + +```sh +poetry run python -m pytest -k "api_service" + +``` diff --git a/pyproject.toml b/pyproject.toml index 4204d3d..2ad8f1a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,3 +17,9 @@ jsonpath = "^0.82" [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" + +[tool.pytest.ini_options] +markers = [ + "api_service: marks tests for api testing')", + "serial", +] diff --git a/tests/features/cucumbers.feature b/tests/features/cucumbers.feature index 8fbc188..653fa9d 100644 --- a/tests/features/cucumbers.feature +++ b/tests/features/cucumbers.feature @@ -13,7 +13,7 @@ Feature: Cucumber Basket | initial | some | total | | 0 | 3 | 3 | | 3 | 4 | 7 | - | 7 | 5 | 12 | + | 2 | 1 | 3 | Scenario Outline: Remove cucumbers from the basket diff --git a/tests/features/zippopo.feature b/tests/features/zippopo.feature index 06190d6..04fc443 100644 --- a/tests/features/zippopo.feature +++ b/tests/features/zippopo.feature @@ -1,3 +1,4 @@ +@pytest.mark.api_service Feature: Zippopo Instant Answer API As an application developer, I want to get instant answers for search terms via a REST API, @@ -10,6 +11,6 @@ Feature: Zippopo Instant Answer API Then the response contains results for "" Examples: - | country_code | zip_code | place_name | - | us | 12345 | Schenectady | - | nl | 3825 | Vathorst | + | country_code | zip_code | place_name | + | us | 12345 | Schenectady | + | nl | 3825 | Vathorst | diff --git a/tests/test_json_schema_base.py b/tests/test_json_schema_base.py index 4841224..c19803b 100644 --- a/tests/test_json_schema_base.py +++ b/tests/test_json_schema_base.py @@ -1,12 +1,13 @@ import csv import json +import os import pytest from jsonschema import Draft7Validator from jsonschema import validate -path_to_test_data_csv_file = "../asset/data_file.csv" -path_json_schema_file = "../asset/schema_first.json" +path_to_test_data_csv_file = os.getcwd() + "\\asset\\data_file.csv" +path_json_schema_file = os.getcwd() + "\\asset\\schema_first.json" def read_test_data_from_csv(path): @@ -35,7 +36,6 @@ def test_using_csv_with_different_fields(): assert result == True -# @pytest.mark.skip @pytest.mark.parametrize("productId,productName,price,tags", read_test_data_from_csv(path_to_test_data_csv_file)) def test_using_csv_with_different_fields_negative(productId, productName, price, tags): schema = get_data_from_json_schema(path_json_schema_file) From f80edf0d7c9d0a5695474b6ae6e70fa0a8a69fec Mon Sep 17 00:00:00 2001 From: GT <77ripdrive@gmail.com> Date: Wed, 6 Jan 2021 18:49:15 +0300 Subject: [PATCH 02/19] add tags --- tests/features/api.feature | 1 + tests/{models_steps => models}/__init__.py | 0 tests/{models_steps => models}/cucumbers.py | 1 - tests/steps_defs/test_cucumber_steps.py | 22 ++++++++++++--------- tests/test_json_ex_b.py | 22 --------------------- tests/test_json_schema_base.py | 2 ++ 6 files changed, 16 insertions(+), 32 deletions(-) rename tests/{models_steps => models}/__init__.py (100%) rename tests/{models_steps => models}/cucumbers.py (99%) delete mode 100644 tests/test_json_ex_b.py diff --git a/tests/features/api.feature b/tests/features/api.feature index fb2a633..cabf964 100644 --- a/tests/features/api.feature +++ b/tests/features/api.feature @@ -1,3 +1,4 @@ +@pytest.mark.duckDucksSearch Feature: DuckDuckGo Instant Answer API As an application developer, I want to get instant answers for search terms via a REST API, diff --git a/tests/models_steps/__init__.py b/tests/models/__init__.py similarity index 100% rename from tests/models_steps/__init__.py rename to tests/models/__init__.py diff --git a/tests/models_steps/cucumbers.py b/tests/models/cucumbers.py similarity index 99% rename from tests/models_steps/cucumbers.py rename to tests/models/cucumbers.py index 26dbcb3..28bdec3 100644 --- a/tests/models_steps/cucumbers.py +++ b/tests/models/cucumbers.py @@ -1,5 +1,4 @@ class CucumberBasket: - def __init__(self, initial_count=0, max_count=10): if initial_count < 0: raise ValueError("Initial cucumber basket count must not be negative") diff --git a/tests/steps_defs/test_cucumber_steps.py b/tests/steps_defs/test_cucumber_steps.py index b68db8e..4432356 100644 --- a/tests/steps_defs/test_cucumber_steps.py +++ b/tests/steps_defs/test_cucumber_steps.py @@ -1,22 +1,26 @@ -from pytest_bdd import scenarios, parsers, given, when, then +from pytest_bdd import given +from pytest_bdd import parsers +from pytest_bdd import scenarios +from pytest_bdd import then +from pytest_bdd import when -from tests.models_steps.cucumbers import CucumberBasket +from tests.models.cucumbers import CucumberBasket EXTRA_TYPES = { - 'Number': int, + "Number": int, } CONVERTERS = { - 'initial': int, - 'some': int, - 'total': int, + "initial": int, + "some": int, + "total": int, } -scenarios('../features/cucumbers.feature', example_converters=CONVERTERS) +scenarios("../features/cucumbers.feature", example_converters=CONVERTERS) -@given(parsers.cfparse('the basket has "{initial:Number}" cucumbers', extra_types=EXTRA_TYPES), target_fixture='basket') -@given('the basket has "" cucumbers', target_fixture='basket') +@given(parsers.cfparse('the basket has "{initial:Number}" cucumbers', extra_types=EXTRA_TYPES), target_fixture="basket") +@given('the basket has "" cucumbers', target_fixture="basket") def basket(initial): return CucumberBasket(initial_count=initial) diff --git a/tests/test_json_ex_b.py b/tests/test_json_ex_b.py deleted file mode 100644 index 84e00b9..0000000 --- a/tests/test_json_ex_b.py +++ /dev/null @@ -1,22 +0,0 @@ -import json - -schema = { - "id": "int", - "username": "string", - "firstName": "string", - "lastName": "string", - "email": "string", - "password": "string", - "phone": "string", - "userStatus": "int" -} - - -def builder_for_json(dict): - items = sorted(dict.items(), key=lambda item: item[0]) - values = [item[1] for item in items] - json_dict = json.dumps(values) - return json_dict - - -print(builder_for_json(schema)) diff --git a/tests/test_json_schema_base.py b/tests/test_json_schema_base.py index c19803b..1d12bbe 100644 --- a/tests/test_json_schema_base.py +++ b/tests/test_json_schema_base.py @@ -28,6 +28,7 @@ def get_data_from_json_schema(path): payload = {"productId": 1, "productName": "A green door", "productPrice": 12.50, "tags": ["home", "green"]} +@pytest.mark.jsonValidation def test_using_csv_with_different_fields(): with open(path_json_schema_file, "r") as schema_file: schema = json.load(schema_file) @@ -36,6 +37,7 @@ def test_using_csv_with_different_fields(): assert result == True +@pytest.mark.jsonValidation @pytest.mark.parametrize("productId,productName,price,tags", read_test_data_from_csv(path_to_test_data_csv_file)) def test_using_csv_with_different_fields_negative(productId, productName, price, tags): schema = get_data_from_json_schema(path_json_schema_file) From acd692beb4c70b8e02d9eea0c8c586f546877d1b Mon Sep 17 00:00:00 2001 From: GT <77ripdrive@gmail.com> Date: Thu, 7 Jan 2021 18:46:04 +0300 Subject: [PATCH 03/19] Add allure report and logging --- asset/data_file.csv | 3 -- asset/data_test_negative.csv | 4 ++ poetry.lock | 36 +++++++++++++- pyproject.toml | 10 +++- tests/conftest.py | 49 +++++++++++++++++++ tests/features/api.feature | 2 +- tests/steps_defs/conftest.py | 6 --- tests/test_base.py | 2 - tests/test_json_schema_base.py | 49 ++----------------- tests/test_json_schema_negative.py | 38 ++++++++++++++ tests/{test_ex_a.py => test_tuple_as_dict.py} | 13 ++--- 11 files changed, 146 insertions(+), 66 deletions(-) delete mode 100644 asset/data_file.csv create mode 100644 asset/data_test_negative.csv create mode 100644 tests/conftest.py delete mode 100644 tests/steps_defs/conftest.py delete mode 100644 tests/test_base.py create mode 100644 tests/test_json_schema_negative.py rename tests/{test_ex_a.py => test_tuple_as_dict.py} (52%) diff --git a/asset/data_file.csv b/asset/data_file.csv deleted file mode 100644 index 7fce9cf..0000000 --- a/asset/data_file.csv +++ /dev/null @@ -1,3 +0,0 @@ -productId,productName,price,tags -2, apple, 25.6, green -3, banana, 30, grey diff --git a/asset/data_test_negative.csv b/asset/data_test_negative.csv new file mode 100644 index 0000000..6c38c9e --- /dev/null +++ b/asset/data_test_negative.csv @@ -0,0 +1,4 @@ +productId,productName,price,tags +2, apple, two, green +one, banana, 30, grey +4,one,20,green diff --git a/poetry.lock b/poetry.lock index 6d8e694..925018f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,3 +1,29 @@ +[[package]] +name = "allure-pytest" +version = "2.8.29" +description = "Allure pytest integration" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +allure-python-commons = "2.8.29" +pytest = ">=4.5.0" +six = ">=1.9.0" + +[[package]] +name = "allure-python-commons" +version = "2.8.29" +description = "Common module for integrate allure with python-based frameworks" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +attrs = ">=16.0.0" +pluggy = ">=0.4.0" +six = ">=1.9.0" + [[package]] name = "atomicwrites" version = "1.4.0" @@ -274,9 +300,17 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "f0e56220cb63e32c7ad90922df3f89969a94692588873547a70f7cb16917287b" +content-hash = "479b171761defc57787ff7d1fe151bcc3edd5ed1097719cd3744c97b9ad009df" [metadata.files] +allure-pytest = [ + {file = "allure-pytest-2.8.29.tar.gz", hash = "sha256:d37d235cd7c305e697fc90bd93f022f221d13c5a6184c1dec19f8f637092ad16"}, + {file = "allure_pytest-2.8.29-py3-none-any.whl", hash = "sha256:eb021f8610f55b2349a71e8b7d4dffcf08ddd363d44ac08482b628bc09bea5e9"}, +] +allure-python-commons = [ + {file = "allure-python-commons-2.8.29.tar.gz", hash = "sha256:b74c03e793bd4628d8c7644e49737c6ebdc1d883692da34d7547d1ef7ee7c863"}, + {file = "allure_python_commons-2.8.29-py3-none-any.whl", hash = "sha256:e9831bd01f25049a54cf47d7c17ad4b65506d5a35d70571cfaf8c4aa82a30f90"}, +] atomicwrites = [ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, diff --git a/pyproject.toml b/pyproject.toml index 2ad8f1a..2a1806c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,6 +11,7 @@ requests = "^2.25.1" jsonschema = "^3.2.0" pytest-bdd = "^4.0.2" jsonpath = "^0.82" +allure-pytest = "^2.8.29" [tool.poetry.dev-dependencies] @@ -21,5 +22,12 @@ build-backend = "poetry.core.masonry.api" [tool.pytest.ini_options] markers = [ "api_service: marks tests for api testing')", - "serial", + "jsonValidation: marks tests with jsonschema validation", + "duck's_search: marks tests with duckducks api search", +] +filterwarnings = [ + "error", + "ignore::UserWarning", + # note the use of single quote below to denote "raw" strings in TOML + 'ignore:function ham\(\) is deprecated:DeprecationWarning', ] diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..76d1178 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,49 @@ +import csv +import json +import os + +import pytest + +path_to_test_data_csv_file = os.getcwd() + "\\asset\\data_test_negative.csv" +path_json_schema_file = os.getcwd() + "\\asset\\schema_first.json" + + +def read_test_data_from_csv(path): + test_data = [] + with open(path, newline="") as csvfile: + data = csv.reader(csvfile, delimiter=",") + next(data) + for row in data: + test_data.append(row) + return test_data + + +def get_data_from_json_schema(path): + with open(path, "r") as schema_file: + return json.load(schema_file) + + +# Hooks + + +def pytest_bdd_step_error(request, feature, scenario, step, step_func, step_func_args, exception): + print(f"Step failed: {step}") + print(f"Request failed: {request}") + + +@pytest.fixture(scope="session") +def set_base_payload(): + payload = {"productId": 1, "productName": "A green door", "productPrice": 12.50, "tags": ["home", "green"]} + return payload + + +@pytest.fixture(scope="session") +def set_schema(): + schema = get_data_from_json_schema(path_json_schema_file) + return schema + + +@pytest.fixture(scope="session") +def set_test_data_negative(): + negative_test_data = read_test_data_from_csv(path_to_test_data_csv_file) + return negative_test_data diff --git a/tests/features/api.feature b/tests/features/api.feature index cabf964..91c75b4 100644 --- a/tests/features/api.feature +++ b/tests/features/api.feature @@ -1,4 +1,4 @@ -@pytest.mark.duckDucksSearch +@pytest.mark.duck's_search Feature: DuckDuckGo Instant Answer API As an application developer, I want to get instant answers for search terms via a REST API, diff --git a/tests/steps_defs/conftest.py b/tests/steps_defs/conftest.py deleted file mode 100644 index f948701..0000000 --- a/tests/steps_defs/conftest.py +++ /dev/null @@ -1,6 +0,0 @@ -# Hooks - - -def pytest_bdd_step_error(request, feature, scenario, step, step_func, step_func_args, exception): - print(f"Step failed: {step}") - print(f"Request failed: {request}") diff --git a/tests/test_base.py b/tests/test_base.py deleted file mode 100644 index 1f3eb81..0000000 --- a/tests/test_base.py +++ /dev/null @@ -1,2 +0,0 @@ -def test_first_test(): - assert str(1 + 1) == '2' diff --git a/tests/test_json_schema_base.py b/tests/test_json_schema_base.py index 1d12bbe..c2b9e7f 100644 --- a/tests/test_json_schema_base.py +++ b/tests/test_json_schema_base.py @@ -1,51 +1,12 @@ -import csv -import json -import os +import logging import pytest from jsonschema import Draft7Validator -from jsonschema import validate -path_to_test_data_csv_file = os.getcwd() + "\\asset\\data_file.csv" -path_json_schema_file = os.getcwd() + "\\asset\\schema_first.json" - - -def read_test_data_from_csv(path): - test_data = [] - with open(path, newline="") as csvfile: - data = csv.reader(csvfile, delimiter=",") - next(data) - for row in data: - test_data.append(row) - return test_data - - -def get_data_from_json_schema(path): - with open(path, "r") as schema_file: - return json.load(schema_file) - - -payload = {"productId": 1, "productName": "A green door", "productPrice": 12.50, "tags": ["home", "green"]} - - -@pytest.mark.jsonValidation -def test_using_csv_with_different_fields(): - with open(path_json_schema_file, "r") as schema_file: - schema = json.load(schema_file) - result = Draft7Validator(schema).is_valid(payload) - print(result) - assert result == True +LOGGER = logging.getLogger(__name__) @pytest.mark.jsonValidation -@pytest.mark.parametrize("productId,productName,price,tags", read_test_data_from_csv(path_to_test_data_csv_file)) -def test_using_csv_with_different_fields_negative(productId, productName, price, tags): - schema = get_data_from_json_schema(path_json_schema_file) - payload.update({"productId": productId}) - payload.update({"productName": productName}) - payload.update({"productPrice": price}) - payload.update({"tags": tags}) - try: - validate(payload, schema) - except: - print(f" - Validation error") +def test_using_csv_with_different_fields(set_schema, set_base_payload): + result = Draft7Validator(set_schema).is_valid(set_base_payload) + assert result == True, LOGGER.info("Schema is valid") diff --git a/tests/test_json_schema_negative.py b/tests/test_json_schema_negative.py new file mode 100644 index 0000000..393d619 --- /dev/null +++ b/tests/test_json_schema_negative.py @@ -0,0 +1,38 @@ +import json +import logging +import os + +import allure +import pytest +from jsonschema import ValidationError +from jsonschema import validate + +LOGGER = logging.getLogger(__name__) +path_json_schema_file = os.getcwd() + "\\asset\\schema_first.json" + + +def get_data_from_json_schema(path): + with open(path, "r") as schema_file: + return json.load(schema_file) + + +@allure.feature("Jsonschema validation") +@allure.story("Validation with incorrect value") +@pytest.mark.jsonValidation +@pytest.mark.parametrize( + "productId,productName,price,tags", + [(2, "apple", "two", ["green", "grey"]), ("one", "banana", 30, []), (4, "one", 20, "green")], +) +def test_using_csv_with_different_fields_negative(productId, productName, price, tags): + payload = {"productId": None, "productName": None, "productPrice": None, "tags": None} + with allure.step("insert nit correct value "): + payload.update({"productId": productId}) + payload.update({"productName": productName}) + payload.update({"productPrice": price}) + payload.update({"tags": tags}) + schema = get_data_from_json_schema(path_json_schema_file) + with allure.step("Validation with base JsonSchema"): + with pytest.raises(ValidationError) as e: + validate(payload, schema=schema) + assert e.value.__module__.strip("ValidationError") == "jsonschema.exceptions" + LOGGER.info(e.value) diff --git a/tests/test_ex_a.py b/tests/test_tuple_as_dict.py similarity index 52% rename from tests/test_ex_a.py rename to tests/test_tuple_as_dict.py index c832838..7888836 100644 --- a/tests/test_ex_a.py +++ b/tests/test_tuple_as_dict.py @@ -1,23 +1,20 @@ from collections import namedtuple -Task = namedtuple('Task', ['summary', 'owner', 'done', 'id']) +Task = namedtuple("Task", ["summary", "owner", "done", "id"]) Task.__new__.__defaults__ = (None, None, False, None) def test_asdict(): """_asdict() should return a dictionary.""" - t_task = Task('do something', 'Todos', True, 22) + t_task = Task("do something", "Todos", True, 22) t_dict = t_task._asdict() - expected = {'summary': 'do something', - 'owner': 'Todos', - 'done': True, - 'id': 22} + expected = {"summary": "do something", "owner": "Todos", "done": True, "id": 22} assert t_dict == expected def test_replace(): """replace() should change passed in fields.""" - t_before = Task('finish book', 'Ioan', False, 20) + t_before = Task("finish book", "Ioan", False, 20) t_after = t_before._replace(id=10, done=True) - t_expected = Task('finish book', 'Ioan', True, 10) + t_expected = Task("finish book", "Ioan", True, 10) assert t_after == t_expected From 038cf796d3a4b0ff520e849e5e313268deb94911 Mon Sep 17 00:00:00 2001 From: GT <77ripdrive@gmail.com> Date: Thu, 7 Jan 2021 19:18:08 +0300 Subject: [PATCH 04/19] Add github actions --- .github/workflows/poetry.yml | 34 ++++++++++++++++++++++++++++++++++ poetry.lock | 17 ++++++++++++++++- pyproject.toml | 1 + 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/poetry.yml diff --git a/.github/workflows/poetry.yml b/.github/workflows/poetry.yml new file mode 100644 index 0000000..9e15cbe --- /dev/null +++ b/.github/workflows/poetry.yml @@ -0,0 +1,34 @@ +on: + push: + branches: + - master + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-python@v1 + with: + python-version: ^3.9 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install --user poetry + poetry install + + - name: Test with pytest + run: | + poetry run pytest --alluredir=allure-results + - name: Allure results + uses: simple-elf/allure-report-action@master + if: always() + id: allure-report + with: + allure_results: allure-results + allure_report: allure-report + path: ./artifacts/*.* + allure_history: allure-history diff --git a/poetry.lock b/poetry.lock index 925018f..1ea6ab7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -250,6 +250,17 @@ py = "*" pytest = ">=4.3" six = ">=1.9.0" +[[package]] +name = "pytest-github-actions-annotate-failures" +version = "0.1.1" +description = "pytest plugin to annotate failed tests with a workflow command for GitHub Actions" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +pytest = ">=4.0.0" + [[package]] name = "requests" version = "2.25.1" @@ -300,7 +311,7 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "479b171761defc57787ff7d1fe151bcc3edd5ed1097719cd3744c97b9ad009df" +content-hash = "8720fc81b4bf7430c6dd52c0d1d00e7579d790c9239e86ef35a9619d139d6a45" [metadata.files] allure-pytest = [ @@ -422,6 +433,10 @@ pytest-bdd = [ {file = "pytest-bdd-4.0.2.tar.gz", hash = "sha256:982489f2f036c7561affe4eeb5b392a37e1ace2a9f260cad747b1c8119e63cfd"}, {file = "pytest_bdd-4.0.2-py2.py3-none-any.whl", hash = "sha256:74ea5a147ea558c99ae83d838e6acbe5c9e6843884a958f8231615d96838733d"}, ] +pytest-github-actions-annotate-failures = [ + {file = "pytest-github-actions-annotate-failures-0.1.1.tar.gz", hash = "sha256:66445649ac8c0e1a05475faeda1679f0609a77861f9c620f68429cf6daf4ddc2"}, + {file = "pytest_github_actions_annotate_failures-0.1.1-py2.py3-none-any.whl", hash = "sha256:e997068fff4909331c3b5f4e2c7868535aa4c62cb71b96b9d9724733f80bba26"}, +] requests = [ {file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"}, {file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"}, diff --git a/pyproject.toml b/pyproject.toml index 2a1806c..7d707eb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,6 +12,7 @@ jsonschema = "^3.2.0" pytest-bdd = "^4.0.2" jsonpath = "^0.82" allure-pytest = "^2.8.29" +pytest-github-actions-annotate-failures = "^0.1.1" [tool.poetry.dev-dependencies] From 82ea4d54fef3ea495ae5ce5b904ba61ab5ebcd7c Mon Sep 17 00:00:00 2001 From: Gleb <77ripdrive@gmail.com> Date: Thu, 7 Jan 2021 19:26:03 +0300 Subject: [PATCH 05/19] Update poetry.yml --- .github/workflows/poetry.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/poetry.yml b/.github/workflows/poetry.yml index 9e15cbe..e092c83 100644 --- a/.github/workflows/poetry.yml +++ b/.github/workflows/poetry.yml @@ -16,7 +16,6 @@ jobs: - name: Install dependencies run: | - python -m pip install --upgrade pip pip install --user poetry poetry install From 0526cddf75047ca7a66e1746235f376772a40537 Mon Sep 17 00:00:00 2001 From: GT <77ripdrive@gmail.com> Date: Thu, 7 Jan 2021 19:54:24 +0300 Subject: [PATCH 06/19] fix for actions --- .github/workflows/poetry.yml | 7 +++++-- .gitignore | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/poetry.yml b/.github/workflows/poetry.yml index e092c83..c13f776 100644 --- a/.github/workflows/poetry.yml +++ b/.github/workflows/poetry.yml @@ -16,12 +16,15 @@ jobs: - name: Install dependencies run: | + python -m pip install --upgrade pip pip install --user poetry poetry install - name: Test with pytest - run: | - poetry run pytest --alluredir=allure-results + if: always() + run: poetry run pytest --alluredir=allure-results + continue-on-error: true + - name: Allure results uses: simple-elf/allure-report-action@master if: always() diff --git a/.gitignore b/.gitignore index ae61a53..aada650 100644 --- a/.gitignore +++ b/.gitignore @@ -107,3 +107,5 @@ venv.bak/ *.iml !.gitignore !.pre-commit-config.yaml + +.allure-results/ From 8644834f2ffd5d4f8cd24e98279896cb82934bdb Mon Sep 17 00:00:00 2001 From: GT <77ripdrive@gmail.com> Date: Thu, 7 Jan 2021 20:12:52 +0300 Subject: [PATCH 07/19] fix for actions --- .github/workflows/poetry.yml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/poetry.yml b/.github/workflows/poetry.yml index c13f776..66bc0aa 100644 --- a/.github/workflows/poetry.yml +++ b/.github/workflows/poetry.yml @@ -17,12 +17,19 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install --user poetry - poetry install - - name: Test with pytest + - name: Configure poetry + shell: bash + run: python -m poetry config virtualenvs.in-project true + + - name: Install dependencies + shell: bash + run: python -m poetry install + + - name: Run pytest + shell: bash if: always() - run: poetry run pytest --alluredir=allure-results + run: python -m poetry run python -m pytest -v tests --alluredir=allure-results continue-on-error: true - name: Allure results From 8241626e673be9b9ef4c246348e2edb68118a0a4 Mon Sep 17 00:00:00 2001 From: GT <77ripdrive@gmail.com> Date: Thu, 7 Jan 2021 20:45:40 +0300 Subject: [PATCH 08/19] fix for path --- .github/workflows/poetry.yml | 7 +------ tests/conftest.py | 9 +-------- tests/test_json_schema_negative.py | 2 +- 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/.github/workflows/poetry.yml b/.github/workflows/poetry.yml index 66bc0aa..a7f04fd 100644 --- a/.github/workflows/poetry.yml +++ b/.github/workflows/poetry.yml @@ -16,11 +16,7 @@ jobs: - name: Install dependencies run: | - python -m pip install --upgrade pip - - - name: Configure poetry - shell: bash - run: python -m poetry config virtualenvs.in-project true + pip install --user poetry - name: Install dependencies shell: bash @@ -30,7 +26,6 @@ jobs: shell: bash if: always() run: python -m poetry run python -m pytest -v tests --alluredir=allure-results - continue-on-error: true - name: Allure results uses: simple-elf/allure-report-action@master diff --git a/tests/conftest.py b/tests/conftest.py index 76d1178..7ebd4fb 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,8 +4,7 @@ import pytest -path_to_test_data_csv_file = os.getcwd() + "\\asset\\data_test_negative.csv" -path_json_schema_file = os.getcwd() + "\\asset\\schema_first.json" +path_json_schema_file = os.getcwd() + "/asset/schema_first.json" def read_test_data_from_csv(path): @@ -41,9 +40,3 @@ def set_base_payload(): def set_schema(): schema = get_data_from_json_schema(path_json_schema_file) return schema - - -@pytest.fixture(scope="session") -def set_test_data_negative(): - negative_test_data = read_test_data_from_csv(path_to_test_data_csv_file) - return negative_test_data diff --git a/tests/test_json_schema_negative.py b/tests/test_json_schema_negative.py index 393d619..3ac85dd 100644 --- a/tests/test_json_schema_negative.py +++ b/tests/test_json_schema_negative.py @@ -8,7 +8,7 @@ from jsonschema import validate LOGGER = logging.getLogger(__name__) -path_json_schema_file = os.getcwd() + "\\asset\\schema_first.json" +path_json_schema_file = os.getcwd() + "/asset/schema_first.json" def get_data_from_json_schema(path): From 52d3866ae713f5b5d44aa19854f7d34e323013fb Mon Sep 17 00:00:00 2001 From: GT <77ripdrive@gmail.com> Date: Thu, 7 Jan 2021 22:10:02 +0300 Subject: [PATCH 09/19] add gitlab ci --- .gitlab-ci.yml | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..9599f3d --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,69 @@ +stages: + - testing # Tests run + - history_save # Save allure history + - reports # Report generation + - deploy # Report publication in gitlab pages + +docker_job: + stage: testing + tags: + - docker + image: python:3.9-alpine + before_script: + - pip install --user poetry + - python -m poetry install + script: + - python -m poetry run python -m pytest -v tests --alluredir=./allure-results tests/ + + allow_failure: true + artifacts: + when: always + paths: + - ./allure-results + expire_in: 1 day + +history_job: + stage: history_save + tags: + - docker + image: storytel/alpine-bash-curl + script: +# https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html#downloading-artifacts + - 'curl --location --output artifacts.zip "https://gitlab.com/api///-/jobs/artifacts/master/download?job=pages&job_token=$CI_JOB_TOKEN"' + - apk add unzip + - unzip artifacts.zip + - chmod -R 777 public + - cp -r ./public/history ./allure-results + allow_failure: true + artifacts: + paths: + - ./allure-results + expire_in: 1 day + rules: + - when: always + +allure_job: + stage: reports + tags: + - docker + image: frankescobar/allure-docker-service + script: + - allure generate -c ./allure-results -o ./allure-report + artifacts: + paths: + - ./allure-results + - ./allure-report + expire_in: 1 day + rules: + - when: always + +pages: + stage: deploy + script: + - mkdir public + - mv ./allure-report/* public + artifacts: + paths: + - public + rules: + - when: always From da75a11ebfc1e0a23cf418dcb172794671684a74 Mon Sep 17 00:00:00 2001 From: Gleb <77ripdrive@gmail.com> Date: Thu, 7 Jan 2021 23:00:31 +0300 Subject: [PATCH 10/19] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 0104053..44e8399 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![PYTEST](https://img.shields.io/badge/pytest-v%200.1-green)](https://img.shields.io/badge/pytest-v%200.1-green) + ## An example of initializing a Python project from scratch ### Dependency management with [Poetry-Python](https://python-poetry.org/docs/) From 8ad0c51c0b7352d03dcf333ff54905c15aad0d5d Mon Sep 17 00:00:00 2001 From: Gleb <77ripdrive@gmail.com> Date: Thu, 7 Jan 2021 23:04:26 +0300 Subject: [PATCH 11/19] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 44e8399..198d69b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +![.github/workflows/poetry.yml](https://github.com/77ripdrive/Python_sandbox/workflows/.github/workflows/poetry.yml/badge.svg) [![PYTEST](https://img.shields.io/badge/pytest-v%200.1-green)](https://img.shields.io/badge/pytest-v%200.1-green) ## An example of initializing a Python project from scratch From 20e1733c0af7f49904a7be90febf72c0bdfc86e0 Mon Sep 17 00:00:00 2001 From: GT <77ripdrive@gmail.com> Date: Fri, 8 Jan 2021 19:35:59 +0300 Subject: [PATCH 12/19] add cerberus and assertpy --- poetry.lock | 24 +++++++++++++++++++++- pyproject.toml | 2 ++ tests/test_cerberus_assertpy.py | 35 +++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 tests/test_cerberus_assertpy.py diff --git a/poetry.lock b/poetry.lock index 1ea6ab7..8b7c8d6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -24,6 +24,14 @@ attrs = ">=16.0.0" pluggy = ">=0.4.0" six = ">=1.9.0" +[[package]] +name = "assertpy" +version = "1.1" +description = "Simple assertion library for unit testing in python with a fluent API" +category = "main" +optional = false +python-versions = "*" + [[package]] name = "atomicwrites" version = "1.4.0" @@ -46,6 +54,14 @@ docs = ["furo", "sphinx", "zope.interface"] tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"] +[[package]] +name = "cerberus" +version = "1.3.2" +description = "Lightweight, extensible schema and data validation tool for Python dictionaries." +category = "main" +optional = false +python-versions = ">=2.7" + [[package]] name = "certifi" version = "2020.12.5" @@ -311,7 +327,7 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "8720fc81b4bf7430c6dd52c0d1d00e7579d790c9239e86ef35a9619d139d6a45" +content-hash = "0ec99c07802eefdfb1ce706b6bc2eaddb810f5482796f8fe858b52f150b6047d" [metadata.files] allure-pytest = [ @@ -322,6 +338,9 @@ allure-python-commons = [ {file = "allure-python-commons-2.8.29.tar.gz", hash = "sha256:b74c03e793bd4628d8c7644e49737c6ebdc1d883692da34d7547d1ef7ee7c863"}, {file = "allure_python_commons-2.8.29-py3-none-any.whl", hash = "sha256:e9831bd01f25049a54cf47d7c17ad4b65506d5a35d70571cfaf8c4aa82a30f90"}, ] +assertpy = [ + {file = "assertpy-1.1.tar.gz", hash = "sha256:acc64329934ad71a3221de185517a43af33e373bb44dc05b5a9b174394ef4833"}, +] atomicwrites = [ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, @@ -330,6 +349,9 @@ attrs = [ {file = "attrs-20.3.0-py2.py3-none-any.whl", hash = "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6"}, {file = "attrs-20.3.0.tar.gz", hash = "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"}, ] +cerberus = [ + {file = "Cerberus-1.3.2.tar.gz", hash = "sha256:302e6694f206dd85cb63f13fd5025b31ab6d38c99c50c6d769f8fa0b0f299589"}, +] certifi = [ {file = "certifi-2020.12.5-py2.py3-none-any.whl", hash = "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"}, {file = "certifi-2020.12.5.tar.gz", hash = "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c"}, diff --git a/pyproject.toml b/pyproject.toml index 7d707eb..9deddd3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,8 @@ pytest-bdd = "^4.0.2" jsonpath = "^0.82" allure-pytest = "^2.8.29" pytest-github-actions-annotate-failures = "^0.1.1" +Cerberus = "^1.3.2" +assertpy = "^1.1" [tool.poetry.dev-dependencies] diff --git a/tests/test_cerberus_assertpy.py b/tests/test_cerberus_assertpy.py new file mode 100644 index 0000000..315555b --- /dev/null +++ b/tests/test_cerberus_assertpy.py @@ -0,0 +1,35 @@ +from dataclasses import dataclass + +import pytest +from assertpy import assert_that +from cerberus import Validator + + +@dataclass +class Person: + name: str + age: int + + +class PersonValidator(Validator): + def validate_person(self, obj): + return self.validate(obj.__dict__) + + +schema = {"name": {"type": "string", "minlength": 2}, "age": {"type": "integer", "min": 18, "max": 65}} + + +@pytest.mark.json_validation_cerberus +def test_cerberus_validator_base(set_schema, set_base_payload): + v = PersonValidator(schema) + person = Person("John Doe", 20) + result = v.validate_person(person) + assert_that(result, description=v.errors).is_true() + + +@pytest.mark.json_validation_cerberus +def test_cerberus_validator_negative(set_schema, set_base_payload): + v = PersonValidator(schema) + children = Person("Zoe Doe", 2) + result = v.validate_person(children) + assert_that(result, description=v.errors).is_false() From c64ce1071e5c5d2e23e51fee2e380e17d4f6121c Mon Sep 17 00:00:00 2001 From: GT <77ripdrive@gmail.com> Date: Fri, 8 Jan 2021 20:25:48 +0300 Subject: [PATCH 13/19] add main config --- config.py | 2 ++ tests/steps_defs/test_api_steps.py | 6 +++--- tests/steps_defs/test_zippo_steps.py | 5 +++-- 3 files changed, 8 insertions(+), 5 deletions(-) create mode 100644 config.py diff --git a/config.py b/config.py new file mode 100644 index 0000000..679ca7d --- /dev/null +++ b/config.py @@ -0,0 +1,2 @@ +BASE_URL_ZIPPOPO = "http://api.zippopotam.us" +DUCKDUCKGO_API = "https://api.duckduckgo.com/" diff --git a/tests/steps_defs/test_api_steps.py b/tests/steps_defs/test_api_steps.py index 58f8541..7819b71 100644 --- a/tests/steps_defs/test_api_steps.py +++ b/tests/steps_defs/test_api_steps.py @@ -5,11 +5,11 @@ from pytest_bdd import then # Shared Variables - -DUCKDUCKGO_API = "https://api.duckduckgo.com/" +from config import DUCKDUCKGO_API # Scenarios + scenarios("../features/api.feature", example_converters=dict(phrase=str)) @@ -19,7 +19,7 @@ @given('the DuckDuckGo API is queried with ""', target_fixture="ddg_response") def ddg_response(phrase): params = {"q": phrase, "format": "json"} - response = requests.get(DUCKDUCKGO_API, params=params) + response = requests.get({DUCKDUCKGO_API}, params=params) return response diff --git a/tests/steps_defs/test_zippo_steps.py b/tests/steps_defs/test_zippo_steps.py index e3372a0..4df1e01 100644 --- a/tests/steps_defs/test_zippo_steps.py +++ b/tests/steps_defs/test_zippo_steps.py @@ -5,6 +5,8 @@ from pytest_bdd import scenarios from pytest_bdd import then +from config import BASE_URL_ZIPPOPO + CONVERTERS = {"country_code": str, "zip_code": int, "place_name": str} scenarios("../features/zippopo.feature", example_converters=CONVERTERS) @@ -12,8 +14,7 @@ @given('the Zippopotam API is queried with "" and ""', target_fixture="ddg_response") def ddg_response(country_code, zip_code): - url = "http://api.zippopotam.us/{}/{}".format(country_code, zip_code) - response = requests.get(url) + response = requests.get(f"{BASE_URL_ZIPPOPO}/{country_code}/{zip_code}") return response From 2855c9705b06c1618f285a5b159f189d6e484fff Mon Sep 17 00:00:00 2001 From: GT <77ripdrive@gmail.com> Date: Fri, 8 Jan 2021 20:35:54 +0300 Subject: [PATCH 14/19] fix for allure-report in github --- .github/workflows/poetry.yml | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/.github/workflows/poetry.yml b/.github/workflows/poetry.yml index a7f04fd..a7a2da2 100644 --- a/.github/workflows/poetry.yml +++ b/.github/workflows/poetry.yml @@ -27,12 +27,28 @@ jobs: if: always() run: python -m poetry run python -m pytest -v tests --alluredir=allure-results - - name: Allure results + - name: Get Allure history + uses: actions/checkout@v2 + if: always() + continue-on-error: true + with: + ref: gh-pages + path: gh-pages + + - name: Allure Report action from marketplace uses: simple-elf/allure-report-action@master if: always() id: allure-report with: - allure_results: allure-results - allure_report: allure-report - path: ./artifacts/*.* - allure_history: allure-history + allure_results: allure-results + gh_pages: gh-pages + allure_report: allure-report + allure_history: allure-history + + - name: Deploy report to Github Pages + if: always() + uses: peaceiris/actions-gh-pages@v2 + env: + PERSONAL_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PUBLISH_BRANCH: gh-pages + PUBLISH_DIR: allure-history From 0ade1442faf6bc59abffec3a83b1420d9ad0c108 Mon Sep 17 00:00:00 2001 From: GT <77ripdrive@gmail.com> Date: Fri, 8 Jan 2021 21:04:19 +0300 Subject: [PATCH 15/19] fix for @tag duckduck_search --- tests/features/api.feature | 2 +- tests/steps_defs/test_api_steps.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/features/api.feature b/tests/features/api.feature index 91c75b4..3f47506 100644 --- a/tests/features/api.feature +++ b/tests/features/api.feature @@ -1,4 +1,4 @@ -@pytest.mark.duck's_search +@pytest.mark.duckduck_search Feature: DuckDuckGo Instant Answer API As an application developer, I want to get instant answers for search terms via a REST API, diff --git a/tests/steps_defs/test_api_steps.py b/tests/steps_defs/test_api_steps.py index 7819b71..50ffccc 100644 --- a/tests/steps_defs/test_api_steps.py +++ b/tests/steps_defs/test_api_steps.py @@ -19,7 +19,7 @@ @given('the DuckDuckGo API is queried with ""', target_fixture="ddg_response") def ddg_response(phrase): params = {"q": phrase, "format": "json"} - response = requests.get({DUCKDUCKGO_API}, params=params) + response = requests.get(f"{DUCKDUCKGO_API}", params=params) return response From 359913af182be46d603d519bc623972d9b14fdd0 Mon Sep 17 00:00:00 2001 From: Gleb <77ripdrive@gmail.com> Date: Fri, 8 Jan 2021 21:19:07 +0300 Subject: [PATCH 16/19] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 198d69b..0387472 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ ![.github/workflows/poetry.yml](https://github.com/77ripdrive/Python_sandbox/workflows/.github/workflows/poetry.yml/badge.svg) [![PYTEST](https://img.shields.io/badge/pytest-v%200.1-green)](https://img.shields.io/badge/pytest-v%200.1-green) +#### The test report can be found here [Allure report](https://77ripdrive.github.io/Python_sandbox.github.io/) + ## An example of initializing a Python project from scratch ### Dependency management with [Poetry-Python](https://python-poetry.org/docs/) From 968f16895d9d37dbcac1600b86c3ac9077c09afc Mon Sep 17 00:00:00 2001 From: GT <77ripdrive@gmail.com> Date: Sat, 9 Jan 2021 13:56:01 +0300 Subject: [PATCH 17/19] add utils for read test data --- tests/conftest.py | 31 +++++-------------------------- tests/test_json_schema_base.py | 12 ++++++------ tests/utils/__init__.py | 0 tests/utils/utils.py | 30 ++++++++++++++++++++++++++++++ 4 files changed, 41 insertions(+), 32 deletions(-) create mode 100644 tests/utils/__init__.py create mode 100644 tests/utils/utils.py diff --git a/tests/conftest.py b/tests/conftest.py index 7ebd4fb..2584ed2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,30 +1,9 @@ -import csv -import json -import os - import pytest -path_json_schema_file = os.getcwd() + "/asset/schema_first.json" - - -def read_test_data_from_csv(path): - test_data = [] - with open(path, newline="") as csvfile: - data = csv.reader(csvfile, delimiter=",") - next(data) - for row in data: - test_data.append(row) - return test_data - - -def get_data_from_json_schema(path): - with open(path, "r") as schema_file: - return json.load(schema_file) - - -# Hooks +from tests.utils.utils import read_data_from_json_file +# bdd hooks def pytest_bdd_step_error(request, feature, scenario, step, step_func, step_func_args, exception): print(f"Step failed: {step}") print(f"Request failed: {request}") @@ -33,10 +12,10 @@ def pytest_bdd_step_error(request, feature, scenario, step, step_func, step_func @pytest.fixture(scope="session") def set_base_payload(): payload = {"productId": 1, "productName": "A green door", "productPrice": 12.50, "tags": ["home", "green"]} - return payload + yield payload @pytest.fixture(scope="session") def set_schema(): - schema = get_data_from_json_schema(path_json_schema_file) - return schema + schema = read_data_from_json_file("schema_first.json") + yield schema diff --git a/tests/test_json_schema_base.py b/tests/test_json_schema_base.py index c2b9e7f..e48a045 100644 --- a/tests/test_json_schema_base.py +++ b/tests/test_json_schema_base.py @@ -1,12 +1,12 @@ -import logging - +import allure import pytest from jsonschema import Draft7Validator -LOGGER = logging.getLogger(__name__) - +@allure.feature("Jsonschema validation") +@allure.story("Validation with correct payload value") @pytest.mark.jsonValidation def test_using_csv_with_different_fields(set_schema, set_base_payload): - result = Draft7Validator(set_schema).is_valid(set_base_payload) - assert result == True, LOGGER.info("Schema is valid") + with allure.step("Validation with correct JsonSchema"): + result = Draft7Validator(set_schema).is_valid(set_base_payload) + assert result == True diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/utils/utils.py b/tests/utils/utils.py new file mode 100644 index 0000000..1c91a12 --- /dev/null +++ b/tests/utils/utils.py @@ -0,0 +1,30 @@ +import csv +import json +from pathlib import Path + +BASE_PATH = Path.cwd().joinpath("asset") + + +def read_data_from_json_file(file_name): + path = get_path(file_name) + with path.open(mode="r") as schema_file: + return json.load(schema_file) + + +def read_data_from_csv_file(file_name): + test_data = [] + path = get_path(file_name) + with path.open(mode="r") as csvfile: + data = csv.reader(csvfile, delimiter=",") + next(data) + for row in data: + test_data.append(row) + return test_data + + +def get_path(file_name): + if ".json" in file_name: + path = BASE_PATH.joinpath(file_name) + elif ".csv" in file_name: + path = BASE_PATH.joinpath(file_name) + return path From 63996710a6daaedc6dd907d4121ac29de936687f Mon Sep 17 00:00:00 2001 From: Gleb <77ripdrive@gmail.com> Date: Sat, 9 Jan 2021 15:41:38 +0300 Subject: [PATCH 18/19] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0387472..385b6f7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ![.github/workflows/poetry.yml](https://github.com/77ripdrive/Python_sandbox/workflows/.github/workflows/poetry.yml/badge.svg) -[![PYTEST](https://img.shields.io/badge/pytest-v%200.1-green)](https://img.shields.io/badge/pytest-v%200.1-green) +[![PYTEST](https://img.shields.io/badge/pytest-v%206.2.1-green)](https://img.shields.io/badge/pytest-v%206.2.1-green) #### The test report can be found here [Allure report](https://77ripdrive.github.io/Python_sandbox.github.io/) From cfe5f45cc3cbe35d51df3f8c46081333e599c365 Mon Sep 17 00:00:00 2001 From: Gleb Telesh Date: Wed, 30 Jun 2021 14:46:26 +0300 Subject: [PATCH 19/19] add method --- tests/utils/utils.py | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/tests/utils/utils.py b/tests/utils/utils.py index 1c91a12..00fb96e 100644 --- a/tests/utils/utils.py +++ b/tests/utils/utils.py @@ -1,8 +1,12 @@ import csv import json +import os from pathlib import Path +import jsonpath as jsonpath + BASE_PATH = Path.cwd().joinpath("asset") +test_data = [] def read_data_from_json_file(file_name): @@ -12,7 +16,7 @@ def read_data_from_json_file(file_name): def read_data_from_csv_file(file_name): - test_data = [] + path = get_path(file_name) with path.open(mode="r") as csvfile: data = csv.reader(csvfile, delimiter=",") @@ -28,3 +32,36 @@ def get_path(file_name): elif ".csv" in file_name: path = BASE_PATH.joinpath(file_name) return path + + +def read_data(file): + """Чтение csv файла в list of jsons""" + with open(f'{file}', "r", encoding='utf-8') as f: + dict_reader = csv.DictReader(f, delimiter=";") + for row in dict_reader: + dict_from_csv = dict(row) + test_data.append(dict_from_csv) + + return test_data + + +def write_scv_to_list_dict_file(file, name): + """ Чтение данных из csv в корне проекта и запись в файл как list of jsons """ + dicts = read_data(file) + file_name = os.getcwd() + f"/assets/assets_{name}.py" + with open(file_name, "a+", encoding="utf-8") as f: + json.dump(dicts, f, ensure_ascii=False, sort_keys=True, indent=4) + + +def search_data_from_json_to_list_of_jsons(base_file: json, jsonpath_expression: str): + """метод для получения list required полей из openApi + в зависимости от endpoint запроса и статуса response""" + list_jsons = jsonpath.jsonpath(base_file, jsonpath_expression) + return list_jsons + + +def write_json_file(base_name, json_object: json): + """Too do """ + file_name = os.getcwd() + f"/assets/{base_name}.json" + with open(file_name, "a+", encoding="utf-8") as f: + json.dump(json_object, f, ensure_ascii=False, sort_keys=True, indent=4) \ No newline at end of file