# Test your Data

> Run schema and quality tests against your data source — Snowflake, BigQuery, Databricks, S3, Postgres, Kafka, and more.

# Test your Data

`datacontract test` connects to the data source defined in the contract's `servers` block and runs **schema** and **quality** tests to verify that the actual data complies with the data contract.

```bash
datacontract test --server production datacontract.yaml
```

## Supported connections

  
    
    SnowflakeImport a contract from your tables and test in 5 minutes
  
  
    
    Google BigQueryImport a contract from your tables and test in 5 minutes
  
  
    
    DatabricksImport a contract from Unity Catalog and test in 5 minutes
  
  
    
    Amazon RedshiftImport a contract from your tables and test in 5 minutes
  
  
    
    PostgresPostgres and Postgres-compatible (e.g. RisingWave)
  
  
    
    Amazon S3CSV, JSON, Delta, Parquet on S3 / S3-compatible storage
  
  
    
    Local filesTry it in 60 seconds — no credentials needed
  
  
    
    Amazon AthenaAthena over data in S3
  
  
    
    Apache ImpalaImpala
  
  
    
    Azure Blob / ADLSFiles on Azure Blob storage or ADLS Gen2
  
  
    
    Google Cloud StorageFiles on GCS via S3 interoperability
  
  
    
    HTTP APIJSON HTTP APIs (GET only)
  
  
    
    KafkaKafka topics (experimental)
  
  
    
    Microsoft SQL ServerSQL Server, Azure SQL, Synapse, Fabric
  
  
    
    MySQLMySQL / MariaDB
  
  
    
    OracleOracle Database
  
  
    
    Spark DataFrameIn-memory Spark DataFrames (programmatic)
  
  
    
    TrinoTrino (basic, JWT, OAuth2)
  

:::tip
Missing a source? [Open an issue on GitHub](https://github.com/datacontract/datacontract-cli/issues).
:::

Each connection requires the matching [optional dependency (extra)](../installation.md#optional-dependencies-extras), or install everything with `datacontract-cli[all]`.

## How it works

The CLI uses different engines based on the server `type`. Internally it connects with **DuckDB**, **Spark**, or a native connection, executes most checks with [_ibis_](https://ibis-project.org/) (compiling dialect-specific SQL per backend), and validates JSON with [_fastjsonschema_](https://pypi.org/project/fastjsonschema/).

Checks fall into categories you can select with `--checks`:

- `schema` — the [schema](../schema.md) attributes: presence, types, `required`, `unique`, primary keys, and `logicalTypeOptions`.
- `quality` — the [quality rules](../quality-rules/index.md) defined in the contract.
- `servicelevel` — the [service levels](../service-levels.md) defined in the contract (`slaProperties`).
- `custom` — custom checks.

Omit `--checks` to run all of them.

`--dimension` cuts across those categories instead: it selects every check that measures one aspect of data quality — the [quality rules](../quality-rules/index.md#quality-dimensions) tagged with that `dimension` plus the schema and service level checks that measure the same thing.

`--quality-id` and `--tag` go the other way and narrow the run to individual [quality rules](../quality-rules/index.md#identifying-rules): `--quality-id` runs the one rule declaring that `id`, `--tag` runs every rule declaring that tag, and neither runs any schema or service level check.

## Configuring the connection

The connection details (host, catalog, location, …) live in the contract's `servers` block; **credentials are provided as environment variables**.

```yaml
servers:
  - server: production
    type: postgres   # selects the connection engine
    host: localhost
    port: 5432
    database: postgres
    schema: public
```

Environment variables are also loaded from a `.env` file in the current working directory (or the nearest parent directory containing one). Already-set environment variables take precedence over values from `.env`.

```bash
# .env
DATACONTRACT_POSTGRES_USERNAME=postgres
DATACONTRACT_POSTGRES_PASSWORD=postgres
```

The page for each source above lists its `servers` fields and the environment variables it expects. Credentials can also come from a YAML config file (`--config-file`), the Python `Config` class, or per-request API headers; see [Configuration](../configuration.md) for all mechanisms and their precedence.

## Options

`--server`, `--schema-name`, `--checks`, `--dimension`, `--quality-id`, and `--tag` narrow down what runs. `--output` with `--output-format` writes the results to a file as `json` or `junit`, `--publish` sends them to a URL, and `--include-failed-samples` collects a small sample of the offending rows. See the full [`test` command reference](../commands/test.md).

For CI/CD pipelines, use the [`ci`](../commands/ci.md) command, which wraps `test` with annotations, summaries, and exit-code control.

## Testing only a subset of rows

On large tables, a full scan for every test run is slow and expensive. `--filter` restricts the checks to the rows matching a SQL predicate, written in the dialect of the server:

```bash
# Test only the rows ingested in the last 24 hours
datacontract test datacontract.yaml --server production --filter "ingested_at >= CURRENT_TIMESTAMP - INTERVAL '24 hours'"

# Test a specific partition
datacontract test datacontract.yaml --server production --filter "batch_id = '2026-07-31'"
```

`--filter` requires that a single schema is tested. If the contract defines several schemas, either select one with `--schema-name` or pass `--filters` with a JSON object mapping schema name to predicate:

```bash
datacontract test datacontract.yaml --server production \
  --filters '{"orders": "ingested_at >= CURRENT_DATE - 1", "line_items": "ingested_at >= CURRENT_DATE - 1"}'
```

The predicate references the columns of the schema unqualified. It applies to all row-based checks: row counts, missing/invalid values, duplicates, freshness, retention, and failed-row samples. Schema checks (column presence and types) read metadata, not rows, so a filter does not change them. Custom SQL quality checks (`quality.type: sql`) and JSON schema validation of files run the query or file as-is and are not filtered.

The [API server](../api.md)'s `POST /test` accepts the same `filter` and `filters` as query parameters.

A filtered run only makes a statement about the tested subset. So the applied filters are recorded in the test results: the `Run` carries a `filters` field (per schema), the console output prints a `Row filter:` line, and the recorded SQL of each check contains the `WHERE` clause.

## Next steps

- Run the tests from Python instead of the CLI: **[Python Library](../python-library.md)**.
- Keep the tests running automatically: **[Scheduling and CI/CD](../ci-cd.md)**.
- Roll data contracts out across a team: **[Adopting Data Contracts](../best-practices.md)**.
