Skip to content

Commit 9cf32c8

Browse files
authored
Restructure warn_error_options testing for better isolation (#12489)
* Move fixtures for warn error options tests into base class We don't typically declare fixtures at the top level of a testing file. Doing so can lead to weirdness when those fixtures conflict with other fixtures defined elsewhere. Additionally it can lead to situations where the fixture is unintentionally reused. * Refactor warn error options tests to have one test per test class A best practice generally in our functional/integration tests is to have only one test per test class. This is because running dbt writes files to the operating system. When multiple tests are in the same test class they share an operating system meaning that the test can accidentally become dependent on one another.
1 parent 9b730a2 commit 9cf32c8

File tree

1 file changed

+58
-40
lines changed

1 file changed

+58
-40
lines changed

tests/functional/configs/test_warn_error_options.py

Lines changed: 58 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -24,53 +24,52 @@
2424
"""
2525

2626

27-
@pytest.fixture(scope="class")
28-
def models() -> ModelsDictSpec:
29-
return {"my_model.sql": my_model_sql, "schema.yml": schema_yml}
30-
31-
32-
@pytest.fixture(scope="function")
33-
def catcher() -> EventCatcher:
34-
return EventCatcher(event_to_catch=DeprecatedModel)
35-
36-
37-
@pytest.fixture(scope="function")
38-
def runner(catcher: EventCatcher) -> dbtRunner:
39-
return dbtRunner(callbacks=[catcher.catch])
27+
class BaseTestWarnErrorOptions:
28+
@pytest.fixture(scope="class")
29+
def models(self) -> ModelsDictSpec:
30+
return {"my_model.sql": my_model_sql, "schema.yml": schema_yml}
4031

32+
@pytest.fixture(scope="function")
33+
def catcher(self) -> EventCatcher:
34+
return EventCatcher(event_to_catch=DeprecatedModel)
4135

42-
def assert_deprecation_warning(result: dbtRunnerResult, catcher: EventCatcher) -> None:
43-
assert result.success
44-
assert result.exception is None
45-
assert len(catcher.caught_events) == 1
46-
assert catcher.caught_events[0].info.level == EventLevel.WARN.value
36+
@pytest.fixture(scope="function")
37+
def runner(self, catcher: EventCatcher) -> dbtRunner:
38+
return dbtRunner(callbacks=[catcher.catch])
4739

40+
def assert_deprecation_warning(self, result: dbtRunnerResult, catcher: EventCatcher) -> None:
41+
assert result.success
42+
assert result.exception is None
43+
assert len(catcher.caught_events) == 1
44+
assert catcher.caught_events[0].info.level == EventLevel.WARN.value
4845

49-
def assert_deprecation_error(result: dbtRunnerResult) -> None:
50-
assert not result.success
51-
assert result.exception is not None
52-
assert "Model my_model has passed its deprecation date of" in str(result.exception)
46+
def assert_deprecation_error(self, result: dbtRunnerResult) -> None:
47+
assert not result.success
48+
assert result.exception is not None
49+
assert "Model my_model has passed its deprecation date of" in str(result.exception)
5350

5451

55-
class TestWarnErrorOptionsFromCLI:
52+
class TestWarnErrorOptionsFromCLICanSilence(BaseTestWarnErrorOptions):
5653
def test_can_silence(self, project, catcher: EventCatcher, runner: dbtRunner) -> None:
5754
result = runner.invoke(["run"])
58-
assert_deprecation_warning(result, catcher)
55+
self.assert_deprecation_warning(result, catcher)
5956

6057
catcher.flush()
6158
result = runner.invoke(["run", "--warn-error-options", "{'silence': ['DeprecatedModel']}"])
6259
assert result.success
6360
assert len(catcher.caught_events) == 0
6461

62+
63+
class TestWarnErrorOptionsFromCLICanRaiseWarningToError(BaseTestWarnErrorOptions):
6564
def test_can_raise_warning_to_error(
6665
self, project, catcher: EventCatcher, runner: dbtRunner
6766
) -> None:
6867
result = runner.invoke(["run"])
69-
assert_deprecation_warning(result, catcher)
68+
self.assert_deprecation_warning(result, catcher)
7069

7170
catcher.flush()
7271
result = runner.invoke(["run", "--warn-error-options", "{'include': ['DeprecatedModel']}"])
73-
assert_deprecation_error(result)
72+
self.assert_deprecation_error(result)
7473

7574
catcher.flush()
7675
result = runner.invoke(
@@ -80,25 +79,27 @@ def test_can_raise_warning_to_error(
8079
"{'include': 'all', 'warn': ['DeprecationsSummary', 'WEOIncludeExcludeDeprecation']}",
8180
]
8281
)
83-
assert_deprecation_error(result)
82+
self.assert_deprecation_error(result)
8483

8584
catcher.flush()
8685
result = runner.invoke(["run", "--warn-error-options", "{'error': ['DeprecatedModel']}"])
87-
assert_deprecation_error(result)
86+
self.assert_deprecation_error(result)
8887

8988
catcher.flush()
9089
result = runner.invoke(
9190
["run", "--warn-error-options", "{'error': 'all', 'warn': ['DeprecationsSummary']}"]
9291
)
93-
assert_deprecation_error(result)
92+
self.assert_deprecation_error(result)
93+
9494

95+
class TestWarnErrorOptionsFromCLICanExcludeSpecificEvent(BaseTestWarnErrorOptions):
9596
def test_can_exclude_specific_event(
9697
self, project, catcher: EventCatcher, runner: dbtRunner
9798
) -> None:
9899
result = runner.invoke(
99100
["run", "--warn-error-options", "{'error': 'all', 'warn': ['DeprecationsSummary']}"]
100101
)
101-
assert_deprecation_error(result)
102+
self.assert_deprecation_error(result)
102103

103104
catcher.flush()
104105
result = runner.invoke(
@@ -108,7 +109,7 @@ def test_can_exclude_specific_event(
108109
"{'error': 'all', 'exclude': ['DeprecatedModel', 'WEOIncludeExcludeDeprecation', 'DeprecationsSummary']}",
109110
]
110111
)
111-
assert_deprecation_warning(result, catcher)
112+
self.assert_deprecation_warning(result, catcher)
112113

113114
catcher.flush()
114115
result = runner.invoke(
@@ -118,8 +119,10 @@ def test_can_exclude_specific_event(
118119
"{'error': 'all', 'warn': ['DeprecatedModel', 'DeprecationsSummary']}",
119120
]
120121
)
121-
assert_deprecation_warning(result, catcher)
122+
self.assert_deprecation_warning(result, catcher)
122123

124+
125+
class TestWarnErrorOptionsFromCLICantSetBothIncludeAndError(BaseTestWarnErrorOptions):
123126
def test_cant_set_both_include_and_error(self, project, runner: dbtRunner) -> None:
124127
result = runner.invoke(
125128
["run", "--warn-error-options", "{'include': 'all', 'error': 'all'}"]
@@ -141,17 +144,20 @@ def test_cant_set_both_exclude_and_warn(self, project, runner: dbtRunner) -> Non
141144
assert "Only `exclude` or `warn` can be specified" in str(result.exception)
142145

143146

144-
class TestWarnErrorOptionsFromProject:
147+
class BaseTestWarnErrorOptionsFromProject(BaseTestWarnErrorOptions):
145148
@pytest.fixture(scope="function")
146149
def clear_project_flags(self, project_root) -> None:
147-
flags = {"flags": {}}
150+
# TODO: Is this still necessary now that the project based tests are broken into separate test classes?
151+
flags: Dict[str, Any] = {"flags": {}}
148152
update_config_file(flags, project_root, "dbt_project.yml")
149153

154+
155+
class TestWarnErrorOptionsFromProjectCanSilence(BaseTestWarnErrorOptionsFromProject):
150156
def test_can_silence(
151157
self, project, clear_project_flags, project_root, catcher: EventCatcher, runner: dbtRunner
152158
) -> None:
153159
result = runner.invoke(["run"])
154-
assert_deprecation_warning(result, catcher)
160+
self.assert_deprecation_warning(result, catcher)
155161

156162
silence_options = {"flags": {"warn_error_options": {"silence": ["DeprecatedModel"]}}}
157163
update_config_file(silence_options, project_root, "dbt_project.yml")
@@ -161,11 +167,13 @@ def test_can_silence(
161167
assert result.success
162168
assert len(catcher.caught_events) == 0
163169

170+
171+
class TestWarnErrorOptionsFromProjectCanRaiseWarningToError(BaseTestWarnErrorOptionsFromProject):
164172
def test_can_raise_warning_to_error(
165173
self, project, clear_project_flags, project_root, catcher: EventCatcher, runner: dbtRunner
166174
) -> None:
167175
result = runner.invoke(["run"])
168-
assert_deprecation_warning(result, catcher)
176+
self.assert_deprecation_warning(result, catcher)
169177

170178
warn_error_options: Dict[str, Any] = {
171179
"flags": {"warn_error_options": {"error": ["DeprecatedModel"]}}
@@ -174,7 +182,7 @@ def test_can_raise_warning_to_error(
174182

175183
catcher.flush()
176184
result = runner.invoke(["run"])
177-
assert_deprecation_error(result)
185+
self.assert_deprecation_error(result)
178186

179187
warn_error_options = {
180188
"flags": {"warn_error_options": {"error": "all", "warn": ["DeprecationsSummary"]}}
@@ -183,8 +191,10 @@ def test_can_raise_warning_to_error(
183191

184192
catcher.flush()
185193
result = runner.invoke(["run"])
186-
assert_deprecation_error(result)
194+
self.assert_deprecation_error(result)
195+
187196

197+
class TestWarnErrorOptionsFromProjectCanExcludeSpecificEvent(BaseTestWarnErrorOptionsFromProject):
188198
def test_can_exclude_specific_event(
189199
self, project, clear_project_flags, project_root, catcher: EventCatcher, runner: dbtRunner
190200
) -> None:
@@ -193,7 +203,7 @@ def test_can_exclude_specific_event(
193203
}
194204
update_config_file(warn_error_options, project_root, "dbt_project.yml")
195205
result = runner.invoke(["run"])
196-
assert_deprecation_error(result)
206+
self.assert_deprecation_error(result)
197207

198208
warn_error_options = {
199209
"flags": {
@@ -207,8 +217,12 @@ def test_can_exclude_specific_event(
207217

208218
catcher.flush()
209219
result = runner.invoke(["run"])
210-
assert_deprecation_warning(result, catcher)
220+
self.assert_deprecation_warning(result, catcher)
211221

222+
223+
class TestWarnErrorOptionsFromProjectCantSetBothIncludeAndError(
224+
BaseTestWarnErrorOptionsFromProject
225+
):
212226
def test_cant_set_both_include_and_error(
213227
self, project, clear_project_flags, project_root, runner: dbtRunner
214228
) -> None:
@@ -219,6 +233,10 @@ def test_cant_set_both_include_and_error(
219233
assert result.exception is not None
220234
assert "Only `include` or `error` can be specified" in str(result.exception)
221235

236+
237+
class TestWarnErrorOptionsFromProjectCantSetBothExcludeAndWarn(
238+
BaseTestWarnErrorOptionsFromProject
239+
):
222240
def test_cant_set_both_exclude_and_warn(
223241
self, project, clear_project_flags, project_root, runner: dbtRunner
224242
) -> None:

0 commit comments

Comments
 (0)