11
11
from statistics import StatisticsError
12
12
13
13
import pandas as pd
14
+ import numpy as np
14
15
import scipy
15
16
from fitter import Fitter , get_common_distributions
16
17
21
22
from causal_testing .specification .scenario import Scenario
22
23
from causal_testing .specification .variable import Input , Meta , Output
23
24
from causal_testing .testing .causal_test_case import CausalTestCase
24
- from causal_testing .testing .causal_test_result import CausalTestResult
25
+ from causal_testing .testing .causal_test_result import CausalTestResult , TestValue
25
26
from causal_testing .testing .base_test_case import BaseTestCase
26
27
from causal_testing .testing .causal_test_adequacy import DataAdequacy
27
28
@@ -136,8 +137,10 @@ def run_json_tests(self, effects: dict, estimators: dict, f_flag: bool = False,
136
137
failed , msg = self ._run_concrete_metamorphic_test (test , f_flag , effects )
137
138
# If we have a variable to mutate
138
139
else :
139
- if test ["estimate_type" ] == "coefficient" :
140
- failed , msg = self ._run_coefficient_test (test = test , f_flag = f_flag , effects = effects )
140
+ if test ["estimate_type" ] in ["coefficient" , "unit_odds_ratio" ]:
141
+ failed , msg = self ._run_coefficient_test (
142
+ test = test , f_flag = f_flag , effects = effects , estimate_type = test ["estimate_type" ]
143
+ )
141
144
else :
142
145
failed , msg = self ._run_metamorphic_tests (
143
146
test = test , f_flag = f_flag , effects = effects , mutates = mutates
@@ -146,7 +149,7 @@ def run_json_tests(self, effects: dict, estimators: dict, f_flag: bool = False,
146
149
test ["result" ] = msg
147
150
return self .test_plan ["tests" ]
148
151
149
- def _run_coefficient_test (self , test : dict , f_flag : bool , effects : dict ):
152
+ def _run_coefficient_test (self , test : dict , f_flag : bool , effects : dict , estimate_type : str = "coefficient" ):
150
153
"""Builds structures and runs test case for tests with an estimate_type of 'coefficient'.
151
154
152
155
:param test: Single JSON test definition stored in a mapping (dict)
@@ -163,10 +166,11 @@ def _run_coefficient_test(self, test: dict, f_flag: bool, effects: dict):
163
166
causal_test_case = CausalTestCase (
164
167
base_test_case = base_test_case ,
165
168
expected_causal_effect = next (effects [effect ] for variable , effect in test ["expected_effect" ].items ()),
166
- estimate_type = "coefficient" ,
169
+ estimate_type = estimate_type ,
167
170
effect_modifier_configuration = {self .scenario .variables [v ] for v in test .get ("effect_modifiers" , [])},
168
171
)
169
172
failed , result = self ._execute_test_case (causal_test_case = causal_test_case , test = test , f_flag = f_flag )
173
+
170
174
msg = (
171
175
f"Executing test: { test ['name' ]} \n "
172
176
+ f" { causal_test_case } \n "
@@ -273,10 +277,17 @@ def _execute_test_case(
273
277
failed = False
274
278
275
279
estimation_model = self ._setup_test (causal_test_case = causal_test_case , test = test )
276
- causal_test_result = causal_test_case .execute_test (
277
- estimator = estimation_model , data_collector = self .data_collector
278
- )
279
- test_passes = causal_test_case .expected_causal_effect .apply (causal_test_result )
280
+ try :
281
+ causal_test_result = causal_test_case .execute_test (
282
+ estimator = estimation_model , data_collector = self .data_collector
283
+ )
284
+ test_passes = causal_test_case .expected_causal_effect .apply (causal_test_result )
285
+ except np .linalg .LinAlgError as e :
286
+ result = CausalTestResult (
287
+ estimator = estimation_model ,
288
+ test_value = TestValue ("Error" , str (e )),
289
+ )
290
+ return None , result
280
291
281
292
if "coverage" in test and test ["coverage" ]:
282
293
adequacy_metric = DataAdequacy (causal_test_case , estimation_model )
0 commit comments