Новости / Тестирование данных и схем: Data Contracts, property-based-тесты и защита от порчи данных в пайплайнах
Новость
8 июня 2026

Тестирование данных и схем: Data Contracts, property-based-тесты и защита от порчи данных в пайплайнах

Arenadata в СМИ
Тестирование данных и схем: Data Contracts, property-based-тесты и защита от порчи данных в пайплайнах

Современные компании живут на данных. BI-отчёты управляют инвестициями, ML-модели влияют на кредитные решения, а витрины данных определяют стратегию продаж. При этом инфраструктура обработки данных становится всё сложнее: десятки источников, потоковые шины, ELT-пайплайны, lakehouse-архитектуры, CDC, real-time-аналитика.

И в этой сложности возникает системная проблема: данные ломаются. Варианты могут быть разные, например:

  • Меняется схема источника.
  • Появляются неожиданные null.
  • Нарушается инвариант агрегации.
  • Поток сообщений получает несовместимый формат.

В отличие от классической разработки, где unit-тесты и CI/CD давно стали нормой, в Data Engineering тестирование данных всё ещё часто ограничивается подходом «проверим на проде».

Современная data-архитектура выглядит примерно следующим образом:

Проблема: между этими слоями почти нет формальных контрактов.

В результате возможны такие ситуации, как:

  1. Изменения данных на источнике ломают пайплайны.
  2. Бизнес‑инварианты нарушаются.
  3. Ошибки обнаруживаются слишком поздно.

Меня зовут Иван Клименко, и я архитектор компании Arenadata. Эта статья о том, как можно построить модель Data Reliability (надёжность данных):

  • через Data Contracts;
  • через property-based-тестирование трансформаций;
  • через встроенные практики data-quality-мониторинга.

Я постараюсь учесть реалии российского рынка ПО и доступных open source решений.

1. Data Contracts: фундамент инженерии данных

Data Contract— это формализованная договорённость междуисточником и потребителем данных. В качестве источника может выступатьсервис, команда, приложение, система, а потребителем может быть такжесервис, приложение, другая система, команда, ML-модель. То есть в любомместе, где есть обмен данными, может быть применён Data Contract.Простыми словами, это «технический SLA», который описывает, какиеданные, в каком формате, с какой гарантией качестве и структуройпередаются от источника до получателя. Это соглашение о поведении данныхво времени, описанное формальным способом, понятным всем участникампроцесса обмена данными, это API для данных.

В современной архитектуре Data Contract содержат следующие основныекомпоненты:

  1. Структура и схемы (Schema)— какие поля, их типы (string, int, timestamp), обязательность.
  2. Семантика (Meaning)— что означает каждое поле (например, user_status = 'active').
  3. Качество данных (Data Quality)— требования к свежести, полноте, уникальности (например, user_id не может быть null).
  4. Надёжность данных или SLA (Service Level Agreement)— максимальная задержка доставки, допустимый процент потерянных записей.
  5. Контроль изменений или версионирование (Versioning)— правила обратной совместимости, сроки поддержки старых версий.
  6. Владение и ответственность (Ownership)— кто отвечает за источник данных, за исправление ошибок, за коммуникацию.
  7. Формат и транспорт (Format and services)— как и какими инструментами передаются данные.
  8. Политика доступа и безопасность (policy and security)— кто может читать данные, есть ли шифрование, кто может писать данные, применяется ли маскирование.

В зрелых системах контракт состоит из нескольких слоёв:

Когда мы говорим о Data Contract, вопрос формального описания самогоконтракта становится как нельзя актуальным. И тут невозможно обойтистороной Open Data Contract Standard (ODCS).

2. Open Data Contract Standard (ODCS) в инженерии данных

Open Data Contract Standard (ODCS)— это открытый машиночитаемыйстандарт для описания контрактов данных, оформленных какYAML-документ. Стандарт описывает структуру данных, гарантии качества,SLA, доступ и инфраструктуру публикации данных.

