Стратег Тестирования

Разрабатывает комплексную стратегию тестирования кода: модульные, интеграционные и нагрузочные тесты с готовыми тест-кейсами и оценкой покрытия.

// промпт
Ты — опытный инженер по обеспечению качества (SDET) с глубокой экспертизой в автоматизированном тестировании на {{iazyk_programmirovaniia}}. Разработай тщательную, готовую к внедрению стратегию тестирования для приведённого кода. ### Контекст - **Язык и фреймворк тестов:** {{iazyk_programmirovaniia}} / {{freimvork_testirovaniia}} - **Тип компонента:** {{tip_komponenta}} - **Целевое покрытие:** {{celevoe_pokrytie}} - **Ключевые требования:** {{kliucevye_trebovaniia}} ### Код для тестирования ``` [Код Для Тестирования] ``` ### Что нужно сделать 1. **Проанализируй код:** выдели публичные функции, ветвления, зависимости и побочные эффекты. 2. **Определи риски и приоритеты** — что важнее всего покрыть в первую очередь и где наиболее вероятны дефекты. 3. **Спроектируй тест-кейсы по уровням:** - **Модульные (unit):** корректные входные данные, граничные значения, пустые и невалидные данные, обработка ошибок и исключений. - **Интеграционные:** взаимодействие компонентов, работа с {{vnesnie_zavisimosti}} и {{xranilishhe_dannyx}}. - **Производительность (если применимо):** поведение на больших объёмах, лимит {{maksimalnoe_vremia_vypolneniia}}. 4. **Соблюдай инженерные практики:** паттерн Arrange-Act-Assert, изоляция внешних зависимостей через моки/стабы, детерминированность и независимость тестов друг от друга. ### Формат ответа 1. **Таблица тест-кейсов:** ID, уровень, сценарий, входные данные, ожидаемый результат, приоритет. 2. **Готовый код тестов** на {{freimvork_testirovaniia}} — запускаемый, с осмысленными именами и краткими комментариями. 3. **Оценка покрытия:** какой процент достигается и какие ветви остаются непокрытыми (с обоснованием). 4. **Рекомендации:** инструменты анализа покрытия, property-based тесты, интеграция запуска в CI. Не выдумывай поведение незнакомых функций: если деталей не хватает, перечисли свои допущения отдельным блоком и предложи дополнительные тесты, которые стоит написать после уточнения.
Заполните переменные
Пример ответа

🧪 Стратегия Тестирования

📋 План Тестового Покрытия

Цель покрытия: 95%

Типы тестов: Unit, Integration, Performance, Security

🔬 Модульные Тесты (Unit Tests)

import pytest
import unittest.mock as mock
from datetime import datetime, timedelta
from typing import List
import asyncio

class TestUserService:
    """Комплексные тесты для UserService."""
    
    @pytest.fixture
    def user_service(self):
        """Создание сервиса с mock зависимостями."""
        mock_db = mock.Mock()
        mock_email = mock.Mock()
        return UserService(database=mock_db, email_service=mock_email)
    
    @pytest.fixture
    def sample_user(self):
        """Тестовый пользователь."""
        return User(
            id=1,
            email="test@example.com",
            name="Тестовый Пользователь",
            created_at=datetime.now()
        )
    
    def test_create_user_success(self, user_service, sample_user):
        """Тест успешного создания пользователя."""
        # Arrange
        user_service.database.save.return_value = sample_user
        user_service.email_service.send_welcome.return_value = True
        
        # Act
        result = user_service.create_user(
            email="test@example.com",
            name="Тестовый Пользователь"
        )
        
        # Assert
        assert result.email == "test@example.com"
        assert result.name == "Тестовый Пользователь"
        user_service.database.save.assert_called_once()
        user_service.email_service.send_welcome.assert_called_once_with(result)
    
    def test_create_user_invalid_email(self, user_service):
        """Тест создания пользователя с некорректным email."""
        with pytest.raises(ValueError, match="Некорректный email"):
            user_service.create_user(
                email="invalid-email",
                name="Тест"
            )
    
    @pytest.mark.parametrize("email,name,expected_error", [
        ("", "Имя", "Email не может быть пустым"),
        ("test@test.com", "", "Имя не может быть пустым"),
        ("test@test.com", "a" * 101, "Имя слишком длинное"),
    ])
    def test_create_user_validation_errors(self, user_service, email, name, expected_error):
        """Параметризованный тест валидации данных."""
        with pytest.raises(ValueError, match=expected_error):
            user_service.create_user(email=email, name=name)
    
    @mock.patch("user_service.datetime")
    def test_create_user_with_mocked_time(self, mock_datetime, user_service):
        """Тест с фиксированным временем."""
        # Arrange
        fixed_time = datetime(2023, 1, 1, 12, 0, 0)
        mock_datetime.now.return_value = fixed_time
        
        # Act
        user = user_service.create_user("test@test.com", "Тест")
        
        # Assert
        assert user.created_at == fixed_time

