Основы Python для QA
Updated Jul 2026
Python — самый популярный язык для бэкенд/API-тестирования, валидации данных и скриптинга в мире QA. Его читаемый синтаксис, богатая стандартная библиотека и обширная экосистема библиотек для тестирования делают его выбором по умолчанию для QA-инженеров, работающих за пределами браузера.
Почему Python для QA
| Сильная сторона | Как помогает QA |
|---|---|
| Читаемый синтаксис | Тестовый код самодокументируем; легко читается разработчиками, не знающими Python |
| Экосистема pytest | Самый мощный тестовый фреймворк с фикстурами, параметризацией и плагинами |
| Библиотека requests | Чистый HTTP-клиент для тестирования API |
| Библиотеки для данных | pandas, json, csv — необходимы для валидации данных |
| Скорость скриптинга | Быстрые скрипты для парсинга логов, очистки данных, настройки окружения |
| Аннотации типов + mypy | Опциональная статическая типизация ловит ошибки до запуска тестов |
pytest: тестовый фреймворк
pytest — стандартный тестовый фреймворк Python. Он проще, чем unittest, мощнее и используется большинством Python QA-команд.
Базовая структура теста
# test_login.py
def test_successful_login(api_client):
response = api_client.post("/auth/login", json={
"email": "test@example.com",
"password": "ValidPass123!"
})
assert response.status_code == 200
assert "access_token" in response.json()
def test_login_with_invalid_password(api_client):
response = api_client.post("/auth/login", json={
"email": "test@example.com",
"password": "wrong"
})
assert response.status_code == 401
assert "access_token" not in response.json()
Фикстуры
Фикстуры обеспечивают переиспользуемую подготовку и очистку. Они заменяют методы setup/teardown из unittest более гибким и компонуемым паттерном.
# conftest.py
import pytest
import requests
@pytest.fixture(scope="session")
def base_url():
return os.environ.get("API_BASE_URL", "http://localhost:3000/api/v1")
@pytest.fixture(scope="session")
def auth_token(base_url):
r = requests.post(f"{base_url}/auth/login", json={
"email": "admin@test.com", "password": "adminpass"
})
return r.json()["access_token"]
@pytest.fixture
def auth_headers(auth_token):
return {"Authorization": f"Bearer {auth_token}"}
@pytest.fixture
def api_client(base_url, auth_headers):
session = requests.Session()
session.headers.update(auth_headers)
session.base_url = base_url
return session
Области видимости фикстур управляют жизненным циклом:
scope="function"(по умолчанию): выполняется перед/после каждого тестаscope="class": один раз на тестовый классscope="module": один раз на файлscope="session": один раз на запуск тестов
Параметризация
Запуск одного и того же теста с разными данными:
@pytest.mark.parametrize("email,expected_status", [
("valid@test.com", 200),
("", 400),
("not-an-email", 422),
("valid@test.com; DROP TABLE users", 422),
("a" * 255 + "@test.com", 422),
])
def test_login_email_validation(api_client, email, expected_status):
response = api_client.post("/auth/login", json={
"email": email, "password": "ValidPass123!"
})
assert response.status_code == expected_status
Маркеры
Пометка тестов для выборочного запуска:
@pytest.mark.smoke
def test_health_check(base_url):
assert requests.get(f"{base_url}/health").status_code == 200
@pytest.mark.slow
def test_full_checkout_flow(api_client):
# ... lengthy test
pass
pytest -m smoke # Run only smoke tests
pytest -m "not slow" # Skip slow tests
Библиотека requests
Стандартный HTTP-клиент для тестирования API на Python.
import requests
# GET with query parameters
r = requests.get("https://api.example.com/users", params={"page": 1, "limit": 10})
print(r.status_code) # 200
print(r.json()) # parsed JSON response
print(r.headers) # response headers
print(r.elapsed) # time taken
# POST with JSON body
r = requests.post("https://api.example.com/users", json={
"name": "Alice",
"email": "alice@example.com"
})
# PUT with headers
r = requests.put("https://api.example.com/users/123",
json={"name": "Alice Updated"},
headers={"Authorization": "Bearer token123"}
)
# DELETE
r = requests.delete("https://api.example.com/users/123",
headers={"Authorization": "Bearer token123"}
)
assert r.status_code == 204
Объекты сессий
Для тестов, которым необходимо сохранять состояние (cookies, заголовки) между запросами:
session = requests.Session()
session.headers.update({"Authorization": "Bearer token123"})
# All subsequent requests include the auth header
r1 = session.get("https://api.example.com/users/me")
r2 = session.get("https://api.example.com/users/me/orders")
Паттерны валидации данных
import json
from datetime import datetime
def test_user_response_structure(api_client, base_url):
r = api_client.get(f"{base_url}/users/me")
user = r.json()
# Required fields exist
required_fields = {"id", "name", "email", "created_at", "role"}
assert required_fields.issubset(user.keys()), f"Missing: {required_fields - user.keys()}"
# Sensitive fields absent
assert "password" not in user
assert "password_hash" not in user
# Type validation
assert isinstance(user["id"], int)
assert isinstance(user["name"], str)
assert len(user["name"]) > 0
# Date format validation
datetime.fromisoformat(user["created_at"]) # Raises if invalid
# Enum validation
assert user["role"] in {"admin", "editor", "viewer"}
Управление пакетами
| Инструмент | Лучше всего для |
|---|---|
| pip | Простые проекты, быстрая установка |
| poetry | Управление зависимостями с lock-файлами, публикация |
| uv | Быстрая установка, современная замена pip + venv |
# Create virtual environment and install dependencies
python -m venv .venv
source .venv/bin/activate
pip install pytest requests httpx
# Or with poetry
poetry init
poetry add pytest requests httpx
# Or with uv
uv init
uv add pytest requests httpx
Практическое упражнение
Напишите файл тестов pytest, который:
- Использует фикстуру для аутентификации и получения токена
- Тестирует создание пользователя (POST)
- Тестирует получение созданного пользователя (GET)
- Тестирует, что создание с дублирующим email возвращает 409
- Использует parametrize для тестирования валидации email с минимум 5 входными данными
- Очищает созданного пользователя в teardown фикстуры
Ключевые выводы
- pytest — стандарт: изучите фикстуры, parametrize и маркеры
- requests — стандартный HTTP-клиент: изучите сессии, работу с JSON и инспекцию ответов
- Используйте conftest.py для общих фикстур между тестовыми файлами
- Валидируйте структуру ответа (поля, типы, отсутствие чувствительных данных), а не только коды состояния
- Используйте parametrize для data-driven тестирования вместо копирования тестовых функций