Изначально концепция выросла из шаблона data contract, применяемого вPayPal, а сегодня развивается как открытая инициатива сообщества Bitol.Контракт представляет собой описание всей экосистемы обработкиданных, включающее такие сферы как метаданные, схемы данных, правилакачества данных, SLA, инфраструктура размещения и связи сервисов, роли идоступы.

Контракт в стандарте ODCS представляет собой YAML-документ, состоящий изнескольких логических разделов. Каждый из них описывает разные аспектысистемы обработки и хранения данных: от базовой информации о датасете доправил качества и инфраструктуры хранения. Применение YAML позволяетперейти к концепции Data Contracts as Code, что позволяет применятьк контрактам данных те же самые практики, что и к коду: CI/CD,автоматическую валидацию, версионирование.

Раздел Fundamentals содержит базовую информацию о контракте. Здесьуказываются уникальный идентификатор контракта, название датасета илисистемы, версия контракта, домен или бизнес-область, владелец данных,текущий статус (draft, development, production). Фактически этот разделвыполняет роль паспорта контракта — он помогает понять, что это занабор данных, кто за него отвечает и на какой стадии жизненного цикла оннаходится. Данный раздел может быть легко связан с архитектурой C4, чтопозволяет выполнить интеграцию корпоративной архитектуры с физикойсистемы.

Раздел Schema описывает структуру данных, которые публикуются поконтракту. В нём задаются список полей, типы данных, обязательностьполей, ограничения (например, уникальность). По сути, это формальноеописание интерфейса данных — аналог структуры API, только длядатасетов или потоков событий. Контракт может описывать разные типысхем, табличные структуры, JSON-документы, avro-схемы. Этот разделиспользуется системами обработки данных для валидации структуры данных.

Раздел Data Quality описывает требования к качеству данных и содержиттакие проверки, как минимальное или ожидаемое количество строк,допустимый процент пропущенных значений, уникальность ключей, допустимыедиапазоны значений, свежесть данных. Эти правила позволяют автоматическипроверять, соответствует ли фактический датасет заявленным ожиданиям. Напрактике такие правила могут быть выполнены инструментами Data Quality,джобами Spark, валидаторами на языке SQL.

Раздел SLA описывает гарантии, которые предоставляет владелец данных.Обычно это частота обновления данных, максимальная задержка доставки,доступность датасета. Например, обновление каждые 5 минут, задержка неболее 10 минут или доступность 99,9%. Такие параметры особенно важны длякоманд, которые строят свои системы на основе этих данных.

Раздел Servers описывает, где именно публикуются данные. Контракт можетссылаться на разные типы источников — топики Kafka, таблицы вLakehouse, базы данных, API-эндпойнты. Таким образом, контракт связываетлогическое описание данных со своей физической инфраструктурой.

Раздел Roles определяет роли пользователей и команды, которыевзаимодействуют с данными. Здесь могут быть описаны владелец данных,команда поддержки, потребители данных, администраторы. Этот раздел можетвстроить контракт в процессы управления жизненным циклом (DataGovernance), управления доступом.

Кроме стандартных полей, контракт может содержать произвольныедополнительные свойства. Они используются для интеграции с конкретнымиплатформами, например системами Data Catalog, инструментами DataQuality, внутренними платформами DataOps. Это позволяет адаптироватьстандарт ODCS под особенности конкретной инфраструктуры.

Пример ODCS data contract:

yamlapiVersion: v3.0.0kind: DataContractid: orders_v1name: Orders datasetversion: 1.0.0domain: ecommercestatus: productionowner:  name: Data Platform Team  email: data-platform@company.comschema:  type: table  fields:    - name: order_id      type: string      required: true      unique: true    - name: customer_id      type: string    - name: order_timestamp      type: timestampdataQuality:  - type: freshness    threshold: 1h  - type: rowCount    min: 1000sla:  availability: 99.9%  updateFrequency: 5mservers:  - type: kafka    topic: orders_events  - type: lakehouse    table: sales.orders

