Skip to content

Commit 9e6bf5d

Browse files
committed
feature: making sure test counts differentiate
Signed-off-by: Cortland Goffena <30168413+cmgoffena13@users.noreply.github.com>
1 parent e1f589d commit 9e6bf5d

2 files changed

Lines changed: 91 additions & 15 deletions

File tree

tests/cli/test_cli.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,61 @@ def test_plan_all_tests_with_no_changes(runner, tmp_path):
219219
assert "Successfully Ran 1 tests against duckdb" in result.output
220220

221221

222+
def test_plan_runs_only_changed_model_tests(runner, tmp_path):
223+
create_example_project(tmp_path)
224+
init_prod_and_backfill(runner, tmp_path)
225+
226+
# Two unit tests total; changing full_model should run only its test
227+
(tmp_path / "tests" / "test_incremental_model.yaml").write_text(
228+
"""test_example_incremental_model:
229+
model: sqlmesh_example.incremental_model
230+
vars:
231+
start: 2020-01-01
232+
end: 2020-01-02
233+
inputs:
234+
sqlmesh_example.seed_model:
235+
rows:
236+
- id: 1
237+
item_id: 1
238+
event_date: 2020-01-01
239+
outputs:
240+
query:
241+
rows:
242+
- id: 1
243+
item_id: 1
244+
event_date: 2020-01-01
245+
"""
246+
)
247+
full_model_path = tmp_path / "models" / "full_model.sql"
248+
full_model_path.write_text(
249+
full_model_path.read_text().replace("COUNT(DISTINCT id)", "COUNT(id)")
250+
)
251+
252+
result = runner.invoke(
253+
cli,
254+
["--log-file-dir", tmp_path, "--paths", tmp_path, "plan", "--no-prompts", "--auto-apply"],
255+
)
256+
assert result.exit_code == 0
257+
assert "Successfully Ran 1 tests against duckdb" in result.output
258+
assert "Successfully Ran 2 tests against duckdb" not in result.output
259+
260+
result = runner.invoke(
261+
cli,
262+
[
263+
"--log-file-dir",
264+
tmp_path,
265+
"--paths",
266+
tmp_path,
267+
"plan",
268+
"--all-tests",
269+
"--no-prompts",
270+
],
271+
input="\n",
272+
)
273+
assert result.exit_code == 0
274+
assert "Successfully Ran 2 tests against duckdb" in result.output
275+
276+
222277
def test_plan_skip_backfill_all_tests(runner, tmp_path):
223278
create_example_project(tmp_path)
224279

tests/core/test_test.py

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3557,23 +3557,43 @@ def test_filter_tests_by_model_names():
35573557

35583558
def test_plan_scoped_unit_tests(tmp_path: Path, mocker: MockerFixture):
35593559
init_example_project(tmp_path, engine_type="duckdb")
3560+
# Second unit test so scoped plans (1 test) differ from --all-tests (2 tests)
3561+
(tmp_path / "tests" / "test_incremental_model.yaml").write_text(
3562+
"""test_example_incremental_model:
3563+
model: sqlmesh_example.incremental_model
3564+
vars:
3565+
start: 2020-01-01
3566+
end: 2020-01-02
3567+
inputs:
3568+
sqlmesh_example.seed_model:
3569+
rows:
3570+
- id: 1
3571+
item_id: 1
3572+
event_date: 2020-01-01
3573+
outputs:
3574+
query:
3575+
rows:
3576+
- id: 1
3577+
item_id: 1
3578+
event_date: 2020-01-01
3579+
"""
3580+
)
35603581
config = Config(
35613582
gateways={"duckdb": GatewayConfig(connection=DuckDBConnectionConfig())},
35623583
model_defaults=ModelDefaultsConfig(dialect="duckdb"),
35633584
)
35643585
context = Context(paths=tmp_path, config=config)
35653586
context.plan("prod", auto_apply=True, no_prompts=True)
35663587

3567-
calls: t.List[t.Dict[str, t.Any]] = []
3588+
calls: t.List[t.Tuple[t.Dict[str, t.Any], int]] = []
3589+
original_test = context.test
35683590

3569-
def fake_test(**kwargs: t.Any) -> ModelTextTestResult:
3570-
calls.append(kwargs)
3571-
result = mocker.MagicMock(spec=ModelTextTestResult)
3572-
result.wasSuccessful.return_value = True
3573-
result.testsRun = 0
3591+
def tracking_test(**kwargs: t.Any) -> ModelTextTestResult:
3592+
result = original_test(**kwargs)
3593+
calls.append((kwargs, result.testsRun))
35743594
return result
35753595

3576-
mocker.patch.object(context, "test", side_effect=fake_test)
3596+
mocker.patch.object(context, "test", side_effect=tracking_test)
35773597

35783598
# No-op plan should not run tests
35793599
context.plan("prod", auto_apply=True, no_prompts=True)
@@ -3582,26 +3602,27 @@ def fake_test(**kwargs: t.Any) -> ModelTextTestResult:
35823602
# --all-tests on no-op should run the full suite
35833603
context.plan("prod", auto_apply=True, no_prompts=True, all_tests=True)
35843604
assert len(calls) == 1
3585-
assert calls[0].get("model_names") is None
3605+
assert calls[0][0].get("model_names") is None
3606+
assert calls[0][1] == 2
35863607

35873608
calls.clear()
35883609

3589-
# Changing one model should only pass that model's name into test()
3610+
# Changing full_model should only run that model's unit test
35903611
model_path = tmp_path / "models" / "full_model.sql"
35913612
model_path.write_text(model_path.read_text().replace("COUNT(DISTINCT id)", "COUNT(id)"))
35923613
context.load()
35933614
context.plan("prod", auto_apply=True, no_prompts=True)
35943615
assert len(calls) == 1
3595-
model_names = calls[0].get("model_names")
3596-
assert model_names is not None
3597-
assert any("full_model" in name for name in model_names)
3598-
assert not any("seed_model" in name for name in model_names)
3616+
model_names = calls[0][0].get("model_names")
3617+
assert model_names == {'"memory"."sqlmesh_example"."full_model"'}
3618+
assert calls[0][1] == 1
35993619

36003620
calls.clear()
36013621

3602-
# --all-tests with real changes still runs the full suite (no model filter)
3622+
# --all-tests with real changes still runs the full suite
36033623
model_path.write_text(model_path.read_text().replace("COUNT(id)", "COUNT(DISTINCT id)"))
36043624
context.load()
36053625
context.plan("prod", auto_apply=True, no_prompts=True, all_tests=True)
36063626
assert len(calls) == 1
3607-
assert calls[0].get("model_names") is None
3627+
assert calls[0][0].get("model_names") is None
3628+
assert calls[0][1] == 2

0 commit comments

Comments
 (0)