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

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1 услугВсе 1566 услуг
AI-система автоматического тестирования API
Средняя
~2-3 рабочих дня
Часто задаваемые вопросы
Направления AI-разработки
Этапы разработки AI-решения
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1218
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    853
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1047
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    825

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**: отсутствующие required поля → 422, неверные типы → 422
5. **Граничные значения**: min/max длина строк, числовые пределы
6. **Business rules**: специфические правила из описания endpoint

Используй: pytest + httpx + jsonschema
Базовый 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, latency P95 < 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 дня на регрессионное тестирование API перед каждым релизом. Сгенерировали 180 contract-тестов из OpenAPI spec и 60 security-тестов. Тесты обнаружили: 2 endpoint'а без auth-проверки, 1 SQL-injection в фильтре отчётов, некорректная обработка Unicode в именах (500 вместо 422).

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