> ## Documentation Index
> Fetch the complete documentation index at: https://offthepace.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Structural tests: grain and completeness across every model

> not_null, unique, and unique-combination tests are the largest test family by count and the simplest by idea every model's declared key is present once and only once.

This is the biggest single page in the CI Contract by test count and the smallest by idea: three dbt test kinds, repeated once per declared key or required column across every staging, reference, intermediate, and mart model (plus the two reference seeds). One pattern, explained once, then a gated table carrying the per-model breakdown.

<Tabs>
  <Tab title="not_null">
    The most common test in the suite. Declared on every column a downstream model or the app is allowed to assume is populated a surrogate key, a foreign key, a physics component that's supposed to exist on every valid lap. A `not_null` failure means either an upstream join silently dropped rows it shouldn't have, or a column that's genuinely optional (and should read `NULL` downstream, like `compound_component_s` on a lap with no tyre data) had its test declared too strictly.

    ```yaml theme={null}
    - name: lap_id
      description: Foreign key to stg_laps
      tests: [not_null, unique]
    ```
  </Tab>

  <Tab title="unique">
    Declared on every model's grain key the column (or surrogate) that should have exactly one row per real-world entity. `int_lap_residual_decomposed`'s `lap_id` above is the canonical case: this is the model that closes the seven-term identity, so a duplicated `lap_id` here wouldn't just be a data-quality nuisance, it would mean a lap's `driver_skill_residual_s` gets counted twice in any downstream aggregate that doesn't already correct for it.
  </Tab>

  <Tab title="unique_combination_of_columns">
    For models whose grain isn't a single surrogate column, this asserts uniqueness over the column tuple that defines a row. `mart_corner_skill_driver` is keyed on `(race_year, driver_id)`; `mart_degradation_history_envelope` is keyed on `(circuit_id, era, compound, lap_in_stint)` a pre-aggregated cell, not a lap. Two of these exist today, both on marts whose grain is a model-specific aggregate rather than one of the DAG's two universal grains (lap, sector).

    ```yaml theme={null}
    tests:
      - dbt_utils.unique_combination_of_columns:
          arguments:
            combination_of_columns: [circuit_id, era, compound, lap_in_stint]
    ```
  </Tab>
</Tabs>

<Accordion title="Why the join spine can't fan out">
  Every model between `stg_laps` and a feature mart joins back to the same lap, directly or transitively, by `lap_id` (or a sector/corner-grain extension of it). The `unique` test on every model's grain key is what makes that join spine trustworthy: if any one of the \~30 models a lap passes through on its way to `fct_lap_residuals` silently duplicated a row, every downstream `JOIN` on that model would fan out, and a single lap's contribution to a race-level or season-level aggregate would be counted more than once invisibly, since the duplicated rows would carry consistent-looking values. This is also what protects the identity itself: [`assert_lap_7term_identity`](/transform/ci/identity-closure) checks that `pace_delta_s` equals the sum of six components plus the residual on every row of `int_lap_residual_decomposed`, but that check is only meaningful once per lap. A duplicated `lap_id` would pass the identity test twice instead of failing it once.
</Accordion>

## Every model, by structural test count

