💻 Примеры: Allure + API-тесты
⚡ Самый важный пример
# test_companies.py
import allure
@allure.epic("компании")
@allure.severity("blocker")
class CompanyTest:
@allure.id("ITCH-1")
@allure.story("Получение списка компаний")
@allure.feature("READ")
@allure.title("Получение полного списка организаций")
def test_get_companies(self):
with allure.step("Получить список через API"):
api_result = api.get_company_list()
with allure.step("Получить список из БД"):
db_result = db.get_companies()
with allure.step("Сравнить размеры"):
assert len(api_result) == len(db_result)
Пример 1: разметка тестов декораторами (из лекции)
Из лекции: @allure.epic и @allure.severity — общие для всего класса, выносим на уровень класса.
# test_x_clients_db.py
import allure
from CompanyApi import CompanyApi
from CompanyTable import CompanyTable
@allure.epic("компании")
@allure.severity("blocker")
class CompanyTest:
api = CompanyApi("https://x-clients-be.onrender.com")
db = CompanyTable("postgresql://user:password@host/db")
@allure.id("ITCH-1")
@allure.story("Получение списка компаний")
@allure.feature("READ")
@allure.title("Получение полного списка организаций")
def test_get_companies(self):
...
@allure.id("ITCH-2")
@allure.story("Получение списка компаний")
@allure.feature("READ")
@allure.title("Получение списка активных организаций")
@allure.description("Запрос организаций с параметром active = true")
def test_get_active_companies(self):
...
@allure.id("ITCH-3")
@allure.story("Создание компаний")
@allure.feature("CREATE")
@allure.title("Создание организации")
def test_add_new(self):
...
Пример 2: шаги в тесте (из лекции)
Из лекции: тест получения компаний, разбитый на три шага — каждый шаг виден в отчёте Allure в разделе «Test body».
# test_x_clients_db.py
import allure
@allure.id("ITCH-1")
@allure.story("Получение компаний")
@allure.feature("READ")
@allure.epic("компании")
def test_get_companies():
with allure.step("Получить список компаний через API"):
api_result = api.get_company_list()
with allure.step("Получить список компаний из БД"):
db_result = db.get_companies()
with allure.step("Сравнить размеры двух списков"):
assert len(api_result) == len(db_result)
Пример 3: вложенные шаги (из лекции)
Из лекции: тест создания компании с вложенными шагами. Помогает точно видеть, на каком этапе возникла ошибка.
# test_x_clients_db.py
@allure.id("ITCH-3")
@allure.story("Создание компаний")
@allure.feature("CREATE")
@allure.title("Создание организации")
def test_add_new(self):
with allure.step("Получить количество организаций ДО"):
body = self.api.get_company_list()
len_before = len(body)
with allure.step("Создать организацию"):
with allure.step("Сгенерировать название"):
name = "Autotest"
descr = "Descr"
with allure.step("Вызвать API-метод для создания"):
result = self.api.create_company(name, descr)
new_id = result["id"]
with allure.step("Проверить поля новой организации"):
body = self.api.get_company_list()
for company in body:
if company["id"] == new_id:
assert company["name"] == name
assert company["description"] == descr
with allure.step("Получить количество организаций ПОСЛЕ"):
body = self.api.get_company_list()
len_after = len(body)
with allure.step("Проверить, что список ДО меньше ПОСЛЕ на 1"):
assert len_after - len_before == 1
with allure.step("Удалить из БД новую организацию"):
self.db.delete(new_id)
Пример 4: @allure.step на методах класса CompanyApi (из лекции)
Из лекции: декорируем методы API-класса. В названии шага используем приставку «api.», параметры подставляются автоматически через {имя_аргумента}.
# company_api.py
import allure
import requests
class CompanyApi:
def __init__(self, url):
self.url = url
@allure.step("api. Получить список компаний")
def get_company_list(self, params_to_add=None):
resp = requests.get(self.url + "/company", params=params_to_add)
assert resp.status_code == 200
return resp.json()
@allure.step("api. Получить токен авторизации пользователя '{user}'")
def get_token(self, user="raphael", password="cool-but-crude"):
creds = {"user": user, "password": password}
resp = requests.post(self.url + "/auth/login", json=creds)
assert resp.status_code == 200
return resp.json()["userToken"]
@allure.step("api. Получить компанию по id '{id}'")
def get_company(self, id):
resp = requests.get(self.url + f"/company/{id}")
assert resp.status_code == 200
return resp.json()
@allure.step("api. Создать компанию '{name}' ({description})")
def create_company(self, name, description=""):
company = {"name": name, "description": description}
resp = requests.post(self.url + "/company", json=company)
assert resp.status_code == 201
return resp.json()
@allure.step("api. Редактировать компанию '{new_id}': новое имя '{new_name}'")
def edit(self, new_id, new_name, new_descr):
resp = requests.patch(self.url + f"/company/{new_id}",
json={"name": new_name, "description": new_descr})
assert resp.status_code == 200
return resp.json()
@allure.step("api. Удалить компанию '{id}'")
def delete(self, id):
resp = requests.delete(self.url + f"/company/{id}")
assert resp.status_code == 200
return resp.json()
@allure.step("api. (Де)активировать компанию '{id}', состояние '{isActive}'")
def set_active_status(self, id, isActive):
resp = requests.patch(self.url + f"/company/{id}",
json={"isActive": isActive})
assert resp.status_code == 200
return resp.json()
Пример 5: @allure.step на методах класса CompanyTable с вложением SQL (из лекции)
Из лекции: приставка «БД.» в шагах позволяет сразу видеть в отчёте, что метод взаимодействует с базой данных.
# company_table.py
import allure
from sqlalchemy import create_engine
from sqlalchemy.sql import text
class CompanyTable:
__scripts = {
"select": "select * from company",
"select only active": 'select * from company where "is_active" = true',
"delete by id": text("delete from company where id = :id_to_delete"),
"insert new": text("insert into company (name) values (:new_name)"),
}
def __init__(self, connection_string):
self.__db = create_engine(connection_string).connect()
@allure.step("БД. Запросить список организаций")
def get_companies(self):
query = self.__db.execute(self.__scripts["select"])
allure.attach(
str(query.context.cursor.query),
"SQL-запрос на получение списка компаний",
allure.attachment_type.TEXT
)
return query.fetchall()
@allure.step("БД. Запросить организацию по {id}")
def get_company_by_id(self, id):
# {id} подставится автоматически
...
@allure.step("БД. Удалить организацию по {id}")
def delete(self, id):
params = {"id_to_delete": id}
query = self.__db.execute(self.__scripts["delete by id"], parameters=params)
allure.attach(
str(query.context.cursor.query),
"SQL-запрос на удаление компании",
allure.attachment_type.TEXT
)
@allure.step("БД. Создать организацию с названием {name}")
def create(self, name):
params = {"new_name": name}
query = self.__db.execute(self.__scripts["insert new"], parameters=params)
allure.attach(
str(query.context.cursor.query),
"SQL-запрос на создание компании",
allure.attachment_type.TEXT
)
@allure.step("БД. Получить максимальный id организации")
def get_max_id(self):
query = self.__db.execute("select max(id) from company")
allure.attach(
str(query.context.cursor.query),
"SQL-запрос на получение максимального id",
allure.attachment_type.TEXT
)
return query.fetchone()[0]
Пример 6: run.sh — автоматизация запуска (из лекции)
Из лекции: bash-скрипт для автоматического запуска тестов и генерации отчёта.
# run.sh
#!/bin/bash
results="allure-results"
report="allure-report"
# Очистить предыдущие результаты и отчёты
rm -rf $results
rm -rf $report
# Запустить тесты с генерацией данных для отчёта Allure
pytest --alluredir=$results
# Сгенерировать HTML-отчёт Allure
allure generate $results -o $report --clean
# Открыть отчёт в браузере
allure open $report
PowerShell-аналог (Windows): Сохранить как
run.ps1.
# run.ps1
$results = "allure-results"
$report = "allure-report"
Remove-Item -Recurse -Force $results -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force $report -ErrorAction SilentlyContinue
pytest --alluredir=$results
allure generate $results -o $report --clean
allure open $report
Пример 7: вложение скриншота при ошибке Selenium
⚠️ Проверить по документации: этот паттерн выходит за рамки лекции — добавлен как практическая рекомендация для UI-тестов с Selenium.
# conftest.py
import allure
import pytest
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
outcome = yield
rep = outcome.get_result()
if rep.failed:
driver = item.funcargs.get("driver")
if driver:
allure.attach(
driver.get_screenshot_as_png(),
name="Скриншот при ошибке",
attachment_type=allure.attachment_type.PNG
)