Skip to content

Commit bc13d84

Browse files
authored
Merge pull request #184 from CITCOM-project/json_fitter
Logging causal test results
2 parents b82011f + 310c481 commit bc13d84

File tree

3 files changed

+33
-29
lines changed

3 files changed

+33
-29
lines changed

causal_testing/json_front/json_class.py

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from causal_testing.specification.scenario import Scenario
2222
from causal_testing.specification.variable import Input, Meta, Output
2323
from causal_testing.testing.causal_test_case import CausalTestCase
24+
from causal_testing.testing.causal_test_result import CausalTestResult
2425
from causal_testing.testing.causal_test_engine import CausalTestEngine
2526
from causal_testing.testing.estimators import Estimator
2627
from causal_testing.testing.base_test_case import BaseTestCase
@@ -124,28 +125,29 @@ def run_json_tests(self, effects: dict, estimators: dict, f_flag: bool = False,
124125
effect=test.get("effect", "direct"),
125126
)
126127
assert len(test["expected_effect"]) == 1, "Can only have one expected effect."
127-
concrete_tests = [
128-
CausalTestCase(
129-
base_test_case=base_test_case,
130-
expected_causal_effect=next(
131-
effects[effect] for variable, effect in test["expected_effect"].items()
132-
),
133-
estimate_type="coefficient",
134-
effect_modifier_configuration={
135-
self.scenario.variables[v] for v in test.get("effect_modifiers", [])
136-
},
137-
)
138-
]
139-
failures = self._execute_tests(concrete_tests, test, f_flag)
128+
causal_test_case = CausalTestCase(
129+
base_test_case=base_test_case,
130+
expected_causal_effect=next(
131+
effects[effect] for variable, effect in test["expected_effect"].items()
132+
),
133+
estimate_type="coefficient",
134+
effect_modifier_configuration={
135+
self.scenario.variables[v] for v in test.get("effect_modifiers", [])
136+
},
137+
)
138+
result = self._execute_test_case(causal_test_case=causal_test_case, test=test, f_flag=f_flag)
140139
msg = (
141140
f"Executing test: {test['name']} \n"
142-
+ f" {concrete_tests[0]} \n"
143-
+ f" {failures}/{len(concrete_tests)} failed for {test['name']}"
141+
+ f" {causal_test_case} \n"
142+
+ " "
143+
+ ("\n ").join(str(result[1]).split("\n"))
144+
+ "==============\n"
145+
+ f" Result: {'FAILED' if result[0] else 'Passed'}"
144146
)
145147
else:
146148
abstract_test = self._create_abstract_test_case(test, mutates, effects)
147-
concrete_tests, dummy = abstract_test.generate_concrete_tests(5, 0.05)
148-
failures = self._execute_tests(concrete_tests, test, f_flag)
149+
concrete_tests, _ = abstract_test.generate_concrete_tests(5, 0.05)
150+
failures, _ = self._execute_tests(concrete_tests, test, f_flag)
149151

150152
msg = (
151153
f"Executing test: {test['name']} \n"
@@ -173,29 +175,28 @@ def run_json_tests(self, effects: dict, estimators: dict, f_flag: bool = False,
173175
treatment_value=test["treatment_value"],
174176
estimate_type=test["estimate_type"],
175177
)
176-
if self._execute_test_case(causal_test_case=causal_test_case, test=test, f_flag=f_flag):
177-
result = "failed"
178-
else:
179-
result = "passed"
178+
failed, _ = self._execute_test_case(causal_test_case=causal_test_case, test=test, f_flag=f_flag)
180179

181180
msg = (
182181
f"Executing concrete test: {test['name']} \n"
183182
+ f"treatment variable: {test['treatment_variable']} \n"
184183
+ f"outcome_variable = {outcome_variable} \n"
185184
+ f"control value = {test['control_value']}, treatment value = {test['treatment_value']} \n"
186-
+ f"result - {result}"
185+
+ f"Result: {'FAILED' if failed else 'Passed'}"
187186
)
188187
self._append_to_file(msg, logging.INFO)
189188

190189
def _execute_tests(self, concrete_tests, test, f_flag):
191190
failures = 0
191+
details = []
192192
if "formula" in test:
193193
self._append_to_file(f"Estimator formula used for test: {test['formula']}")
194194
for concrete_test in concrete_tests:
195-
failed = self._execute_test_case(concrete_test, test, f_flag)
195+
failed, result = self._execute_test_case(concrete_test, test, f_flag)
196+
details.append(result)
196197
if failed:
197198
failures += 1
198-
return failures
199+
return failures, details
199200

200201
def _json_parse(self):
201202
"""Parse a JSON input file into inputs, outputs, metas and a test plan"""
@@ -213,7 +214,9 @@ def _populate_metas(self):
213214
for meta in self.scenario.variables_of_type(Meta):
214215
meta.populate(self.data)
215216

216-
def _execute_test_case(self, causal_test_case: CausalTestCase, test: Iterable[Mapping], f_flag: bool) -> bool:
217+
def _execute_test_case(
218+
self, causal_test_case: CausalTestCase, test: Iterable[Mapping], f_flag: bool
219+
) -> (bool, CausalTestResult):
217220
"""Executes a singular test case, prints the results and returns the test case result
218221
:param causal_test_case: The concrete test case to be executed
219222
:param test: Single JSON test definition stored in a mapping (dict)
@@ -249,7 +252,7 @@ def _execute_test_case(self, causal_test_case: CausalTestCase, test: Iterable[Ma
249252
)
250253
failed = True
251254
logger.warning(" FAILED- expected %s, got %s", causal_test_case.expected_causal_effect, result_string)
252-
return failed
255+
return failed, causal_test_result
253256

254257
def _setup_test(
255258
self, causal_test_case: CausalTestCase, test: Mapping, conditions: list[str] = None

causal_testing/testing/causal_test_result.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""
44
from typing import Any
55
from dataclasses import dataclass
6+
import pandas as pd
67

78
from causal_testing.testing.estimators import Estimator
89
from causal_testing.specification.variable import Variable
@@ -87,7 +88,7 @@ def ci_high(self):
8788

8889
def ci_valid(self) -> bool:
8990
"""Return whether or not the result has valid confidence invervals"""
90-
return self.ci_low() and self.ci_high()
91+
return self.ci_low() and (not pd.isnull(self.ci_low())) and self.ci_high() and (not pd.isnull(self.ci_high()))
9192

9293
def summary(self):
9394
"""Summarise the causal test result as an intuitive sentence."""

tests/json_front_tests/test_json_class.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ def test_generate_coefficient_tests_from_json(self):
123123
# Test that the final log message prints that failed tests are printed, which is expected behaviour for this scenario
124124
with open("temp_out.txt", "r") as reader:
125125
temp_out = reader.readlines()
126-
self.assertIn("failed", temp_out[-1])
126+
self.assertIn("FAILED", temp_out[-1])
127127

128128
def test_run_json_tests_from_json(self):
129129
example_test = {
@@ -234,7 +234,7 @@ def test_run_concrete_json_testcase(self):
234234
self.json_class.run_json_tests(effects=effects, estimators=estimators, f_flag=False)
235235
with open("temp_out.txt", "r") as reader:
236236
temp_out = reader.readlines()
237-
self.assertIn("failed", temp_out[-1])
237+
self.assertIn("FAILED", temp_out[-1])
238238

239239
def tearDown(self) -> None:
240240
remove_temp_dir_if_existent()

0 commit comments

Comments
 (0)