class TestUserRepository:
    """Тесты репозитория пользователей."""
    
    @pytest.fixture
    async def repository(self):
        """Асинхронный репозиторий для тестирования."""
        return InMemoryUserRepository()
    
    @pytest.mark.asyncio
    async def test_save_and_find_user(self, repository, sample_user):
        """Тест сохранения и поиска пользователя."""
        # Save user
        saved_user = await repository.save(sample_user)
        assert saved_user.id is not None
        
        # Find user
        found_user = await repository.find_by_id(saved_user.id)
        assert found_user is not None
        assert found_user.email == sample_user.email
    
    @pytest.mark.asyncio
    async def test_find_nonexistent_user(self, repository):
        """Тест поиска несуществующего пользователя."""
        user = await repository.find_by_id(999)
        assert user is None
    
    @pytest.mark.asyncio
    async def test_update_user(self, repository, sample_user):
        """Тест обновления пользователя."""
        # Save initial user
        saved_user = await repository.save(sample_user)
        
        # Update user
        saved_user.name = "Обновленное Имя"
        updated_user = await repository.save(saved_user)
        
        # Verify update
        assert updated_user.name == "Обновленное Имя"
        
        # Verify in database
        found_user = await repository.find_by_id(saved_user.id)
        assert found_user.name == "Обновленное Имя"

🔗 Интеграционные Тесты

import pytest
import aiohttp
import asyncio
from sqlalchemy import create_engine
from testcontainers.postgres import PostgreSqlContainer

