@@ -21,12 +21,28 @@ def program_under_test(X1, X2, X3, Z=None, M=None, Y=None):
21
21
return {'Z' : Z , 'M' : M , 'Y' : Y }
22
22
23
23
24
+ def buggy_program_under_test (X1 , X2 , X3 , Z = None , M = None , Y = None ):
25
+ if Z is None :
26
+ Z = 2 # No effect of X1 or X2 on Z
27
+ if M is None :
28
+ M = 3 * Z + X3
29
+ if Y is None :
30
+ Y = M / 2
31
+ return {'Z' : Z , 'M' : M , 'Y' : Y }
32
+
33
+
24
34
class ProgramUnderTestEDC (ExperimentalDataCollector ):
25
35
26
36
def run_system_with_input_configuration (self , input_configuration : dict ) -> pd .DataFrame :
27
- print (input_configuration )
28
37
results_dict = program_under_test (** input_configuration )
29
- print (results_dict )
38
+ results_df = pd .DataFrame (results_dict , index = [0 ])
39
+ return results_df
40
+
41
+
42
+ class BuggyProgramUnderTestEDC (ExperimentalDataCollector ):
43
+
44
+ def run_system_with_input_configuration (self , input_configuration : dict ) -> pd .DataFrame :
45
+ results_dict = buggy_program_under_test (** input_configuration )
30
46
results_df = pd .DataFrame (results_dict , index = [0 ])
31
47
return results_df
32
48
@@ -46,18 +62,35 @@ def setUp(self) -> None:
46
62
Z = Output ('Z' , float )
47
63
M = Output ('M' , float )
48
64
Y = Output ('Y' , float )
49
- scenario = Scenario (variables = {X1 , X2 , X3 , Z , M , Y })
50
- default_control_input_config = {'X1' : 1 , 'X2' : 2 , 'X3' : 3 }
51
- default_treatment_input_config = {'X1' : 2 , 'X2' : 3 , 'X3' : 3 }
52
- self .data_collector = ProgramUnderTestEDC (scenario ,
53
- default_control_input_config ,
54
- default_treatment_input_config )
55
-
56
- def test_metamorphic_relation (self ):
65
+ self . scenario = Scenario (variables = {X1 , X2 , X3 , Z , M , Y })
66
+ self . default_control_input_config = {'X1' : 1 , 'X2' : 2 , 'X3' : 3 }
67
+ self . default_treatment_input_config = {'X1' : 2 , 'X2' : 3 , 'X3' : 3 }
68
+ self .data_collector = ProgramUnderTestEDC (self . scenario ,
69
+ self . default_control_input_config ,
70
+ self . default_treatment_input_config )
71
+
72
+ def test_should_cause_metamorphic_relations_should_pass (self ):
57
73
causal_dag = CausalDAG (self .dag_dot_path )
58
74
for edge in causal_dag .graph .edges :
59
75
(u , v ) = edge
60
76
should_cause_MR = ShouldCause (u , v , None , causal_dag )
61
77
should_cause_MR .generate_follow_up (10 , - 10.0 , 10.0 , 1 )
62
78
test_results = should_cause_MR .execute_tests (self .data_collector )
63
- print (test_results )
79
+ should_cause_MR .test_oracle (test_results )
80
+
81
+ def test_should_cause_metamorphic_relation_missing_relationship (self ):
82
+ """Test whether the ShouldCause MR catches missing relationships in the DAG."""
83
+ causal_dag = CausalDAG (self .dag_dot_path )
84
+ self .data_collector = BuggyProgramUnderTestEDC (self .scenario ,
85
+ self .default_control_input_config ,
86
+ self .default_treatment_input_config )
87
+ X1_should_cause_Z_MR = ShouldCause ('X1' , 'Z' , None , causal_dag )
88
+ X2_should_cause_Z_MR = ShouldCause ('X2' , 'Z' , None , causal_dag )
89
+ X1_should_cause_Z_MR .generate_follow_up (10 , - 100 , 100 , 1 )
90
+ X2_should_cause_Z_MR .generate_follow_up (10 , - 100 , 100 , 1 )
91
+ X1_should_cause_Z_test_results = X1_should_cause_Z_MR .execute_tests (self .data_collector )
92
+ X2_should_cause_Z_test_results = X2_should_cause_Z_MR .execute_tests (self .data_collector )
93
+ self .assertRaises (AssertionError , X1_should_cause_Z_MR .test_oracle , X1_should_cause_Z_test_results )
94
+ self .assertRaises (AssertionError , X2_should_cause_Z_MR .test_oracle , X2_should_cause_Z_test_results )
95
+
96
+
0 commit comments