Skip to content

Add has_no_sequence_gaps dataset-level check - #1456

Open
ghanse wants to merge 4 commits into
mainfrom
ghanse/has-no-sequence-gaps
Open

Add has_no_sequence_gaps dataset-level check#1456
ghanse wants to merge 4 commits into
mainfrom
ghanse/has-no-sequence-gaps

Conversation

@ghanse

@ghanse ghanse commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Changes

Adds a new dataset-level check has_no_sequence_gaps(column, step=1, group_by=None) that detects gaps in a numeric sequence.

This follows the approach established in #1370 for has_no_gaps_per_time_window. Distinct values are bucketed onto a fixed grid of step, a windowed lead() finds the next bucket, and a gap is flagged whenever the next bucket starts more than one step after the current bucket. Gaps are reported for every row in the last present bucket before the gap.

The bounds of a sequence are its own lowest and highest present values. When group_by is provided, gaps are detected independently within each group (e.g. to detect missing primary keys by source system) and each group is bounded by its own lowest and highest value.

Linked issues

Tests

  • manually tested
  • added unit tests
  • added integration tests
  • added end-to-end tests
  • added performance tests

Documentation and Demos

  • added/updated demos
  • added/updated docs
  • added/updated agent skills

This pull request and its description were co-written by Isaac.

Adds a dataset-level check that flags gaps in a numeric sequence, i.e. expected
values that are missing between values that are present (for example no invoice
numbered 1002 while 1001 and 1003 are present). This is the numeric counterpart
of has_no_gaps_per_time_window: distinct values are bucketed onto a fixed grid
of `step` aligned to zero, a window lead() finds the next present bucket, and a
gap is flagged wherever the next present bucket starts more than one step after
the current one. Since a missing value has no row to attach a violation to, the
gap is reported on every row in the last present bucket before the gap.

With the default `step` of 1 the grid is the integers, so detection is exact
sequence-gap detection - the common case for invoice numbers, ledger entries and
sequence IDs.

Only interior gaps are detected. The bounds of a sequence are its own lowest and
highest present values, so missing values beyond either end are not reported
because there is no row to anchor them to. When `group_by` is provided, gaps are
detected independently within each group and each group is bounded by its own
lowest and highest present value, so a group whose sequence simply stops earlier
than another group's is not flagged. Null values are ignored and pass with no
violation.
@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 25.00000% with 18 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.51%. Comparing base (010f070) to head (2b1ad08).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/databricks/labs/dqx/check_funcs.py 25.00% 18 Missing ⚠️

❗ There is a different number of reports uploaded between BASE (010f070) and HEAD (2b1ad08). Click for more details.

HEAD has 8 uploads less than BASE
Flag BASE (010f070) HEAD (2b1ad08)
unit 2 1
mcp 2 1
anomaly 2 1
anomaly-serverless 2 1
integration-serverless 2 0
integration 2 0
Additional details and impacted files
@@             Coverage Diff             @@
##             main    #1456       +/-   ##
===========================================
- Coverage   92.51%   78.51%   -14.01%     
===========================================
  Files         141      141               
  Lines       13577    13601       +24     
  Branches      151      151               
