AI-система автоматичного тестування API

Проектуємо та впроваджуємо системи штучного інтелекту: від прототипу до production-ready рішення. Наша команда поєднує експертизу в машинному навчанні, дата-інжинірингу та MLOps, щоб AI працював не в лабораторії, а в реальному бізнесі.
Показано 1 з 1Усі 1566 послуг
AI-система автоматичного тестування API
Середній
~2-3 дні
Часті запитання

Напрямки AI-розробки

Етапи розробки AI-рішення

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1284
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1196
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    901
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1119
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    586
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    853

AI-автоматизоване тестування API

API-тестування вирішує кілька завдань одночасно: функціональність (коректні відповіді), контрактне тестування (schema validation), продуктивність (latency під навантаженням), безпека (auth, injection, rate limits). AI-система покриває всі чотири шари, генеруючи тести з OpenAPI-специфікацій та аналізуючи реальний трафік.

Генерація тестів з OpenAPI специфікації

import yaml
import json
from langchain_openai import ChatOpenAI
from pathlib import Path

class APITestGenerator:
    CONTRACT_TEST_PROMPT = """Створи pytest тести для API endpoint.

Endpoint: {method} {path}
OpenAPI Spec:
{spec}

Тести мають покрити:
1. **Happy path**: валідний запит → очікуваний відповідь
2. **Schema validation**: відповідь відповідає OpenAPI схемі (використовуй jsonschema)
3. **Auth**: запит без токена → 401, невалідний токен → 401/403
4. **Validation errors**: відсутні обов'язкові поля → 422, неправильні типи → 422
5. **Граничні значення**: min/max довжина рядків, числові межі
6. **Business rules**: специфічні правила з опису endpoint

Використовуй: pytest + httpx + jsonschema
Base URL через pytest fixture: base_url
Auth token через fixture: auth_token

Повернення коду тестів."""

    def __init__(self):
        self.llm = ChatOpenAI(model="gpt-4o", temperature=0.1)

    def generate_from_openapi(self, spec_path: str) -> dict[str, str]:
        """Генерує тести для всіх endpoints з OpenAPI spec"""
        with open(spec_path) as f:
            spec = yaml.safe_load(f)

        test_files = {}
        for path, methods in spec.get("paths", {}).items():
            for method, endpoint_spec in methods.items():
                test_code = self._generate_endpoint_tests(path, method, endpoint_spec, spec)
                filename = f"test_{method}_{path.replace('/', '_').strip('_')}.py"
                test_files[filename] = test_code

        return test_files

    def _generate_endpoint_tests(
        self,
        path: str,
        method: str,
        endpoint_spec: dict,
        full_spec: dict
    ) -> str:
        # Розв'язуємо $ref
        resolved_spec = self._resolve_refs(endpoint_spec, full_spec)

        return self.llm.invoke(
            self.CONTRACT_TEST_PROMPT.format(
                method=method.upper(),
                path=path,
                spec=json.dumps(resolved_spec, ensure_ascii=False, indent=2)
            )
        ).content

Генерація тестів на основі реального трафіку

class TrafficBasedTestGenerator:
    """Генерує тести з HAR-файлів або прокси-логів"""

    def generate_from_har(self, har_path: str) -> list[str]:
        """Генерує regression-тести з записаного трафіку"""
        with open(har_path) as f:
            har = json.load(f)

        entries = har["log"]["entries"]
        api_calls = [
            e for e in entries
            if "api" in e["request"]["url"] or
               e["response"]["content"].get("mimeType", "").startswith("application/json")
        ]

        tests = []
        for entry in api_calls[:50]:  # топ-50 унікальних запитів
            test = self._generate_regression_test(entry)
            tests.append(test)

        return tests

    def _generate_regression_test(self, entry: dict) -> str:
        request = entry["request"]
        response = entry["response"]

        prompt = f"""Створи pytest regression-тест з записаної HTTP-взаємодії.

Request:
- Method: {request['method']}
- URL: {request['url']}
- Headers: {json.dumps({h['name']: h['value'] for h in request.get('headers', [])[:5]}, ensure_ascii=False)}
- Body: {request.get('postData', {}).get('text', '')[:500]}

Response:
- Status: {response['status']}
- Body: {response['content'].get('text', '')[:500]}

Створи тест який:
1. Відтворює запит (з параметризованими тестовими даними замість реальних)
2. Перевіряє статус-код
3. Перевіряє схему відповіді (ключі, типи)
4. Не хардкодить реальні дані (замініть на fixtures)

Повернення pytest коду."""

        return self.llm.invoke(prompt).content

Тестування безпеки API

class APISecurityTester:
    SECURITY_PROMPTS = {
        "sql_injection": [
            "' OR '1'='1", "'; DROP TABLE users;--",
            "1 UNION SELECT NULL,NULL,NULL--",
            "' AND SLEEP(5)--"
        ],
        "nosql_injection": [
            '{"$gt": ""}', '{"$where": "this.password.length > 0"}',
            '{"$regex": ".*"}'
        ],
        "xss": [
            "<script>alert('xss')</script>",
            "javascript:alert(1)",
            '"><img src=x onerror=alert(1)>'
        ]
    }

    async def test_injection_resilience(
        self,
        endpoint: str,
        param_name: str,
        client
    ) -> list[dict]:
        results = []
        for attack_type, payloads in self.SECURITY_PROMPTS.items():
            for payload in payloads:
                response = await client.post(
                    endpoint,
                    json={param_name: payload}
                )
                # Застосунок має повернути 400/422, а не 500 або дані
                results.append({
                    "attack_type": attack_type,
                    "payload": payload,
                    "status": response.status_code,
                    "vulnerable": response.status_code == 500 or
                                   self._contains_db_error(response.text)
                })
        return results

Навантажувальне тестування через Locust

    LOCUST_PROMPT = """Створи Locust навантажувальний тест для API.

Endpoints для навантаження:
{endpoints}

Створи:
- HttpUser клас з task'ами для кожного endpoint
- Реалістичне розподілення: часті операції → більша вага
- @task(3) для читання, @task(1) для запису
- between(1, 5) для wait_time
- Обробка помилок через on_failure

Мета: 100 RPS, P95 latency < 500 мс.
Повернення Python коду для locustfile.py."""

Конфігурація CI/CD

# Піраміда API-тестів у CI
api-tests:
  contract:
    run: pytest tests/api/contract/ -v
    on: [push, pull_request]
  security:
    run: pytest tests/api/security/ -v
    on: [pull_request]
  performance:
    run: locust -f tests/api/locustfile.py --headless -u 50 -r 5 --run-time 2m
    on: [manual, schedule]  # не блокуємо PR

Кейс: REST API фінтех-стартапу, 45 endpoints. Команда витрачала 3 дні на regression-тестування API перед кожним релізом. Сгенерували 180 contract-тестів з OpenAPI spec та 60 security-тестів. Тести виявили: 2 endpoint'и без auth-перевірки, 1 SQL-injection у фільтрі звітів, некоректна обробка Unicode в іменах (500 замість 422).

Строки: генератор з OpenAPI + contract-тести: 2–3 тижні; security та performance тести: 3–4 тижні дополнительно.