partest


Namepartest JSON
Version 0.1.31 PyPI version JSON
download
home_pagehttps://github.com/Dec01/partest
SummaryThis is a module for the rapid implementation of test cases with coverage tracking. This module contains a call counter for specific endpoints and their methods. As well as the function of determining the types of tests that need to be counted.
upload_time2024-12-09 09:38:14
maintainerNone
docs_urlNone
authordec01
requires_python>=3.8
licenseNone
keywords autotest partest test coverage
VCS
bugtrack_url
requirements attrs certifi charset-normalizer Faker idna iniconfig jsonschema packaging pluggy py pyparsing pyrsistent pytest python-dateutil requests six tomli urllib3 pytest-repeat pytest-asyncio pydantic pytest-rerunfailures ruff allure-pytest allure-python-commons httpx swagger-parser matplotlib pyyaml
Travis-CI No Travis.
coveralls test coverage No coveralls.
            ## HI!

This is a framework for API autotests with coverage assessment. Detailed instructions in the process of writing. It is better to check with the author how to use it. Tools are used:

* pytest
* httpx
* allure

Files are required for specific work:

**conftest.py** - it must have a fixture's inside:

```commandline
@pytest.fixture(scope="session")
def api_client(domain):
    return ApiClient(domain=domain)
```
```commandline
@pytest.fixture(scope='session', autouse=True)
def clear_call_data():
    """Фикстура для очистки данных перед запуском тестов."""
    global call_count, call_type
    api_call_storage.call_count.clear()
    api_call_storage.call_type.clear()
    yield
```

**confpartest.py** - It must have variables inside:

```
swagger_files = {
    'test1': ['local', '../public/swagger/app-openapi.yaml'],
    'test2': ['local', '../public/swagger/app-openapi2.yaml'],
    'test3': ['url', 'https://url.ru']
}

test_types_coverage = ['default', '405', 'param']
```

The project must have a test that displays information about the coverage in allure. The name of it **test_zorro.py**:

```commandline

    async def test_display_final_call_counts(self):
        report_lines = []
        total_coverage_percentage = 0
        total_endpoints = 0
        total_calls_excluding_generation = 0

        for (method, endpoint, description), count in call_count.items():
            types = set(call_type[(method, endpoint, description)])
            total_endpoints += 1

            # Подсчет вызовов, исключая тип 'generation_data'
            if 'generation_data' not in types:
                total_calls_excluding_generation += count

            # Проверка на наличие обязательных типов тестов
            coverage_status = "Недостаточное покрытие ❌"
            matched_types = set(types).intersection(types)  
            count_matched = len(matched_types)

            # Логика для определения статуса покрытия и расчета процента
            if count_matched == len(types):  # Все типы присутствуют
                coverage_status = "Покрытие выполнено ✅"
                total_coverage_percentage += 100
            elif count_matched == 2:  
                coverage_status = "Покрытие выполнено на 66% 🔔"
                total_coverage_percentage += 66
            elif count_matched == 1:  
                coverage_status = "Покрытие выполнено на 33% ❌"
                total_coverage_percentage += 33
            else: 
                coverage_status = "Недостаточное покрытие ❌"
                total_coverage_percentage += 0

            report_line = (
                f"\n{description}\nЭндпоинт: {endpoint}\nМетод: {method} | "
                f"Обращений: {count}, Типы тестов: {', '.join(types)}\n{coverage_status}\n"
            )
            report_lines.append(report_line)

        # Вычисление общего процента покрытия
        if total_endpoints > 0:
            average_coverage_percentage = total_coverage_percentage / total_endpoints
        else:
            average_coverage_percentage = 0

        border = "*" * 50
        summary = f"{border}\nОбщий процент покрытия: {average_coverage_percentage:.2f}%\nОбщее количество вызовов (исключая 'generation_data'): {total_calls_excluding_generation}\n{border}\n"

        # Добавляем сводку в начало отчета
        report_lines.insert(0, summary)

        create_chart(call_count)

        with open('api_call_counts.png', 'rb') as f:
            allure.attach(f.read(), name='Оценка покрытия', attachment_type=allure.attachment_type.PNG)

        allure.attach("\n".join(report_lines), name='Отчет по вызовам API', attachment_type=allure.attachment_type.TEXT)

        assert True

```


What does the test look like:

```commandline
    async def test_get(self, api_client):
        endpoint = 'https://ya.ru'
        response = await api_client.make_request(
            'GET',
            endpoint,
            params='limit=1',
            expected_status_code=200,
            validate_model=Models.ValidateGet,
            type=types.type_default
        )
        assert response is not None
        assert isinstance(response, dict)
```

All available data that the client can accept:
```
method: str,
endpoint: str,
add_url1: Optional[str] = '',
add_url2: Optional[str] = '',
add_url3: Optional[str] = '',
params: Optional[Dict[str, Any]] = None,
headers: Optional[Dict[str, str]] = None,
data: Optional[Dict[str, Any]] = None,
expected_status_code: Optional[int] = None,
validate_model: Optional[Type[BaseModel]] = None,
type: Optional[str] = None```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/Dec01/partest",
    "name": "partest",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "autotest partest test coverage",
    "author": "dec01",
    "author_email": "parschin.ewg@yandex.ru",
    "download_url": "https://files.pythonhosted.org/packages/30/fb/e100c134d1fd54e179a1002ef765d66cc21dfaf1ab180e88f6181c62ee20/partest-0.1.31.tar.gz",
    "platform": null,
    "description": "## HI!\n\nThis is a framework for API autotests with coverage assessment. Detailed instructions in the process of writing. It is better to check with the author how to use it. Tools are used:\n\n* pytest\n* httpx\n* allure\n\nFiles are required for specific work:\n\n**conftest.py** - it must have a fixture's inside:\n\n```commandline\n@pytest.fixture(scope=\"session\")\ndef api_client(domain):\n    return ApiClient(domain=domain)\n```\n```commandline\n@pytest.fixture(scope='session', autouse=True)\ndef clear_call_data():\n    \"\"\"\u0424\u0438\u043a\u0441\u0442\u0443\u0440\u0430 \u0434\u043b\u044f \u043e\u0447\u0438\u0441\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u0434 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c \u0442\u0435\u0441\u0442\u043e\u0432.\"\"\"\n    global call_count, call_type\n    api_call_storage.call_count.clear()\n    api_call_storage.call_type.clear()\n    yield\n```\n\n**confpartest.py** - It must have variables inside:\n\n```\nswagger_files = {\n    'test1': ['local', '../public/swagger/app-openapi.yaml'],\n    'test2': ['local', '../public/swagger/app-openapi2.yaml'],\n    'test3': ['url', 'https://url.ru']\n}\n\ntest_types_coverage = ['default', '405', 'param']\n```\n\nThe project must have a test that displays information about the coverage in allure. The name of it **test_zorro.py**:\n\n```commandline\n\n    async def test_display_final_call_counts(self):\n        report_lines = []\n        total_coverage_percentage = 0\n        total_endpoints = 0\n        total_calls_excluding_generation = 0\n\n        for (method, endpoint, description), count in call_count.items():\n            types = set(call_type[(method, endpoint, description)])\n            total_endpoints += 1\n\n            # \u041f\u043e\u0434\u0441\u0447\u0435\u0442 \u0432\u044b\u0437\u043e\u0432\u043e\u0432, \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u044f \u0442\u0438\u043f 'generation_data'\n            if 'generation_data' not in types:\n                total_calls_excluding_generation += count\n\n            # \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u0442\u0435\u0441\u0442\u043e\u0432\n            coverage_status = \"\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e\u0435 \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u0435 \u274c\"\n            matched_types = set(types).intersection(types)  \n            count_matched = len(matched_types)\n\n            # \u041b\u043e\u0433\u0438\u043a\u0430 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u044f \u0438 \u0440\u0430\u0441\u0447\u0435\u0442\u0430 \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u0430\n            if count_matched == len(types):  # \u0412\u0441\u0435 \u0442\u0438\u043f\u044b \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442\n                coverage_status = \"\u041f\u043e\u043a\u0440\u044b\u0442\u0438\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e \u2705\"\n                total_coverage_percentage += 100\n            elif count_matched == 2:  \n                coverage_status = \"\u041f\u043e\u043a\u0440\u044b\u0442\u0438\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e \u043d\u0430 66% \ud83d\udd14\"\n                total_coverage_percentage += 66\n            elif count_matched == 1:  \n                coverage_status = \"\u041f\u043e\u043a\u0440\u044b\u0442\u0438\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e \u043d\u0430 33% \u274c\"\n                total_coverage_percentage += 33\n            else: \n                coverage_status = \"\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e\u0435 \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u0435 \u274c\"\n                total_coverage_percentage += 0\n\n            report_line = (\n                f\"\\n{description}\\n\u042d\u043d\u0434\u043f\u043e\u0438\u043d\u0442: {endpoint}\\n\u041c\u0435\u0442\u043e\u0434: {method} | \"\n                f\"\u041e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0439: {count}, \u0422\u0438\u043f\u044b \u0442\u0435\u0441\u0442\u043e\u0432: {', '.join(types)}\\n{coverage_status}\\n\"\n            )\n            report_lines.append(report_line)\n\n        # \u0412\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u043e\u0431\u0449\u0435\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u0430 \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u044f\n        if total_endpoints > 0:\n            average_coverage_percentage = total_coverage_percentage / total_endpoints\n        else:\n            average_coverage_percentage = 0\n\n        border = \"*\" * 50\n        summary = f\"{border}\\n\u041e\u0431\u0449\u0438\u0439 \u043f\u0440\u043e\u0446\u0435\u043d\u0442 \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u044f: {average_coverage_percentage:.2f}%\\n\u041e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u044b\u0437\u043e\u0432\u043e\u0432 (\u0438\u0441\u043a\u043b\u044e\u0447\u0430\u044f 'generation_data'): {total_calls_excluding_generation}\\n{border}\\n\"\n\n        # \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u0432\u043e\u0434\u043a\u0443 \u0432 \u043d\u0430\u0447\u0430\u043b\u043e \u043e\u0442\u0447\u0435\u0442\u0430\n        report_lines.insert(0, summary)\n\n        create_chart(call_count)\n\n        with open('api_call_counts.png', 'rb') as f:\n            allure.attach(f.read(), name='\u041e\u0446\u0435\u043d\u043a\u0430 \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u044f', attachment_type=allure.attachment_type.PNG)\n\n        allure.attach(\"\\n\".join(report_lines), name='\u041e\u0442\u0447\u0435\u0442 \u043f\u043e \u0432\u044b\u0437\u043e\u0432\u0430\u043c API', attachment_type=allure.attachment_type.TEXT)\n\n        assert True\n\n```\n\n\nWhat does the test look like:\n\n```commandline\n    async def test_get(self, api_client):\n        endpoint = 'https://ya.ru'\n        response = await api_client.make_request(\n            'GET',\n            endpoint,\n            params='limit=1',\n            expected_status_code=200,\n            validate_model=Models.ValidateGet,\n            type=types.type_default\n        )\n        assert response is not None\n        assert isinstance(response, dict)\n```\n\nAll available data that the client can accept:\n```\nmethod: str,\nendpoint: str,\nadd_url1: Optional[str] = '',\nadd_url2: Optional[str] = '',\nadd_url3: Optional[str] = '',\nparams: Optional[Dict[str, Any]] = None,\nheaders: Optional[Dict[str, str]] = None,\ndata: Optional[Dict[str, Any]] = None,\nexpected_status_code: Optional[int] = None,\nvalidate_model: Optional[Type[BaseModel]] = None,\ntype: Optional[str] = None```\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "This is a module for the rapid implementation of test cases with coverage tracking. This module contains a call counter for specific endpoints and their methods. As well as the function of determining the types of tests that need to be counted.",
    "version": "0.1.31",
    "project_urls": {
        "GitHub": "https://github.com/Dec01/partest",
        "Homepage": "https://github.com/Dec01/partest"
    },
    "split_keywords": [
        "autotest",
        "partest",
        "test",
        "coverage"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "6ec684fea8aad9a3d1d9b8b5e67e172383c6521130b73623bb4a871c68ce4e5c",
                "md5": "37c63a970c2dc26596eef204c30b090e",
                "sha256": "c9a55580d94c18d2d017ceced96af8f4b8810ef8bb326dfaee5ef750e5e6d0f0"
            },
            "downloads": -1,
            "filename": "partest-0.1.31-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "37c63a970c2dc26596eef204c30b090e",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 14147,
            "upload_time": "2024-12-09T09:38:12",
            "upload_time_iso_8601": "2024-12-09T09:38:12.705584Z",
            "url": "https://files.pythonhosted.org/packages/6e/c6/84fea8aad9a3d1d9b8b5e67e172383c6521130b73623bb4a871c68ce4e5c/partest-0.1.31-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "30fbe100c134d1fd54e179a1002ef765d66cc21dfaf1ab180e88f6181c62ee20",
                "md5": "0db580c9e2604a4f408a7f6459667239",
                "sha256": "cce489113ea495a881341c814bd7edbec111c6019f1eb1626eaf2c91657d22dc"
            },
            "downloads": -1,
            "filename": "partest-0.1.31.tar.gz",
            "has_sig": false,
            "md5_digest": "0db580c9e2604a4f408a7f6459667239",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 13260,
            "upload_time": "2024-12-09T09:38:14",
            "upload_time_iso_8601": "2024-12-09T09:38:14.665855Z",
            "url": "https://files.pythonhosted.org/packages/30/fb/e100c134d1fd54e179a1002ef765d66cc21dfaf1ab180e88f6181c62ee20/partest-0.1.31.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-12-09 09:38:14",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Dec01",
    "github_project": "partest",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [
        {
            "name": "attrs",
            "specs": [
                [
                    "==",
                    "23.2.0"
                ]
            ]
        },
        {
            "name": "certifi",
            "specs": [
                [
                    "==",
                    "2024.7.4"
                ]
            ]
        },
        {
            "name": "charset-normalizer",
            "specs": [
                [
                    "==",
                    "2.0.12"
                ]
            ]
        },
        {
            "name": "Faker",
            "specs": [
                [
                    ">=",
                    "13.12.0"
                ]
            ]
        },
        {
            "name": "idna",
            "specs": [
                [
                    "==",
                    "3.3"
                ]
            ]
        },
        {
            "name": "iniconfig",
            "specs": [
                [
                    "==",
                    "1.1.1"
                ]
            ]
        },
        {
            "name": "jsonschema",
            "specs": [
                [
                    "==",
                    "4.22.0"
                ]
            ]
        },
        {
            "name": "packaging",
            "specs": [
                [
                    "==",
                    "21.3"
                ]
            ]
        },
        {
            "name": "pluggy",
            "specs": [
                [
                    "==",
                    "1.5.0"
                ]
            ]
        },
        {
            "name": "py",
            "specs": [
                [
                    "==",
                    "1.11.0"
                ]
            ]
        },
        {
            "name": "pyparsing",
            "specs": [
                [
                    "==",
                    "3.0.9"
                ]
            ]
        },
        {
            "name": "pyrsistent",
            "specs": [
                [
                    "==",
                    "0.18.1"
                ]
            ]
        },
        {
            "name": "pytest",
            "specs": [
                [
                    "==",
                    "8.3.3"
                ]
            ]
        },
        {
            "name": "python-dateutil",
            "specs": [
                [
                    "==",
                    "2.8.2"
                ]
            ]
        },
        {
            "name": "requests",
            "specs": [
                [
                    "==",
                    "2.32.0"
                ]
            ]
        },
        {
            "name": "six",
            "specs": [
                [
                    "==",
                    "1.16.0"
                ]
            ]
        },
        {
            "name": "tomli",
            "specs": [
                [
                    "==",
                    "2.0.1"
                ]
            ]
        },
        {
            "name": "urllib3",
            "specs": [
                [
                    "==",
                    "2.2.2"
                ]
            ]
        },
        {
            "name": "pytest-repeat",
            "specs": [
                [
                    "==",
                    "0.9.1"
                ]
            ]
        },
        {
            "name": "pytest-asyncio",
            "specs": [
                [
                    ">=",
                    "0.23.7"
                ]
            ]
        },
        {
            "name": "pydantic",
            "specs": [
                [
                    "==",
                    "2.7.1"
                ]
            ]
        },
        {
            "name": "pytest-rerunfailures",
            "specs": [
                [
                    "~=",
                    "14.0"
                ]
            ]
        },
        {
            "name": "ruff",
            "specs": [
                [
                    "==",
                    "0.4.2"
                ]
            ]
        },
        {
            "name": "allure-pytest",
            "specs": [
                [
                    ">=",
                    "2.8.18"
                ]
            ]
        },
        {
            "name": "allure-python-commons",
            "specs": [
                [
                    "~=",
                    "2.13.5"
                ]
            ]
        },
        {
            "name": "httpx",
            "specs": [
                [
                    "~=",
                    "0.27.2"
                ]
            ]
        },
        {
            "name": "swagger-parser",
            "specs": [
                [
                    ">=",
                    "1.0.2"
                ]
            ]
        },
        {
            "name": "matplotlib",
            "specs": [
                [
                    ">=",
                    "3.9.2"
                ]
            ]
        },
        {
            "name": "pyyaml",
            "specs": [
                [
                    ">=",
                    "6.0.2"
                ]
            ]
        }
    ],
    "lcname": "partest"
}
        
Elapsed time: 0.41749s