===========================================
- Hits        12561    10679     -1882     
- Misses        946     2855     +1909     
+ Partials       70       67        -3     
Flag Coverage Δ
anomaly 0.00% <0.00%> (-51.94%) ⬇️
anomaly-serverless 51.86% <8.33%> (-0.09%) ⬇️
integration ?
integration-serverless ?
mcp 78.31% <ø> (-1.36%) ⬇️
unit 65.46% <25.00%> (+0.46%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

❌ 966/977 passed, 1 flaky, 11 failed, 49 skipped, 8h14m8s total

❌ TestDataContractIntegration.test_generate_rules_with_text_processing: litellm.exceptions.RateLimitError: litellm.RateLimitError: DatabricksException - {"error_code":"REQUEST_LIMIT_EXCEEDED","message":"REQUEST_LIMIT_EXCEEDED: Exceeded workspace input tokens per minute rate limit for databricks-claude-sonnet-4-5. Work with your Databricks account team to request a higher FMAPI rate limit tier."} (28.881s)
... (skipped 528056 bytes)
y: <function is_geo_intersects at 0x7f29decd9760>
15:33 DEBUG [databricks.labs.dqx.checks_resolver] Resolving function: is_geo_touches
15:33 DEBUG [databricks.labs.dqx.checks_resolver] Function is_geo_touches resolved successfully: <function is_geo_touches at 0x7f29decd9800>
15:33 DEBUG [databricks.labs.dqx.checks_resolver] Resolving function: is_geo_within
15:33 DEBUG [databricks.labs.dqx.checks_resolver] Function is_geo_within resolved successfully: <function is_geo_within at 0x7f29decd98a0>
15:33 DEBUG [databricks.labs.dqx.checks_resolver] Resolving function: custom_row_check_func_global_registered
15:33 DEBUG [databricks.labs.dqx.checks_resolver] Function custom_row_check_func_global_registered resolved successfully: None
15:33 WARNING [databricks.labs.dqx.llm.llm_utils] Check function custom_row_check_func_global_registered not found in the registry
15:33 DEBUG [databricks.labs.dqx.checks_resolver] Resolving function: custom_dataset_check_func_with_ref_dfs
15:33 DEBUG [databricks.labs.dqx.checks_resolver] Function custom_dataset_check_func_with_ref_dfs resolved successfully: None
15:33 WARNING [databricks.labs.dqx.llm.llm_utils] Check function custom_dataset_check_func_with_ref_dfs not found in the registry
15:33 DEBUG [databricks.labs.dqx.checks_resolver] Resolving function: _check_requires_dbr_v1
15:33 DEBUG [databricks.labs.dqx.checks_resolver] Function _check_requires_dbr_v1 resolved successfully: None
15:33 WARNING [databricks.labs.dqx.llm.llm_utils] Check function _check_requires_dbr_v1 not found in the registry
15:33 DEBUG [databricks.labs.dqx.checks_resolver] Resolving function: does_not_contain_pii
15:33 DEBUG [databricks.labs.dqx.checks_resolver] Function does_not_contain_pii resolved successfully: <function does_not_contain_pii at 0x7f29d4b22160>
15:33 DEBUG [databricks.labs.dqx.checks_resolver] Resolving function: has_no_row_anomalies
15:33 DEBUG [databricks.labs.dqx.checks_resolver] Function has_no_row_anomalies resolved successfully: <function has_no_row_anomalies at 0x7f296d7c4360>
15:33 DEBUG [databricks.labs.dqx.llm.validators] ✓ JSON parsing successful
15:33 DEBUG [databricks.labs.dqx.checks_validator] Processing check definition: {'criticality': 'error', 'check': {'function': 'is_not_null_and_not_empty', 'arguments': {'column': 'product_code', 'trim_strings': True}}}
15:33 DEBUG [databricks.labs.dqx.checks_resolver] Resolving function: is_not_null_and_not_empty
15:33 DEBUG [databricks.labs.dqx.checks_resolver] Function is_not_null_and_not_empty resolved successfully: <function is_not_null_and_not_empty at 0x7f29dec9af20>
15:33 DEBUG [databricks.labs.dqx.llm.validators] ✓ Rules validation passed
15:33 DEBUG [databricks.labs.dqx.llm.validators] Final validation score: 1.00
15:33 DEBUG [databricks.labs.dqx.llm.validators] ✓ JSON parsing successful
15:33 DEBUG [databricks.labs.dqx.checks_validator] Processing check definition: {'criticality': 'error', 'check': {'function': 'is_in_list', 'arguments': {'column': 'status', 'allowed': [1, 2, 3]}}, 'filter': 'order_id IS NOT NULL'}
15:33 DEBUG [databricks.labs.dqx.checks_resolver] Resolving function: is_in_list
15:33 DEBUG [databricks.labs.dqx.checks_resolver] Function is_in_list resolved successfully: <function is_in_list at 0x7f29dec9b740>
15:33 DEBUG [databricks.labs.dqx.llm.validators] ✓ Rules validation passed
15:33 DEBUG [databricks.labs.dqx.llm.validators] Final validation score: 1.00
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:33 INFO [databricks.sdk] Using Databricks Metadata Service authentication
[gw2] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python
❌ test_has_no_sequence_gaps: pyspark.errors.exceptions.base.PySparkAssertionError: [DIFFERENT_ROWS] Results do not match: ( 40.00000 % ) (5.775s)
pyspark.errors.exceptions.base.PySparkAssertionError: [DIFFERENT_ROWS] Results do not match: ( 40.00000 % )
*** actual ***
�[31m! Row(invoice_no=1001, val=1, invoice_no_has_no_sequence_gaps='Gap in sequence: no data between the value at 1001 and the next present value at 1003')�[0m
�[31m! Row(invoice_no=1001, val=2, invoice_no_has_no_sequence_gaps='Gap in sequence: no data between the value at 1001 and the next present value at 1003')�[0m
  Row(invoice_no=1003, val=3, invoice_no_has_no_sequence_gaps=None)
  Row(invoice_no=1004, val=4, invoice_no_has_no_sequence_gaps=None)
  Row(invoice_no=None, val=5, invoice_no_has_no_sequence_gaps=None)


*** expected ***
�[31m! Row(invoice_no=1001, val=1, invoice_no_has_no_sequence_gaps='Gap in sequence: no data between the value at 1001.0 and the next present value at 1003.0')�[0m
�[31m! Row(invoice_no=1001, val=2, invoice_no_has_no_sequence_gaps='Gap in sequence: no data between the value at 1001.0 and the next present value at 1003.0')�[0m
  Row(invoice_no=1003, val=3, invoice_no_has_no_sequence_gaps=None)
  Row(invoice_no=1004, val=4, invoice_no_has_no_sequence_gaps=None)
  Row(invoice_no=None, val=5, invoice_no_has_no_sequence_gaps=None)
15:35 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:35 INFO [databricks.sdk] Using Databricks Metadata Service authentication
[gw2] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python
15:35 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:35 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:35 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:35 INFO [databricks.sdk] Using Databricks Metadata Service authentication
[gw2] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python
❌ test_has_no_sequence_gaps_multiple_gaps: pyspark.errors.exceptions.base.PySparkAssertionError: [DIFFERENT_ROWS] Results do not match: ( 66.66667 % ) (7.247s)
pyspark.errors.exceptions.base.PySparkAssertionError: [DIFFERENT_ROWS] Results do not match: ( 66.66667 % )
*** actual ***
�[31m! Row(invoice_no=1, val=1, invoice_no_has_no_sequence_gaps='Gap in sequence: no data between the value at 1 and the next present value at 3')�[0m
�[31m! Row(invoice_no=3, val=2, invoice_no_has_no_sequence_gaps='Gap in sequence: no data between the value at 3 and the next present value at 7')�[0m
  Row(invoice_no=7, val=3, invoice_no_has_no_sequence_gaps=None)


*** expected ***
�[31m! Row(invoice_no=1, val=1, invoice_no_has_no_sequence_gaps='Gap in sequence: no data between the value at 1.0 and the next present value at 3.0')�[0m
�[31m! Row(invoice_no=3, val=2, invoice_no_has_no_sequence_gaps='Gap in sequence: no data between the value at 3.0 and the next present value at 7.0')�[0m
  Row(invoice_no=7, val=3, invoice_no_has_no_sequence_gaps=None)
15:35 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:35 INFO [databricks.sdk] Using Databricks Metadata Service authentication
[gw2] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python
15:35 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:35 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:35 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:35 INFO [databricks.sdk] Using Databricks Metadata Service authentication
[gw2] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python
❌ test_has_no_sequence_gaps_custom_step: pyspark.errors.exceptions.base.PySparkAssertionError: [DIFFERENT_ROWS] Results do not match: ( 50.00000 % ) (11.93s)
pyspark.errors.exceptions.base.PySparkAssertionError: [DIFFERENT_ROWS] Results do not match: ( 50.00000 % )
*** actual ***
  Row(reading=100, val=1, reading_has_no_sequence_gaps=None)
�[31m! Row(reading=110, val=2, reading_has_no_sequence_gaps='Gap in sequence: no data between the value at 110 and the next present value at 130')�[0m
�[31m! Row(reading=115, val=3, reading_has_no_sequence_gaps='Gap in sequence: no data between the value at 110 and the next present value at 130')�[0m
  Row(reading=130, val=4, reading_has_no_sequence_gaps=None)


*** expected ***
  Row(reading=100, val=1, reading_has_no_sequence_gaps=None)
�[31m! Row(reading=110, val=2, reading_has_no_sequence_gaps='Gap in sequence: no data between the value at 110.0 and the next present value at 130.0')�[0m
�[31m! Row(reading=115, val=3, reading_has_no_sequence_gaps='Gap in sequence: no data between the value at 110.0 and the next present value at 130.0')�[0m
  Row(reading=130, val=4, reading_has_no_sequence_gaps=None)
15:35 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:35 INFO [databricks.sdk] Using Databricks Metadata Service authentication
[gw2] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python
15:35 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:35 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:35 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:35 INFO [databricks.sdk] Using Databricks Metadata Service authentication
[gw2] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python
❌ test_has_no_sequence_gaps_negative_values: pyspark.errors.exceptions.base.PySparkAssertionError: [DIFFERENT_ROWS] Results do not match: ( 33.33333 % ) (6.402s)
pyspark.errors.exceptions.base.PySparkAssertionError: [DIFFERENT_ROWS] Results do not match: ( 33.33333 % )
*** actual ***
  Row(offset=-1, val=2, offset_has_no_sequence_gaps=None)
�[31m! Row(offset=-3, val=1, offset_has_no_sequence_gaps='Gap in sequence: no data between the value at -3 and the next present value at -1')�[0m
  Row(offset=0, val=3, offset_has_no_sequence_gaps=None)


*** expected ***
  Row(offset=-1, val=2, offset_has_no_sequence_gaps=None)
�[31m! Row(offset=-3, val=1, offset_has_no_sequence_gaps='Gap in sequence: no data between the value at -3.0 and the next present value at -1.0')�[0m
  Row(offset=0, val=3, offset_has_no_sequence_gaps=None)
15:35 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:35 INFO [databricks.sdk] Using Databricks Metadata Service authentication
[gw2] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python
15:35 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:35 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:35 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:35 INFO [databricks.sdk] Using Databricks Metadata Service authentication
[gw2] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python
❌ test_has_no_sequence_gaps_group_by: pyspark.errors.exceptions.base.PySparkAssertionError: [DIFFERENT_ROWS] Results do not match: ( 20.00000 % ) (6.44s)
pyspark.errors.exceptions.base.PySparkAssertionError: [DIFFERENT_ROWS] Results do not match: ( 20.00000 % )
*** actual ***
�[31m! Row(customer='A', invoice_no=1, val=1, invoice_no_has_no_sequence_gaps='Gap in sequence: no data between the value at 1 and the next present value at 3')�[0m
  Row(customer='A', invoice_no=3, val=2, invoice_no_has_no_sequence_gaps=None)
  Row(customer='B', invoice_no=1, val=3, invoice_no_has_no_sequence_gaps=None)
  Row(customer='B', invoice_no=2, val=4, invoice_no_has_no_sequence_gaps=None)
  Row(customer='B', invoice_no=3, val=5, invoice_no_has_no_sequence_gaps=None)


*** expected ***
�[31m! Row(customer='A', invoice_no=1, val=1, invoice_no_has_no_sequence_gaps='Gap in sequence: no data between the value at 1.0 and the next present value at 3.0')�[0m
  Row(customer='A', invoice_no=3, val=2, invoice_no_has_no_sequence_gaps=None)
  Row(customer='B', invoice_no=1, val=3, invoice_no_has_no_sequence_gaps=None)
  Row(customer='B', invoice_no=2, val=4, invoice_no_has_no_sequence_gaps=None)
  Row(customer='B', invoice_no=3, val=5, invoice_no_has_no_sequence_gaps=None)
15:36 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:36 INFO [databricks.sdk] Using Databricks Metadata Service authentication
[gw2] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python
15:36 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:36 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:36 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:36 INFO [databricks.sdk] Using Databricks Metadata Service authentication
[gw2] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python
❌ test_has_no_sequence_gaps_group_by_bounded_independently: pyspark.errors.exceptions.base.PySparkAssertionError: [DIFFERENT_ROWS] Results do not match: ( 20.00000 % ) (7.275s)
pyspark.errors.exceptions.base.PySparkAssertionError: [DIFFERENT_ROWS] Results do not match: ( 20.00000 % )
*** actual ***
  Row(customer='A', invoice_no=1, invoice_no_has_no_sequence_gaps=None)
  Row(customer='A', invoice_no=2, invoice_no_has_no_sequence_gaps=None)
  Row(customer='B', invoice_no=1, invoice_no_has_no_sequence_gaps=None)
�[31m! Row(customer='B', invoice_no=2, invoice_no_has_no_sequence_gaps='Gap in sequence: no data between the value at 2 and the next present value at 9')�[0m
  Row(customer='B', invoice_no=9, invoice_no_has_no_sequence_gaps=None)


*** expected ***
  Row(customer='A', invoice_no=1, invoice_no_has_no_sequence_gaps=None)
  Row(customer='A', invoice_no=2, invoice_no_has_no_sequence_gaps=None)
  Row(customer='B', invoice_no=1, invoice_no_has_no_sequence_gaps=None)
�[31m! Row(customer='B', invoice_no=2, invoice_no_has_no_sequence_gaps='Gap in sequence: no data between the value at 2.0 and the next present value at 9.0')�[0m
  Row(customer='B', invoice_no=9, invoice_no_has_no_sequence_gaps=None)
15:36 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:36 INFO [databricks.sdk] Using Databricks Metadata Service authentication
[gw2] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python
15:36 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:36 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:36 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:36 INFO [databricks.sdk] Using Databricks Metadata Service authentication
[gw2] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python
❌ test_has_no_sequence_gaps_group_by_null_key: pyspark.errors.exceptions.base.PySparkAssertionError: [DIFFERENT_ROWS] Results do not match: ( 50.00000 % ) (8.82s)
pyspark.errors.exceptions.base.PySparkAssertionError: [DIFFERENT_ROWS] Results do not match: ( 50.00000 % )
*** actual ***
�[31m! Row(customer=None, invoice_no=1, invoice_no_has_no_sequence_gaps='Gap in sequence: no data between the value at 1 and the next present value at 3')�[0m
  Row(customer=None, invoice_no=3, invoice_no_has_no_sequence_gaps=None)


*** expected ***
�[31m! Row(customer=None, invoice_no=1, invoice_no_has_no_sequence_gaps='Gap in sequence: no data between the value at 1.0 and the next present value at 3.0')�[0m
  Row(customer=None, invoice_no=3, invoice_no_has_no_sequence_gaps=None)
15:36 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:36 INFO [databricks.sdk] Using Databricks Metadata Service authentication
[gw2] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python
15:36 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:36 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:36 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:36 INFO [databricks.sdk] Using Databricks Metadata Service authentication
[gw2] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python
❌ test_has_no_sequence_gaps_group_by_mixed_null_and_named_keys: pyspark.errors.exceptions.base.PySparkAssertionError: [DIFFERENT_ROWS] Results do not match: ( 33.33333 % ) (8.932s)
pyspark.errors.exceptions.base.PySparkAssertionError: [DIFFERENT_ROWS] Results do not match: ( 33.33333 % )
*** actual ***
�[31m! Row(customer='A', invoice_no=10, invoice_no_has_no_sequence_gaps='Gap in sequence: no data between the value at 10 and the next present value at 12')�[0m
  Row(customer='A', invoice_no=12, invoice_no_has_no_sequence_gaps=None)
  Row(customer='B', invoice_no=1, invoice_no_has_no_sequence_gaps=None)
  Row(customer='B', invoice_no=2, invoice_no_has_no_sequence_gaps=None)
�[31m! Row(customer=None, invoice_no=1, invoice_no_has_no_sequence_gaps='Gap in sequence: no data between the value at 1 and the next present value at 3')�[0m
  Row(customer=None, invoice_no=3, invoice_no_has_no_sequence_gaps=None)


*** expected ***
�[31m! Row(customer='A', invoice_no=10, invoice_no_has_no_sequence_gaps='Gap in sequence: no data between the value at 10.0 and the next present value at 12.0')�[0m
  Row(customer='A', invoice_no=12, invoice_no_has_no_sequence_gaps=None)
  Row(customer='B', invoice_no=1, invoice_no_has_no_sequence_gaps=None)
  Row(customer='B', invoice_no=2, invoice_no_has_no_sequence_gaps=None)
�[31m! Row(customer=None, invoice_no=1, invoice_no_has_no_sequence_gaps='Gap in sequence: no data between the value at 1.0 and the next present value at 3.0')�[0m
  Row(customer=None, invoice_no=3, invoice_no_has_no_sequence_gaps=None)
15:36 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:36 INFO [databricks.sdk] Using Databricks Metadata Service authentication
[gw2] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python
15:36 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:36 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:36 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:36 INFO [databricks.sdk] Using Databricks Metadata Service authentication
[gw2] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python
❌ test_has_no_sequence_gaps_group_by_column_expression: pyspark.errors.exceptions.base.PySparkAssertionError: [DIFFERENT_ROWS] Results do not match: ( 25.00000 % ) (9.304s)
pyspark.errors.exceptions.base.PySparkAssertionError: [DIFFERENT_ROWS] Results do not match: ( 25.00000 % )
*** actual ***
�[31m! Row(customer='A', invoice_no=1, invoice_no_has_no_sequence_gaps='Gap in sequence: no data between the value at 1 and the next present value at 3')�[0m
  Row(customer='A', invoice_no=3, invoice_no_has_no_sequence_gaps=None)
  Row(customer='B', invoice_no=1, invoice_no_has_no_sequence_gaps=None)
  Row(customer='B', invoice_no=2, invoice_no_has_no_sequence_gaps=None)


*** expected ***
�[31m! Row(customer='A', invoice_no=1, invoice_no_has_no_sequence_gaps='Gap in sequence: no data between the value at 1.0 and the next present value at 3.0')�[0m
  Row(customer='A', invoice_no=3, invoice_no_has_no_sequence_gaps=None)
  Row(customer='B', invoice_no=1, invoice_no_has_no_sequence_gaps=None)
  Row(customer='B', invoice_no=2, invoice_no_has_no_sequence_gaps=None)
15:36 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:36 INFO [databricks.sdk] Using Databricks Metadata Service authentication
[gw2] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python
15:36 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:36 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:36 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:36 INFO [databricks.sdk] Using Databricks Metadata Service authentication
[gw2] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python
❌ test_apply_checks_and_split_has_no_sequence_gaps: pyspark.errors.exceptions.base.PySparkAssertionError: [DIFFERENT_ROWS] Results do not match: ( 33.33333 % ) (18.625s)
pyspark.errors.exceptions.base.PySparkAssertionError: [DIFFERENT_ROWS] Results do not match: ( 33.33333 % )
*** actual ***
�[31m! Row(invoice_no=1001, val=1, _errors=[Row(name='invoice_no_has_no_sequence_gaps', message='Gap in sequence: no data between the value at 1001 and the next present value at 1003', columns=['invoice_no'], filter=None, function='has_no_sequence_gaps', run_time=datetime.datetime(2025, 1, 1, 0, 0), run_id='2f9120cf-e9f2-446a-8278-12d508b00639', user_metadata={}, skipped=None)], _warnings=None)�[0m
  Row(invoice_no=1003, val=2, _errors=None, _warnings=None)
  Row(invoice_no=1004, val=3, _errors=None, _warnings=None)


*** expected ***
�[31m! Row(invoice_no=1001, val=1, _errors=[Row(name='invoice_no_has_no_sequence_gaps', message='Gap in sequence: no data between the value at 1001.0 and the next present value at 1003.0', columns=['invoice_no'], filter=None, function='has_no_sequence_gaps', run_time=datetime.datetime(2025, 1, 1, 0, 0), run_id='2f9120cf-e9f2-446a-8278-12d508b00639', user_metadata={}, skipped=None)], _warnings=None)�[0m
  Row(invoice_no=1003, val=2, _errors=None, _warnings=None)
  Row(invoice_no=1004, val=3, _errors=None, _warnings=None)
15:39 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:39 INFO [databricks.sdk] Using Databricks Metadata Service authentication
[gw3] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python
15:39 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:39 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:39 DEBUG [databricks.labs.dqx.telemetry] Added User-Agent extra check=has_no_sequence_gaps
15:39 INFO [tests.conftest] Overriding DATABRICKS_CLUSTER_ID with DATABRICKS_DQX_CLUSTER_ID: DATABRICKS_DQX_CLUSTER_ID
15:39 INFO [databricks.sdk] Using Databricks Metadata Service authentication
15:39 DEBUG [databricks.labs.dqx.telemetry] Added User-Agent extra check=has_no_sequence_gaps
[gw3] linux -- Python 3.12.3 /home/runner/work/dqx/dqx/.venv/bin/python

Flaky tests:

  • 🤪 test_generate_dq_rules_ai_assisted_with_sql_expression (21.007s)

Running from acceptance #5656

@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

✅ 1/1 passed, 30m28s total

Running from mcp #405

@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

✅ 138/138 passed, 1 skipped, 8h58m42s total

Running from anomaly #1770

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant