Skip to content

Commit

Permalink
create a happy path project fixture (#10291)
Browse files Browse the repository at this point in the history
  • Loading branch information
ChenyuLInx authored Jun 11, 2024
1 parent e977b3e commit e699f5d
Show file tree
Hide file tree
Showing 24 changed files with 199 additions and 79 deletions.
41 changes: 29 additions & 12 deletions core/dbt/tests/fixtures/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,8 @@ def adapter(
project_root,
profiles_root,
profiles_yml,
dbt_project_yml,
clean_up_logging,
dbt_project_yml,
):
# The profiles.yml and dbt_project.yml should already be written out
args = Namespace(
Expand Down Expand Up @@ -385,7 +385,20 @@ def analyses():

# Write out the files provided by models, macros, properties, snapshots, seeds, tests, analyses
@pytest.fixture(scope="class")
def project_files(project_root, models, macros, snapshots, properties, seeds, tests, analyses):
def project_files(
project_root,
models,
macros,
snapshots,
properties,
seeds,
tests,
analyses,
selectors_yml,
dependencies_yml,
packages_yml,
dbt_project_yml,
):
write_project_files(project_root, "models", {**models, **properties})
write_project_files(project_root, "macros", macros)
write_project_files(project_root, "snapshots", snapshots)
Expand Down Expand Up @@ -515,25 +528,16 @@ def initialization(environment) -> None:
enable_test_caching()


# This is the main fixture that is used in all functional tests. It pulls in the other
# fixtures that are necessary to set up a dbt project, and saves some of the information
# in a TestProjInfo class, which it returns, so that individual test cases do not have
# to pull in the other fixtures individually to access their information.
@pytest.fixture(scope="class")
def project(
def project_setup(
initialization,
clean_up_logging,
project_root,
profiles_root,
request,
unique_schema,
profiles_yml,
dbt_project_yml,
packages_yml,
dependencies_yml,
selectors_yml,
adapter,
project_files,
shared_data_dir,
test_data_dir,
logs_dir,
Expand Down Expand Up @@ -587,3 +591,16 @@ def project(
pass
os.chdir(orig_cwd)
cleanup_event_logger()


# This is the main fixture that is used in all functional tests. It pulls in the other
# fixtures that are necessary to set up a dbt project, and saves some of the information
# in a TestProjInfo class, which it returns, so that individual test cases do not have
# to pull in the other fixtures individually to access their information.
# The order of arguments here determine which steps runs first.
@pytest.fixture(scope="class")
def project(
project_setup: TestProjInfo,
project_files,
):
return project_setup
1 change: 0 additions & 1 deletion core/dbt/tests/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ def run_dbt(
args.extend(["--project-dir", project_dir])
if profiles_dir and "--profiles-dir" not in args:
args.extend(["--profiles-dir", profiles_dir])

dbt = dbtRunner()
res = dbt.invoke(args)

Expand Down
11 changes: 0 additions & 11 deletions tests/functional/adapter/basic/test_adapter_methods.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import pytest

from dbt.tests.fixtures.project import write_project_files
from dbt.tests.util import check_relations_equal, run_dbt

tests__get_columns_in_relation_sql = """
Expand Down Expand Up @@ -73,16 +72,6 @@ def models(self):
"model.sql": models__model_sql,
}

@pytest.fixture(scope="class")
def project_files(
self,
project_root,
tests,
models,
):
write_project_files(project_root, "tests", tests)
write_project_files(project_root, "models", models)

@pytest.fixture(scope="class")
def project_config_update(self):
return {
Expand Down
Empty file.
32 changes: 32 additions & 0 deletions tests/functional/fixtures/happy_path_fixture.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import os
from distutils.dir_util import copy_tree

import pytest


def delete_files_in_directory(directory_path):
try:
with os.scandir(directory_path) as entries:
for entry in entries:
if entry.is_file():
os.unlink(entry.path)
print("All files deleted successfully.")
except OSError:
print("Error occurred while deleting files.")


@pytest.fixture(scope="class")
def happy_path_project_files(project_root):
# copy fixture files to the project root
delete_files_in_directory(project_root)
copy_tree(
os.path.dirname(os.path.realpath(__file__)) + "/happy_path_project", str(project_root)
)


# We do project_setup first because it will write out a dbt_project.yml.
# This file will be overwritten by the files in happy_path_project later on.
@pytest.fixture(scope="class")
def happy_path_project(project_setup, happy_path_project_files):
# A fixture that gives functional test the project living in happy_path_project
return project_setup
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
select 4 as id
17 changes: 17 additions & 0 deletions tests/functional/fixtures/happy_path_project/dbt_project.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
analysis-paths:
- analyses
config-version: 2
flags:
send_anonymous_usage_stats: false
macro-paths:
- macros
name: test
profile: test
seed-paths:
- seeds
seeds:
quote_columns: false
snapshot-paths:
- snapshots
test-paths:
- tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{% macro cool_macro() %}
wow!
{% endmacro %}

{% macro other_cool_macro(a, b) %}
cool!
{% endmacro %}
3 changes: 3 additions & 0 deletions tests/functional/fixtures/happy_path_project/models/docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% docs my_docs %}
some docs
{% enddocs %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{ config(materialized='ephemeral') }}

select
1 as id,
{{ dbt.date_trunc('day', dbt.current_timestamp()) }} as created_at
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{{
config(
materialized = "incremental",
incremental_strategy = "delete+insert",
)
}}

select * from {{ ref('seed') }}

{% if is_incremental() %}
where a > (select max(a) from {{this}})
{% endif %}
7 changes: 7 additions & 0 deletions tests/functional/fixtures/happy_path_project/models/m.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
metrics:
- name: total_outer
type: simple
description: The total count of outer
label: Total Outer
type_params:
measure: total_outer_count
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
select
{{ dbt.date_trunc('day', dbt.current_timestamp()) }} as date_day
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
select * from {{ ref('ephemeral') }}
15 changes: 15 additions & 0 deletions tests/functional/fixtures/happy_path_project/models/schema.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: 2
models:
- name: outer
description: The outer table
columns:
- name: id
description: The id value
data_tests:
- unique
- not_null

sources:
- name: my_source
tables:
- name: my_table
18 changes: 18 additions & 0 deletions tests/functional/fixtures/happy_path_project/models/sm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
semantic_models:
- name: my_sm
model: ref('outer')
defaults:
agg_time_dimension: created_at
entities:
- name: my_entity
type: primary
expr: id
dimensions:
- name: created_at
type: time
type_params:
time_granularity: day
measures:
- name: total_outer_count
agg: count
expr: 1
14 changes: 14 additions & 0 deletions tests/functional/fixtures/happy_path_project/models/sq.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
saved_queries:
- name: my_saved_query
label: My Saved Query
query_params:
metrics:
- total_outer
group_by:
- "Dimension('my_entity__created_at')"
exports:
- name: my_export
config:
alias: my_export_alias
export_as: table
schema: my_export_schema_name
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
select * from {{ ref('outer') }}
2 changes: 2 additions & 0 deletions tests/functional/fixtures/happy_path_project/seeds/seed.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
a,b
1,2
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{% snapshot my_snapshot %}
{{
config(
target_database=var('target_database', database),
target_schema=schema,
unique_key='id',
strategy='timestamp',
updated_at='updated_at',
)
}}
select * from {{database}}.{{schema}}.seed
{% endsnapshot %}
1 change: 1 addition & 0 deletions tests/functional/fixtures/happy_path_project/tests/t.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
select 1 as id limit 0
57 changes: 19 additions & 38 deletions tests/functional/list/test_list.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,18 @@
import json
import os

import pytest

from dbt.tests.util import run_dbt
from tests.functional.list.fixtures import ( # noqa: F401
analyses,
macros,
metrics,
models,
project_files,
saved_queries,
seeds,
semantic_models,
snapshots,
tests,
from tests.functional.fixtures.happy_path_fixture import ( # noqa: F401
happy_path_project,
happy_path_project_files,
)


class TestList:
def dir(self, value):
return os.path.normpath(value)

@pytest.fixture(scope="class")
def project_config_update(self):
return {
"config-version": 2,
"analysis-paths": [self.dir("analyses")],
"snapshot-paths": [self.dir("snapshots")],
"macro-paths": [self.dir("macros")],
"seed-paths": [self.dir("seeds")],
"test-paths": [self.dir("tests")],
"seeds": {
"quote_columns": False,
},
}

def test_packages_install_path_does_not_exist(self, project):
def test_packages_install_path_does_not_exist(self, happy_path_project): # noqa: F811
run_dbt(["list"])
packages_install_path = "dbt_packages"

Expand All @@ -47,7 +23,6 @@ def run_dbt_ls(self, args=None, expect_pass=True):
full_args = ["ls"]
if args is not None:
full_args += args

result = run_dbt(args=full_args, expect_pass=expect_pass)

return result
Expand All @@ -67,7 +42,7 @@ def expect_given_output(self, args, expectations):
else:
assert got == expected

def expect_snapshot_output(self, project):
def expect_snapshot_output(self, happy_path_project): # noqa: F811
expectations = {
"name": "my_snapshot",
"selector": "test.snapshot.my_snapshot",
Expand All @@ -86,8 +61,8 @@ def expect_snapshot_output(self, project):
"quoting": {},
"column_types": {},
"persist_docs": {},
"target_database": project.database,
"target_schema": project.test_schema,
"target_database": happy_path_project.database,
"target_schema": happy_path_project.test_schema,
"unique_key": "id",
"strategy": "timestamp",
"updated_at": "updated_at",
Expand Down Expand Up @@ -735,10 +710,14 @@ def expect_resource_type_env_var(self):
}
del os.environ["DBT_EXCLUDE_RESOURCE_TYPES"]

def expect_selected_keys(self, project):
def expect_selected_keys(self, happy_path_project): # noqa: F811
"""Expect selected fields of the the selected model"""
expectations = [
{"database": project.database, "schema": project.test_schema, "alias": "inner"}
{
"database": happy_path_project.database,
"schema": happy_path_project.test_schema,
"alias": "inner",
}
]
results = self.run_dbt_ls(
[
Expand All @@ -759,7 +738,9 @@ def expect_selected_keys(self, project):

"""Expect selected fields when --output-keys given multiple times
"""
expectations = [{"database": project.database, "schema": project.test_schema}]
expectations = [
{"database": happy_path_project.database, "schema": happy_path_project.test_schema}
]
results = self.run_dbt_ls(
[
"--model",
Expand Down Expand Up @@ -821,8 +802,8 @@ def expect_selected_keys(self, project):
for got, expected in zip(results, expectations):
self.assert_json_equal(got, expected)

def test_ls(self, project):
self.expect_snapshot_output(project)
def test_ls(self, happy_path_project): # noqa: F811
self.expect_snapshot_output(happy_path_project)
self.expect_analyses_output()
self.expect_model_output()
self.expect_source_output()
Expand All @@ -832,7 +813,7 @@ def test_ls(self, project):
self.expect_resource_type_multiple()
self.expect_resource_type_env_var()
self.expect_all_output()
self.expect_selected_keys(project)
self.expect_selected_keys(happy_path_project)


def normalize(path):
Expand Down
Loading

0 comments on commit e699f5d

Please sign in to comment.