Наиболее известный инструмент — консольная утилита datacontract-cli.(https://github.com/datacontract/datacontract-cli).Предоставляет возможность валидации контрактов, генерации документации, проверкинаборов данных, интеграции с CI/CD, генерации схем (SQL, Avro).

Можно рассмотреть применение ODCS в современных архитектурах обработки ихранения данных, например в таком варианте:

Например, в Spark контракт можно использовать на нескольких уровнях:

Проверка схемы:

pythoncontract_schema = load_odcs_schema("orders_contract.yaml")spark_df = spark.read.parquet("orders")validate_schema(spark_df, contract_schema)

Проверку качества данных можно выполнить по показателям: row count, nullratio, uniqueness.

Архитектурный паттерн может иметь следующее представление:

В случае интеграции с Kafka контракт используется как формальный APIсобытия. Producer перед публикацией события выполняет проверку схемы, обязательность полей. Consumer валидирует входящие события против контракта. Реализуется защита от изменения данных на входе и контрольэволюции схем.

Во Flink контракты полезны для проверки на этапе извлечения данных, контроля за схемами данных на этапах трансформации, мониторинга качества данных, например по такому паттерну:

В Lakehouse контракты применяются для управления схемой таблиц, контроляизменений и описания продукта, например по такому принципу:

При этом контракт может описывать таблицу, SLA обновления или построенияотчётности, допустимые значения, правила качества.

ODCS может быть легко интегрирован с инструментами Data Quality, по факту контракт становится единой декларацией правил качества.

Также стандарт хорошо вписывается в пайплайны DataOps. Типовой рабочий процесс можно представить так:

Преимущества стандарта:

  • Формат, удобный для компьютера (Machine-readable governance), — контракты можно автоматически проверять.
  • Контракт как код (Data Contracts as Code) — контракты версионируются в Git, для них можно создать редактор.
  • Унификация экосистемы работы с данными — один формат для потоковой и батчевой обработки, для Lakehouse, баз данных и API.
  • Совместимость с Data Mesh — ODCS хорошо подходит для разделения ответственности за данные (data product ownership).

Несмотря на преимущества, стандарт ещё развивается, не имеетуниверсального инструмента для хранения самих данных, предоставленияконтракта по API и контроля за эволюцией контракта, не имеет реализациидля валидации данных на языках, популярных в Big Data, требуетсамостоятельной интеграции с инструментами обработки данных и контролякачества данных.

ODCS — это фактически «OpenAPI для данных». Он превращает датасет илипоток событий в формальный API с гарантией схемы, качества и SLA. Но насегодняшний день отсутствие нативной интеграции с Kafka, Spark, Flink идругими популярными сервисами мира Big Data является блокирующимфактором применения его в экосистемах, так требуется ресурсоёмкаяразработка на каждом этапе, где есть необходимость взаимодействия состандартом.

Поговорим о текущих реализациях систем, призванных исполнить рольконтрактов данных. И для начала рассмотрим, как обстоят дела в системахпотоковой обработки и батчевых инструментах для организации Lakehouse.

3. Схемы данных в Kafka и контроль за структурой данных в Lakehouse

В архитектурах потоковой обработки данных на базе брокера Kafka контрактможет быть зафиксирован в виде схемы AVRO/Protobuf. Доступ к немуосуществляется через специальный компонент — Schema Registry.Консьюмер уверен, что данные, полученные от топика, были сериализованыпоставщиком данных по схеме, которую предоставил Scherma Registry.Данные могут быть корректно десериализованы по указанной схеме. Также онуверен, что, если схема изменится, она будет следовать правилам эволюциисхем. Замечу, что описание схемы не есть Data Contract в полном смысле,а лишь охватывает часть его. В общем виде применение схем данных можно отразить следующим образом:

Системы не являются статичными, данные могут быть изменены в любоймомент. Поэтому важно не только хранить схему, но и управлять еёэволюцией. Обычно выделяют следующие виды совместимости схем данных:

  • Backward compatible— новые поля добавляются, старые не ломаются.
  • Forward compatible— потребители игнорируют неизвестные поля.
  • Full compatible— строгий контроль обеих сторон.

Это особенно критично для таких отраслей, как финтех, ритейл, телеком,например при обработке банковских потоков транзакций, телеком-событий,ритейл-заказов.

Рассмотрим open source решения для хранения схем данных и управленияими.

Confluent Schema Registry — централизованное хранилище схем длясообщений Kafka. Поддерживает Avro, Protobuf, JSON Schema. Из коробкиреализовано версионирование схем, проверка backward/forward/fullcompatibility, есть REST API для интеграции в CI/CD. Применяется вархитектурах потоковой обработки данных, в системах событийнойобработки, микросервисных экосистемах. Это фактически стандарт де-фактодля «контрактов» в kafka-мире.

Apicurio Registry — альтернатива Confluent Schema Registry,совместимый по API. Реализована поддержка Avro, Protobuf, JSON Schema,есть поддержка артефактов API, есть REST-интерфейс. Преимуществом посравнению с предыдущим является возможность хранить схемы данных внеKafka, например в базе данных или в локальном файловом хранилище. Такжеиз коробки есть веб-интерфейс. Если у вас не применяется Kafka, но вырешили применять схемы данных — это ваш выбор.

Redpanda Schema Registry — встроенный реестр схем, которыйпоставляется как часть платформы Redpanda, полностью совместимый по APIс Confluent Schema Registry. Реализована поддержка Avro, Protobuf, JSONSchema. В отличие от отдельных решений, Schema Registry являетсявстроенным компонентом самого Redpanda, что исключает необходимостьразвёртывания и обслуживания внешнего сервиса. Преимуществом посравнению с альтернативами является отсутствие внешних зависимостей(например, Zookeeper), единая точка управления в составе кластераRedpanda, а также высокая производительность благодаря нативному коду наC++. Из коробки доступен веб-интерфейс через Redpanda Console. Если увас уже используется Redpanda или вы рассматриваете переход с Kafka наболее современную платформу с меньшими операционными затратами — этоваш выбор. Ключевое отличие от Apicurio в том, что Redpanda не хранитсхемы вне кластера — они хранятся внутри самого Redpanda (встроенноехранилище), что упрощает архитектуру, но не позволяет использоватьвнешние БД или файловые системы как бэкэнд. Это компромисс междупростотой эксплуатации и гибкостью хранения.

В архитектуре Lakehouse контракты данных играют роль механизма согласования между слоями хранения (data lake) и обработки (warehouse/compute). В отличие от классических DWH, где схема данныхжёстко фиксирована, Lakehouse предполагает более гибкую работу с данными— и именно поэтому контракты становятся критически важными.

В архитектурах, основанных на обработках батчей или наборов датасетов,ключевую роль играют современные табличные форматы, такие как ApacheIceberg, Delta Lake, Apache Hudi. Они фактическистановятся технической основой реализации контрактов данных на уровнехранения данных. Эти форматы добавляют в data lake свойства, которыераньше были характерны только для хранилищ:

  1. Эволюция схемы (schema evolution) позволяет изменять структуру таблиц без разрушения существующих пайплайнов. Можно выполнять добавление новых колонок, изменение типов, выполнять переименование полей. С точки зрения Data Contract это означает, что контракт можно расширять без изменений, нарушающих работу существующих потребителей данных (breaking changes), изменения становятся управляемыми и предсказуемыми.
  2. Версионирование данных (versioning) позволяет фиксировать каждое изменение таблицы как новой версии (snapshot). Это даёт возможность отката изменений, воспроизводимость аналитики, аудит изменений. В контексте контрактов можно привязать потребителя к конкретной версии, безопасно тестировать новые версии схемы.
  3. ACID-операции гарантируют поддержку атомарности, согласованности, изолированности и долговечности. Не может быть «частично записанных» данных, реализуется корректная работа параллельных процессов, обеспечивается консистентность чтения. Для Data Contract это означает гарантированное соблюдение целостности данных и отсутствие скрытых нарушений контракта из-за записи различными участниками процесса.

Благодаря этим возможностям Lakehouse позволяет реализовать контракт нетолько на уровне документации, но и на уровне самой системы хранения:

  • схема становится частью контракта и контролируется платформой;
  • изменения проходят через механизм версионирования;
  • потребители защищены от неожиданных изменений;
  • можно внедрять автоматические проверки совместимости.

Иначе говоря, табличные форматы превращают Data Contract из«договорённости» в конкретную техническую реализацию.

Как я говорил ранее, в потоковой обработке мире (например, с ApacheKafka) роль контракта часто централизована через Schema Registry. ВLakehouse всё устроено более «распределённо»: контракт размазан междуформатом таблиц, каталогом (catalog), слоем управления данных иинструментами качества. Но при этом есть вполне конкретный стек opensource решений.

Для уровня хранения контракт описан таблицей. Физически реализуется врешениях Apache Iceberg, Delta Lake, Apache Hudi. Как контракт они даютконтроль эволюции схем, версионирование структуры, обновление схемы призаписи, историчность изменений.

Если в потоковой обработке есть Schema Registry, то в Lakehouse его рольиграют каталоги. «Реестр контрактов» может быть реализован с помощьюProject Nessie, Apache Hive Metastore.

Project Nessie — активно развивающийся проект, он является наиболееблизким аналогом Schema Registry в мире Lakehouse. Обеспечиваетверсионирование (branches, commits), поддерживает изоляцию изменений(dev- / prod-ветки), позволяет провести откат и выполняет контрольэволюции схем и управление ей. Здесь контракт становится версионируемым,готовым к интеграции как код. Сервер Nessie хранит метаданные о версияхи ссылках на физические данные, находящиеся в хранилище объектов.Клиенты взаимодействуют через REST-API или SDK (например, для Java илиPython), что позволяет интегрировать систему с существующимиETL-процессами.

Но контракт — это не только схема, но и семантика + доступ +происхождение данных (lineage). Мы можем опираться на такие решения, какOpenMetadata, DataHub, Apache Atlas. Они позволят добавить к контрактусемантику или описание полей, определить владельца, понять, откудапришли данные (lineage), определить политики доступа. Это делает DataContract понятным людям, а не только системам.

OpenMetadata позволяет хранить схемы таблиц, при этом естьверсионирование, и обладает широкими возможностями по интеграции сдругими инструментами. При этом контракт трактуется как часть моделиуправления данными предприятия, учитывающей схему, владельца системы,наличие SLA и политики. Подходит для Data Mesh и DataOps-подхода.

DataHub — это не только хранение схем/контрактов, это платформауправления метаданными. Реализованы версионирование схем, хранениеистории изменений, есть управление совместимостью, доступны интеграции сSpark, Kafka, BI. Если контракт рассматривается как часть общей моделиуправления данными предприятия, то этот сервис может быть вам полезным вприменении построения Lakehouse.

Apache Atlas — это платформа управления метаданными и data governanceиз экосистемы Hadoop. Она ориентирована на централизованное хранениеметаданных и управление ими, включая схемы, таблицы, пайплайны ибизнес-термины. Реализованы функции lineage (отслеживание происхожденияданных), классификация данных (в том числе чувствительных), политикидоступа и интеграции с инструментами обработки данных (Hive, Spark,Kafka). Поддержка версионирования и отслеживания изменений позволяетиспользовать Atlas как основу для контроля эволюции данных. Есликонтракт рассматривается как часть корпоративного подхода к управлениюданными, включая безопасность и соответствие требованиям, этот сервисможет быть полезным в вашей инфраструктуре.

Контракт без проверок — это просто текст. Рассмотрим, кто можетвыполнить валидацию, проверить, соблюдается ли контракт участникамипроцесса. Тут нам могут помочь такие решения, как Great Expectations,Soda Core, Deequ. Их роль — проверка схемы, проверка значений,контроль SLA (freshness, completeness) в процессе выполнения, в runtime.

Great Expectations — это фреймворк для тестирования и валидацииданных, в котором проверки описываются в виде декларативных «ожиданий»(expectations). Позволяет контролировать соответствие данных контракту:проверка схемы, диапазонов значений, уникальности и полноты.Поддерживает документирование качества данных и интеграцию с пайплайнами(Spark, SQL, Airflow). Хорошо подходит как инструмент runtime-проверкиData Contract.

Soda Core — это легковесный инструмент для мониторинга и тестированиякачества данных с использованием SQL-ориентированных правил (SodaCL).Позволяет быстро описывать проверки на уровне таблиц и колонок,отслеживать аномалии и контролировать SLA по данным. Часто используетсядля встроенного контроля качества в ELT/ETL-процессах и как часть CI/CDдля данных.

Deequ — это библиотека для проверки качества данных на базе ApacheSpark, разработанная Amazon. Предоставляет программный API(Scala/Python) для описания правил валидации, профилирования данных иавтоматического выявления аномалий. Подходит для крупных обработокдатасетов и сценариев, где контроль качества должен быть встроеннепосредственно в вычислительные пайплайны.

Контракт должен соблюдаться не только при хранении, но и в вычислениях.Для уровня вычислений можно применять известные решения Apache Spark,Trino, Apache Flink. В код процессов обработки можно сразу заложитьпроверку схем при чтении/записи, выполнить интеграцию сIceberg/Hudi/Delta, выполнить тесты качества данных. Здесь контрактстановится частью пайплайна.

Таким образом, в Lakehouse Data Contract — это не сервис, а композициятабличных форматов, каталогов, управления данными и качеством и слоявычислений и обработки.

4. Property-Based Testing для трансформаций

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

Классический тест:

pythonassert transform({"price": 100, "tax": 20}) == 120

Он проверяет конкретный кейс. Но что, если:

  • tax отрицательный?
  • price = None?
  • значения экстремальные?

В Data Engineering пространство входных данных огромно и нестатично. Яуже говорил ранее, что системы эволюционируют и, соответственно,меняются данные, поступающие от них. Именно здесь появляется property-based testing (PBT).

Что же такое property-based-тестирование? Давайте разбираться.

Вместо проверки конкретных значений мы проверяем свойства(invariants), например что сумма после агрегации не меняется,количество уникальных ключей сохраняется, даты не уходят в будущее,валютные курсы > 0 и так далее.

Тест автоматически генерирует множество случайных входных данных.

В Python это удобно делать через Hypothesis(https://hypothesis.readthedocs.io/en/latest/quickstart.html).

Например, выполним проверку инварианта агрегации. Свойство: сумма поключам до и после группировки должна совпадать.

pythonfrom hypothesis import givenimport hypothesis.strategies as st@given(st.lists(st.integers(min_value=0, max_value=100)))def test_sum_invariant(values):    original_sum = sum(values)    aggregated_sum = sum(values)  # имитация трансформации    assert original_sum == aggregated_sum

В spark-среде property-подход реализуется через декларативные проверки,например с использованием Deequ (https://github.com/awslabs/deequ).Тут надо сразу отметить, что Deequ — не генератор тестовых данных (какHypothesis), а движок декларативных проверок свойств (constraints) над большими датафреймами.

Поэтому PBT в Spark + Deequ выглядит примерно следующим образом. Сначалаформулируется описание инвариантов (properties), далее генерируется илиподаётся набор входных данных и выполняется проверка, что свойствавсегда выполняются.

Рассмотрим PBT для агрегации в Spark + Deequ на практическом примере.

Допустим, у нас есть следующий пайплайн:

  1. Загружается таблица транзакций:
    _id | amount | currency
  2. Выполняется агрегация:
    by user_id -> sum(amount)

Описываем инварианты (properties):

  1. Общая сумма amount до и после агрегации должна совпадать.
  2. Количество уникальных user_id после агрегации равно количеству уникальных user_id до.
  3. Все агрегированные суммы ≥ 0.
  4. Не должно появляться null.

Это и есть свойства, которые мы будем тестировать в ходе проверки.

Реализация на Spark + Deequ (Scala) выглядит следующим образом:

scalaimport org.apache.spark.sql.SparkSessionimport org.apache.spark.sql.functions._import com.amazon.deequ.checks._import com.amazon.deequ.VerificationSuiteimport com.amazon.deequ.VerificationResultval spark = SparkSession.builder()  .appName("PBT-Deequ-Example")  .master("local[*]")  .getOrCreate()import spark.implicits._

Вместо одного фиксированного набора — генерируем разные данные:

scalaval data = Seq(  (1, 100.0, "RUB"),  (1, 50.0, "RUB"),  (2, 200.0, "RUB"),  (3, 0.0, "RUB")).toDF("user_id", "amount", "currency")

В продвинутом варианте можно генерировать данные случайно или черезфреймворк и передавать в Spark.

Допустим, у нас будет следующая трансформация:

scalaval aggregated = data  .groupBy("user_id")  .agg(sum("amount").alias("total_amount"))

Проверка инвариантов через Deequ.

Property 1: суммы до и после совпадают. Пример кода:

scalaval originalSum = data.agg(sum("amount")).first().getDouble(0)val aggregatedSum = aggregated.agg(sum("total_amount")).first().getDouble(0)assert(originalSum == aggregatedSum)

Это property-test на логичное поведение пайплайна.

Property 2–4: декларативные проверки через Deequ могут бытьреализованы, например, вот так:

scalaval check = Check(CheckLevel.Error, "Aggregation invariants")  .isComplete("user_id")          // нет null  .isComplete("total_amount")     // нет null  .isNonNegative("total_amount")  // >= 0  .hasSize(_ > 0)                 // датафрейм не пуст

Запуск проверки:

val result = VerificationSuite()  .onData(aggregated)  .addCheck(check)  .run()assert(result.status == com.amazon.deequ.VerificationResult.Status.Success)

Где же здесь property-based-подход? Он заключается в том, чтопроверяются свойства, а не конкретные значения:

Example-basedProperty-based
user 1 = 150сумма не изменилась
user 2 = 200нет отрицательных значений
3 строкиуникальность ключей сохраняется

Добавим генерацию данных для проверки трансформаций и сделаем этипроверки в цикле:

scalafor (i <- 1 to 100) {  val randomData = generateRandomDataset(spark)  val transformed = transform(randomData)  verifyInvariants(randomData, transformed)}

Где verifyInvariants содержит:

  • проверку суммы,
  • уникальности,
  • декларативные Deequ constraints.

Это уже полноценный property-based-стресс-тест пайплайна.

Рассмотрим пример бизнес-инварианта. Допустим, что после дедупликации поtransaction_id количество строк не превышает исходного количества исумма не увеличивается:

scalaCheck(CheckLevel.Error, "Dedup invariant")  .hasSize(_ <= originalCount)  .isNonNegative("amount")

Возможности Deequ позволяют перейти к аппроксимациям метрик:

scala.hasApproxQuantile("amount", 0.5, _ > 0)

Это уже property уровня распределения данных, а не просто проверки типа.

PBT будет полезен при тестировании дедупликации, оконных функций,сложных join, расчётов метрик, при CDC-процессах. PBT позволяет выявитьedge-cases до продакшена.

5. Data Quality как непрерывный процесс

В пайплайнах контракт — это входной контроль, тесты до внедренияпайплайна — это защита логики. Но данные могут портиться уже в проде.И здесь вступает в работу data-quality-мониторинг.

Обычно выделяют следующие ключевые измерения качества данных:

  1. Completeness— заполненность полей.
  2. Uniqueness— отсутствие дубликатов.
  3. Consistency— соблюдение бизнес-правил.
  4. Freshness— своевременность загрузки.
  5. Validity— соответствие допустимым диапазонам.

Можно применять ранее упомянутые инструменты, такие как GreatExpectations, OpenMetadata, Data Hub. Многие компании интегрируютвстроенные DQ-механизмы в ETL, добавляют слой правил поверх Spark,реализуют собственные фреймворки контроля схем.

При импортозамещении популярна стратегия, когда применяется Open Sourceвместе с собственной обвязкой контроля данных, внедрение Schema Registryв корпоративный контур, интеграция DQ в CI/CD.

6. Рассмотрим интеграцию в CI/CD и DataOps

Можно выделить разные подходы к организации интеграции контрактов.Рассмотрим подход, основанный на контракте, включающий следующиеэлементы:

  1. Описывается контракт.
  2. Проверяется совместимость.
  3. Только после этого формируется источник данных, пайплайны обработки, слои хранения.

Контракт хранится в Git. Проверка совместимости — в CI. Нарушение — блокирует merge. После проверки контракт помещается в Registry, либо к нему обеспечивается доступ для исполняемого иным способом.

Следующий подход — Test-Driven Data Pipelines, в котором можновыделить минимальный набор тестов — unit-тесты трансформаций,property-based-тесты (PBT), проверка схем, интеграционные тесты стестовым датасетом, DQ-проверки на уровне стейджинговых данных.

Также легко реализуемый подход — защита от порчи данных, при котором основными элементами являются:

  • Canary-загрузка — постепенное и безопасное внедрение изменений в пайплайн обработки данных.
  • Автоматический откат при нарушении SLA.
  • Оповещение при превышениях метрик качества.
  • Версионирование таблиц (lakehouse-подход).

Мы рассмотрели общее описание контрактов данных, прошлись потехнологиям в потоковой и пакетной обработке, увидели, какобеспечивать контракты в Lakehouse, говорили о тестах и подходахCI/CD.

Заключение

Современный стек обработки данных должен включать:

  1. Контрактный слой— схемы, системы хранения у контроля эволюцией (registry), версионирование.
  2. Тестовый слой— классические unit-тесты, PBT, валидации схем.
  3. Слой мониторинга— DQ-метрики, системы оповещений и алерты, дашборды.
  4. Слой управления данными— каталог, эволюция данных (lineage), SLA.

Это и есть зрелая модель DataOps. Конечно, при реализации требуется впервую очередь оценивать необходимость и ресурсоёмкость внедрениякаждого из этапов.

Тестирование данных, описание данных, внедрение метаданных над данными— это не дополнительная активность. Это необходимый уровень зрелостисовременной платформы обработки данных, важная часть Data Engineering.Каждый компонент позволяет закрыть большой список возможных рисков:

  • Data Contracts→ защищают интерфейс данных;
  • property-based-тесты→ защищают логику трансформаций;
  • data-quality-мониторинг→ защищает продакшен.

В российских реалиях, где активно развивается импортозамещение и растётпотребность в on-premise-инфраструктуах в целях Big Data, именносистемный подход к качеству данных становится конкурентнымпреимуществом.

Данные должны быть не просто доступными. Они должны быть предсказуемыми,проверяемыми и управляемыми. И это уже зона ответственности архитекторови инженеров данных.

Источник: ВАйти