| Model                                        | Family           | `not_null` | `unique` | `unique_combination_of_columns` | Total   |
| -------------------------------------------- | ---------------- | ---------- | -------- | ------------------------------- | ------- |
| `stg_circuit_info`                           | Staging          | 4          | 1        |                                 | 5       |
| `stg_events`                                 | Staging          | 1          | 1        |                                 | 2       |
| `stg_laps`                                   | Staging          | 8          | 1        |                                 | 9       |
| `stg_laps_qualifying`                        | Staging          | 8          | 1        |                                 | 9       |
| `stg_pits`                                   | Staging          | 3          | 1        |                                 | 4       |
| `stg_race_control`                           | Staging          | 2          |          |                                 | 2       |
| `stg_results`                                | Staging          | 6          | 1        |                                 | 7       |
| `stg_results_qualifying`                     | Staging          | 5          | 1        |                                 | 6       |
| `stg_sector_times`                           | Staging          | 2          | 1        |                                 | 3       |
| `stg_session_status`                         | Staging          | 3          |          |                                 | 3       |
| `stg_session_status_qualifying`              | Staging          | 4          |          |                                 | 4       |
| `stg_track_status`                           | Staging          | 3          | 1        |                                 | 4       |
| `stg_tyre_allocations`                       | Staging          | 5          |          |                                 | 5       |
| `dim_circuits`                               | Reference        | 4          | 1        |                                 | 5       |
| `dim_compounds_season`                       | Reference        | 4          |          |                                 | 4       |
| `dim_constructors`                           | Reference        | 2          | 1        |                                 | 3       |
| `dim_corners`                                | Reference        | 11         | 1        |                                 | 12      |
| `dim_drivers`                                | Reference        | 1          | 1        |                                 | 2       |
| `int_corner_metrics`                         | Physics          | 7          |          |                                 | 7       |
| `int_dirty_air_tax_component`                | Physics          | 7          | 1        |                                 | 8       |
| `int_lap_air_state`                          | Physics          | 2          | 1        |                                 | 3       |
| `int_lap_fuel_state`                         | Physics          | 1          | 1        |                                 | 2       |
| `int_lap_fuel_state_qualifying`              | Physics          | 1          | 1        |                                 | 2       |
| `int_lap_normalized_pace`                    | Physics          | 2          | 1        |                                 | 3       |
| `int_lap_proximity`                          | Physics          | 3          | 1        |                                 | 4       |
| `int_lap_telemetry_aggregates`               | Physics          | 2          | 1        |                                 | 3       |
| `int_lap_thermal_proxy`                      | Physics          | 2          | 1        |                                 | 3       |
| `int_stint_geometry`                         | Physics          | 9          | 1        |                                 | 10      |
| `int_track_geometry`                         | Physics          | 3          |          |                                 | 3       |
| `int_circuit_x_constructor_interaction`      | Pace Baselines   | 2          | 1        |                                 | 3       |
| `int_compound_cliff_predicted`               | Pace Baselines   | 3          | 1        |                                 | 4       |
| `int_constructor_structural_pace`            | Pace Baselines   | 11         | 1        |                                 | 12      |
| `int_constructor_structural_pace_qualifying` | Pace Baselines   | 2          | 1        |                                 | 3       |
| `int_field_pace_curve`                       | Pace Baselines   | 3          |          |                                 | 3       |
| `int_qualifying_push_laps`                   | Pace Baselines   | 6          | 1        |                                 | 7       |
| `int_qualifying_segments`                    | Pace Baselines   | 6          | 1        |                                 | 7       |
| `int_track_evolution`                        | Pace Baselines   | 3          |          |                                 | 3       |
| `int_constructor_car_fe`                     | Skill            | 5          | 1        |                                 | 6       |
| `int_driver_circuit_affinity`                | Skill            | 12         | 1        |                                 | 13      |
| `int_driver_circuit_era_affinity`            | Skill            | 14         | 1        |                                 | 15      |
| `int_driver_race_skill_loro`                 | Skill            | 5          | 1        |                                 | 6       |
| `int_driver_season_ratings`                  | Skill            | 8          | 1        |                                 | 9       |
| `int_era_normalized_driver_rating`           | Skill            | 12         | 1        |                                 | 13      |
| `int_synthetic_teammate`                     | Skill            | 4          |          |                                 | 4       |
| `int_corner_skill_residuals`                 | Residual         | 5          | 1        |                                 | 6       |
| `int_event_corrections`                      | Residual         | 1          | 1        |                                 | 2       |
| `int_lap_anomaly_flags`                      | Residual         | 1          | 1        |                                 | 2       |
| `int_lap_corner_inputs`                      | Residual         | 7          | 1        |                                 | 8       |
| `int_lap_residual_decomposed`                | Residual         | 5          | 1        |                                 | 6       |
| `int_lap_residual_decomposed_qualifying`     | Residual         | 3          | 1        |                                 | 4       |
| `int_lap_residual_stint_detrend`             | Residual         | 2          |          |                                 | 2       |
| `int_qualifying_decomposed`                  | Residual         | 3          | 1        |                                 | 4       |
| `int_sector_residual_decomposed`             | Residual         | 7          | 1        |                                 | 8       |
| `int_tyre_surface_vs_bulk_decoupling`        | Residual         | 5          | 1        |                                 | 6       |
| `int_constructor_deg_sensitivity`            | Strategy         | 17         | 1        |                                 | 18      |
| `int_pit_loss_circuit`                       | Strategy         | 5          | 1        |                                 | 6       |
| `int_pit_strategy_cost_curve`                | Strategy         | 12         |          | 1                               | 13      |
| `int_pit_strategy_value`                     | Strategy         | 4          | 1        |                                 | 5       |
| `int_sc_hazard_history`                      | Strategy         | 9          |          | 1                               | 10      |
| `int_stint_end_regime`                       | Strategy         | 14         | 1        |                                 | 15      |
| `dim_events`                                 | Marts            | 2          | 1        |                                 | 3       |
| `fct_ghost_car_pace`                         | Marts            | 20         | 1        |                                 | 21      |
| `fct_ghost_race_finish`                      | Marts            | 9          | 1        |                                 | 10      |
| `fct_lap_residuals`                          | Marts            | 16         | 1        |                                 | 17      |
| `fct_stint_features`                         | Marts            | 9          | 1        |                                 | 10      |
| `fct_telemetry_deltas`                       | Marts            | 9          |          |                                 | 9       |
| `mart_corner_skill_driver`                   | Marts            | 17         |          | 1                               | 18      |
| `mart_degradation_history_envelope`          | Marts            | 13         |          | 1                               | 14      |
| `circuit_reference`                          | Reference (seed) | 2          | 1        |                                 | 3       |
| `compound_cliff_params`                      | Reference (seed) | 7          |          |                                 | 7       |
| `tyre_allocations`                           | Reference (seed) | 6          |          |                                 | 6       |
| **Total**                                    |                  | 421        | 53       | 4                               | **478** |
