Test Python
In this guide, you'll learn how to add data quality and validation tests to your Python Components, create dedicated Python Test Components, and implement specialized tests for custom validation logic.
Prerequisites
- Ascend Flow
For a comprehensive overview of test types and when to use them, see our Tests concept guide.
Test behavior
Tests accept a severity parameter that can be set to error or warn.
error is the default severity, meaning that failed tests cause the entire Component to fail. To log warnings instead of failing, set severity="warn":
test("not_null", column="id", severity="warn")
Native tests in Transforms
Add native tests to Python Components by including them in the @transform decorator:
from ascend.resources import transform, test, ref
@transform(
inputs=[ref("source")],
tests=[
test("not_null", column="id"),
test("count_equal", count=1000, severity="warn"),
],
)
def my_transform(source, context):
return source
Column-level tests
Validate individual columns by specifying the column parameter:
Component-level tests
Validate the entire dataset by omitting the column parameter:
from ascend.resources import transform, test, ref
from ascend.common.formats import ibis_table
@transform(
inputs=[ref("orders")],
materialized="table",
tests=[
test("count_greater_than", count=0),
test("count_less_than", count=1000000),
test("combination_unique", columns=["order_id", "line_item_id"]),
],
)
def validated_orders(orders: ibis_table, context) -> ibis_table:
return orders
Generic tests
Generic tests are reusable test functions that can be applied to any Component. Define them once and reference them in multiple places.
Define a generic test
Create a Python file with the @generic_test decorator:
Reference generic tests
Reference generic tests in your Component's YAML configuration:
Singular tests
Singular tests validate data across one or more Components. Use them for cross-component validation, referential integrity checks, and complex business rules.
Basic singular test
Referential integrity test
Multiple validations in one test
Singular tests can yield multiple test results:
Asset tests
Asset tests run during the execution of a Read Component, validating data as it's ingested. Use them for source data validation.
Test results
Test functions return TestResult objects:
from ascend.resources import TestResult
# Passing test
TestResult.empty("test_name", True)
# Failing test with message
TestResult.empty("test_name", False, "Error description")
# Failing test with sample data
TestResult("test_name", False, failing_rows_dataframe, "Error description")
Test result states:
- PASS: Test passed
- FAIL_WARN: Failed with
severity="warn"(processing continues) - FAIL_ERROR: Failed with
severity="error"(halts processing)
Best practices
- Use appropriate severity: Set
severity="error"for critical validations that should halt processing,severity="warn"for informational checks - Return sample data: Include sample failing rows in test results to aid debugging
- Keep tests focused: Each test should validate one specific condition
- Use descriptive names: Test names appear in results; make them clear and actionable
- Test at the right level: Use column tests for value validation, Component tests for aggregations, singular tests for cross-component checks
Next steps
- Explore SQL tests
- Learn about YAML tests
- Review the Tests concept guide