Тесты кодовых моделей¶
Кодовую модель удобно проверять локально, не публикуя изменения в репозиторий:
для этого рядом с model.py и model.yml размещается файл тестов, который
запускает модель на локальном Spark с тестовыми данными.
Подготовка¶
Для локального запуска нужны Java и pyspark — они устанавливаются вместе с клиентской библиотекой при настройке рабочего места:
Файл тестов¶
Файл тестов называется test_<имя модели>.py и располагается в папке модели.
В нём принято описывать два теста: проверку метаданных и проверку самого кода модели.
import datetime
from pathlib import Path
import pytest
from aw_client.data_source import DataSourceTable
from aw_client.models.code import DataSourceBindings, DataSourceBindingToTestTable
from aw_client.models.code.runtime import run_code_model, read_code_model_meta
@pytest.fixture
def data_sources():
"""Привязка источников к тестовым таблицам"""
return DataSourceBindings(
bindings={
"products": DataSourceBindingToTestTable(
table=DataSourceTable(
rows=[
{"id": 1, "name": "Товар 1"},
]
)
),
"customers": DataSourceBindingToTestTable(
table=DataSourceTable(
rows=[
{"id": 1, "name": "Покупатель 1"},
]
)
),
"orders": DataSourceBindingToTestTable(
table=DataSourceTable(
rows=[
{
"id": 1,
"product_id": 1,
"customer_id": 1,
"summa": 1000,
"created_at": datetime.datetime(2025, 1, 1, 0, 0, 0),
}
]
)
),
}
)
def test_meta():
"""Проверка метаданных модели"""
read_code_model_meta(Path(__file__).parent)
def test_model(data_sources):
"""Проверка модели на тестовых данных"""
model_root = run_code_model(Path(__file__).parent, data_sources=data_sources)
assert set(model_root.df.columns).issuperset(
{
"id",
"product_id",
"customer_id",
"summa",
"name",
"name_1",
"order_day",
"order_month",
"order_year",
"summa_with_discount",
}
)
assert model_root.df.count() == 1
- Фикстура описывает привязку источников: для каждого источника из
model.ymlзадаётся тестовая таблица с данными. - Тест проверяет, что файл
model.ymlкорректен. - Тест запускает модель и проверяет результат: состав колонок и число строк.
- Ассерты формулируются под вашу предметную область — здесь проверяется состав колонок итогового датафрейма.
Тест метаданных: test_meta¶
Тест вызывает read_code_model_meta(Path(__file__).parent) — эта функция читает
model.yml и валидирует его по схеме: обязательные поля, допустимые значения
type и т.д. Если метаданные некорректны, тест упадёт с понятным сообщением.
Тест модели: test_model¶
Основной тест запускает модель функцией run_code_model():
| Параметр | Описание |
|---|---|
model_path |
Путь к папке модели — обычно Path(__file__).parent |
data_sources |
Привязки источников: объект DataSourceBindings с тестовыми таблицами |
Функция:
- читает метаданные из
model.yml; - создаёт локальную сессию Spark;
- импортирует
model.pyи вызываетmain()с заявленными в сигнатуре параметрами; - вычисляет итоговый датафрейм и возвращает корневой узел графа — у него доступны
df(итоговый датафрейм) и обычные методы Spark для проверок.
Тестовые данные: DataSourceBindingToTestTable¶
Каждый источник из model.yml привязывается к тестовой таблице
DataSourceBindingToTestTable:
| Параметр | Описание |
|---|---|
table |
Объект DataSourceTable со списком строк rows — словари «имя колонки: значение» |
data_source_id |
Необязательно. Идентификатор источника в AW — для сценария запуска на реальном сервере |
Тестовые строки должны покрывать ключевые сценарии вашей трансформации: граничные
значения, отсутствующие связи (для left join), пустые значения полей.
Запуск тестов¶
Тесты запускаются стандартным pytest из папки репозитория:
В VS Code тесты можно запускать из боковой панели Testing — подробности см. в разделе тестов etl-блоков — механика запуска идентична.
Первый запуск медленный
При первом запуске Spark инициализирует локальное окружение — это занимает заметное время. Последующие запуски в той же сессии выполняются быстрее.
Что проверять в тестах¶
Рекомендуемый минимальный набор проверок:
- метаданные —
test_metaвсегда включайте в файл тестов; - структура результата — состав колонок итогового датафрейма соответствует
списку полей из
model.yml; - бизнес-логика — конкретные значения: суммы, агрегаты, результаты соединений;
- крайние случаи — пустые источники, отсутствующие ключи соединения.
Публикация¶
Тесты — часть репозитория: они помогают не только вам, но и коллегам при code review. Рабочий процесс с ветками и merge в production-ветку описан в разделе Git-репозитории.