diff --git a/.changes/unreleased/Under the Hood-20230912-190506.yaml b/.changes/unreleased/Under the Hood-20230912-190506.yaml new file mode 100644 index 00000000000..41804b6c0c7 --- /dev/null +++ b/.changes/unreleased/Under the Hood-20230912-190506.yaml @@ -0,0 +1,6 @@ +kind: Under the Hood +body: Add unit testing functional tests +time: 2023-09-12T19:05:06.023126-04:00 +custom: + Author: gshank + Issue: "8512" diff --git a/tests/functional/unit_testing/test_unit_testing.py b/tests/functional/unit_testing/test_unit_testing.py index dd7cbdc1666..0773a53e613 100644 --- a/tests/functional/unit_testing/test_unit_testing.py +++ b/tests/functional/unit_testing/test_unit_testing.py @@ -1,5 +1,6 @@ import pytest -from dbt.tests.util import run_dbt +from dbt.tests.util import run_dbt, write_file, get_manifest, get_artifact +from dbt.exceptions import DuplicateResourceNameError my_model_sql = """ SELECT @@ -86,6 +87,11 @@ - {id: 1, string_b: b} expect: - {string_c: ab} + config: + tags: test_this +""" + +datetime_test = """ - name: test_my_model_datetime given: - input: ref('my_model_a') @@ -106,7 +112,7 @@ def models(self): "my_model.sql": my_model_sql, "my_model_a.sql": my_model_a_sql, "my_model_b.sql": my_model_b_sql, - "test_my_model.yml": test_my_model_yml, + "test_my_model.yml": test_my_model_yml + datetime_test, } @pytest.fixture(scope="class") @@ -114,9 +120,55 @@ def project_config_update(self): return {"vars": {"my_test": "my_test_var"}} def test_basic(self, project): - run_dbt(["deps"]) results = run_dbt(["run"]) assert len(results) == 3 + # Select by model name results = run_dbt(["unit-test", "--select", "my_model"], expect_pass=False) assert len(results) == 5 + + # Test select by test name + results = run_dbt(["unit-test", "--select", "test_name:test_my_model_string_concat"]) + assert len(results) == 1 + + # Select, method not specified + results = run_dbt(["unit-test", "--select", "test_my_model_overrides"]) + assert len(results) == 1 + + # Select using tag + results = run_dbt(["unit-test", "--select", "tag:test_this"]) + assert len(results) == 1 + + # Partial parsing... remove test + write_file(test_my_model_yml, project.project_root, "models", "test_my_model.yml") + results = run_dbt(["unit-test", "--select", "my_model"], expect_pass=False) + assert len(results) == 4 + + # Partial parsing... put back removed test + write_file( + test_my_model_yml + datetime_test, project.project_root, "models", "test_my_model.yml" + ) + results = run_dbt(["unit-test", "--select", "my_model"], expect_pass=False) + assert len(results) == 5 + + manifest = get_manifest(project.project_root) + assert len(manifest.unit_tests) == 5 + # Every unit test has a depends_on to the model it tests + for unit_test_definition in manifest.unit_tests.values(): + assert unit_test_definition.depends_on.nodes[0] == "model.test.my_model" + + # We should have a UnitTestNode for every test, plus two input models for each test + unit_test_manifest = get_artifact( + project.project_root, "target", "unit_test_manifest.json" + ) + assert len(unit_test_manifest["nodes"]) == 15 + + # Check for duplicate unit test name + write_file( + test_my_model_yml + datetime_test + datetime_test, + project.project_root, + "models", + "test_my_model.yml", + ) + with pytest.raises(DuplicateResourceNameError): + run_dbt(["unit-test", "--select", "my_model"])