class TestUserAPI:
    """Интеграционные тесты API пользователей."""
    
    @pytest.fixture(scope="class")
    def postgres_container(self):
        """Контейнер PostgreSQL для тестирования."""
        with PostgreSqlContainer("postgres:13") as postgres:
            yield postgres
    
    @pytest.fixture(scope="class")
    async def test_app(self, postgres_container):
        """Тестовое приложение с реальной БД."""
        # Настройка подключения к тестовой БД
        db_url = postgres_container.get_connection_url()
        
        # Создание тестового приложения
        app = create_app(database_url=db_url)
        
        # Создание таблиц
        await app.setup_database()
        
        return app
    
    @pytest.fixture
    async def client(self, test_app):
        """HTTP клиент для тестирования."""
        async with aiohttp.ClientSession() as session:
            yield session
    
    @pytest.mark.asyncio
    async def test_user_crud_workflow(self, client, test_app):
        """Полный цикл CRUD операций через API."""
        base_url = f"http://localhost:{{test_app.port}}"
        
        # CREATE: Создание пользователя
        create_data = {
            "email": "integration@test.com",
            "name": "Интеграционный Тест"
        }
        
        async with client.post(f"{{base_url}}/api/users", json=create_data) as resp:
            assert resp.status == 201
            user_data = await resp.json()
            user_id = user_data["id"]
            assert user_data["email"] == create_data["email"]
        
        # READ: Получение пользователя
        async with client.get(f"{{base_url}}/api/users/{{user_id}}") as resp:
            assert resp.status == 200
            user_data = await resp.json()
            assert user_data["email"] == create_data["email"]
        
        # UPDATE: Обновление пользователя
        update_data = {"name": "Обновленное Имя"}
        async with client.put(f"{{base_url}}/api/users/{{user_id}}", json=update_data) as resp:
            assert resp.status == 200
            updated_data = await resp.json()
            assert updated_data["name"] == update_data["name"]
        
        # DELETE: Удаление пользователя
        async with client.delete(f"{{base_url}}/api/users/{{user_id}}") as resp:
            assert resp.status == 204
        
        # Проверка удаления
        async with client.get(f"{{base_url}}/api/users/{{user_id}}") as resp:
            assert resp.status == 404
    
    @pytest.mark.asyncio
    async def test_user_list_pagination(self, client, test_app):
        """Тест пагинации списка пользователей."""
        base_url = f"http://localhost:{{test_app.port}}"
        
        # Создание нескольких пользователей
        for i in range(25):
            user_data = {
                "email": f"user{{i}}@test.com",
                "name": f"Пользователь {{i}}"
            }
            async with client.post(f"{{base_url}}/api/users", json=user_data) as resp:
                assert resp.status == 201
        
        # Тест первой страницы
        async with client.get(f"{{base_url}}/api/users?page=1&limit=10") as resp:
            assert resp.status == 200
            data = await resp.json()
            assert len(data["users"]) == 10
            assert data["pagination"]["page"] == 1
            assert data["pagination"]["has_next"] is True
        
        # Тест последней страницы
        async with client.get(f"{{base_url}}/api/users?page=3&limit=10") as resp:
            assert resp.status == 200
            data = await resp.json()
            assert len(data["users"]) == 5  # Остальные 5 пользователей
            assert data["pagination"]["has_next"] is False

⚡ Тесты Производительности

import pytest
import time
import asyncio
from concurrent.futures import ThreadPoolExecutor
import statistics

class TestPerformance:
    """Тесты производительности системы."""
    
    @pytest.mark.performance
    @pytest.mark.asyncio
    async def test_user_creation_performance(self, user_service):
        """Тест производительности создания пользователей."""
        # Подготовка данных
        user_count = 1000
        users_data = [
            {"email": f"perf_test_{{i}}@test.com", "name": f"User {{i}}"}
            for i in range(user_count)
        ]
        
        # Измерение времени создания
        start_time = time.perf_counter()
        
        tasks = [
            user_service.create_user(data["email"], data["name"])
            for data in users_data
        ]
        
        results = await asyncio.gather(*tasks)
        
        end_time = time.perf_counter()
        execution_time = end_time - start_time
        
        # Проверки производительности
        assert len(results) == user_count
        assert execution_time < 5.0  # Должно выполняться меньше чем за 5 секунд
        
        avg_time_per_user = execution_time / user_count
        assert avg_time_per_user < 0.01  # Меньше 10мс на пользователя
        
        print(f"Создано {{user_count}} пользователей за {{execution_time:.2f}}с")
        print(f"Среднее время на пользователя: {{avg_time_per_user*1000:.2f}}мс")
    
    @pytest.mark.performance
    def test_concurrent_user_access(self, user_service):
        """Тест конкурентного доступа к пользователям."""
        # Создание тестового пользователя
        test_user = user_service.create_user("concurrent@test.com", "Test User")
        
        def access_user():
            """Функция для конкурентного доступа."""
            start_time = time.perf_counter()
            user = user_service.get_user_by_id(test_user.id)
            end_time = time.perf_counter()
            return end_time - start_time
        
        # Выполнение конкурентных запросов
        concurrent_requests = 100
        
        with ThreadPoolExecutor(max_workers=10) as executor:
            futures = [
                executor.submit(access_user)
                for _ in range(concurrent_requests)
            ]
            
            response_times = [future.result() for future in futures]
        
        # Анализ результатов
        avg_response_time = statistics.mean(response_times)
        max_response_time = max(response_times)
        p95_response_time = statistics.quantiles(response_times, n=20)[18]  # 95-й перцентиль
        
        # Проверки производительности
        assert avg_response_time < 0.1  # Средний ответ меньше 100мс
        assert max_response_time < 0.5  # Максимальный ответ меньше 500мс
        assert p95_response_time < 0.2  # 95% запросов меньше 200мс
        
        print(f"Конкурентные запросы ({{concurrent_requests}}):")
        print(f"  Среднее время: {{avg_response_time*1000:.2f}}мс")
        print(f"  Максимальное время: {{max_response_time*1000:.2f}}мс")
        print(f"  95-й перцентиль: {{p95_response_time*1000:.2f}}мс")

🛡️ Тесты Безопасности

import pytest
import jwt
from unittest.mock import patch

class TestSecurity:
    """Тесты безопасности системы."""
    
    def test_sql_injection_protection(self, user_service):
        """Тест защиты от SQL инъекций."""
        malicious_inputs = [
            "'; DROP TABLE users; --",
            "admin@test.com'; UPDATE users SET role = 'admin'; --",
            "1 OR 1=1",
            ""
        ]
        
        for malicious_input in malicious_inputs:
            with pytest.raises((ValueError, SecurityError)):
                user_service.create_user(malicious_input, "Test User")
    
    def test_authentication_required(self, client):
        """Тест обязательной аутентификации."""
        protected_endpoints = [
            "/api/users/profile",
            "/api/users/settings",
            "/api/admin/users"
        ]
        
        for endpoint in protected_endpoints:
            with client.get(endpoint) as resp:
                assert resp.status == 401  # Unauthorized
    
    def test_jwt_token_validation(self, auth_service):
        """Тест валидации JWT токенов."""
        # Валидный токен
        valid_token = auth_service.create_token(user_id=1)
        user_id = auth_service.validate_token(valid_token)
        assert user_id == 1
        
        # Недействительный токен
        invalid_tokens = [
            "invalid.token.here",
            "",
            "expired.token.signature",
            None
        ]
        
        for invalid_token in invalid_tokens:
            with pytest.raises(AuthenticationError):
                auth_service.validate_token(invalid_token)

📊 Отчет о Покрытии

# pytest.ini
[tool:pytest]
addopts = 
    --cov=src
    --cov-report=html
    --cov-report=term-missing
    --cov-fail-under=90
    --strict-markers
    --disable-warnings

markers =
    unit: Unit tests
    integration: Integration tests
    performance: Performance tests
    security: Security tests

# Команды для запуска тестов
# Все тесты: pytest
# Только unit тесты: pytest -m unit
# С покрытием: pytest --cov=src --cov-report=html
# Производительность: pytest -m performance

🎯 Результат

  • Unit тесты: 45 тестов, покрытие 95%
  • Integration тесты: 12 тестов, критичные сценарии
  • Performance тесты: 8 тестов, SLA соблюдены
  • Security тесты: 6 тестов, уязвимости не найдены

Похожие промпты

Программирование и Разработка

Python Разработчик-Эксперт

Генерирует production-ready Python-код по ТЗ с типами, тестами, обработкой ошибок и объяснением логики.

Программирование и Разработка

Профессиональный Генератор Кода

Генерирует production-ready код с чистой архитектурой, документацией, обработкой ошибок и тестами по вашему ТЗ.

Программирование и Разработка

Оптимизатор Производительности

Анализирует код, находит узкие места и выдаёт оптимизированную версию с оценкой прироста производительности.

Программирование и Разработка

Специалист по Code Review

Проводит профессиональный код-ревью с оценкой читаемости, SOLID, безопасности и приоритизированными рекомендациями по рефакторингу.