Skip to content

Commit 0357c85

Browse files
committed
tests pass and coverage increased
1 parent 7b4c4d8 commit 0357c85

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

tests/specification_tests/test_metamorphic_relations.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ def setUp(self) -> None:
7373
dag_dot = """digraph DAG { rankdir=LR; X1 -> Z; Z -> M; M -> Y; X2 -> Z; X3 -> M;}"""
7474
with open(self.dag_dot_path, "w") as f:
7575
f.write(dag_dot)
76+
self.dcg_dot_path = os.path.join(self.temp_dir_path, "dcg.dot")
77+
dcg_dot = """digraph dct { a -> b -> c -> d; d -> c; }"""
78+
with open(self.dcg_dot_path, "w") as f:
79+
f.write(dcg_dot)
7680

7781
X1 = Input("X1", float)
7882
X2 = Input("X2", float)
@@ -248,6 +252,71 @@ def test_all_metamorphic_relations_implied_by_dag(self):
248252
self.assertEqual(extra_snc_relations, [])
249253
self.assertEqual(missing_snc_relations, [])
250254

255+
def test_all_metamorphic_relations_implied_by_dag_parallel(self):
256+
dag = CausalDAG(self.dag_dot_path)
257+
dag.add_edge("Z", "Y") # Add a direct path from Z to Y so M becomes a mediator
258+
metamorphic_relations = generate_metamorphic_relations(dag, threads=2)
259+
should_cause_relations = [mr for mr in metamorphic_relations if isinstance(mr, ShouldCause)]
260+
should_not_cause_relations = [mr for mr in metamorphic_relations if isinstance(mr, ShouldNotCause)]
261+
262+
# Check all ShouldCause relations are present and no extra
263+
expected_should_cause_relations = [
264+
ShouldCause("X1", "Z", [], dag),
265+
ShouldCause("Z", "M", [], dag),
266+
ShouldCause("M", "Y", ["Z"], dag),
267+
ShouldCause("Z", "Y", ["M"], dag),
268+
ShouldCause("X2", "Z", [], dag),
269+
ShouldCause("X3", "M", [], dag),
270+
]
271+
272+
extra_sc_relations = [scr for scr in should_cause_relations if scr not in expected_should_cause_relations]
273+
missing_sc_relations = [escr for escr in expected_should_cause_relations if escr not in should_cause_relations]
274+
275+
self.assertEqual(extra_sc_relations, [])
276+
self.assertEqual(missing_sc_relations, [])
277+
278+
# Check all ShouldNotCause relations are present and no extra
279+
expected_should_not_cause_relations = [
280+
ShouldNotCause("X1", "X2", [], dag),
281+
ShouldNotCause("X1", "X3", [], dag),
282+
ShouldNotCause("X1", "M", ["Z"], dag),
283+
ShouldNotCause("X1", "Y", ["Z"], dag),
284+
ShouldNotCause("X2", "X3", [], dag),
285+
ShouldNotCause("X2", "M", ["Z"], dag),
286+
ShouldNotCause("X2", "Y", ["Z"], dag),
287+
ShouldNotCause("X3", "Y", ["M", "Z"], dag),
288+
ShouldNotCause("Z", "X3", [], dag),
289+
]
290+
291+
extra_snc_relations = [
292+
sncr for sncr in should_not_cause_relations if sncr not in expected_should_not_cause_relations
293+
]
294+
missing_snc_relations = [
295+
esncr for esncr in expected_should_not_cause_relations if esncr not in should_not_cause_relations
296+
]
297+
298+
self.assertEqual(extra_snc_relations, [])
299+
self.assertEqual(missing_snc_relations, [])
300+
301+
def test_all_metamorphic_relations_implied_by_dag_ignore_cycles(self):
302+
dag = CausalDAG(self.dcg_dot_path, ignore_cycles=True)
303+
metamorphic_relations = generate_metamorphic_relations(dag, threads=2, nodes_to_ignore=set(dag.cycle_nodes()))
304+
should_cause_relations = [mr for mr in metamorphic_relations if isinstance(mr, ShouldCause)]
305+
should_not_cause_relations = [mr for mr in metamorphic_relations if isinstance(mr, ShouldNotCause)]
306+
307+
# Check all ShouldCause relations are present and no extra
308+
309+
self.assertEqual(
310+
should_cause_relations,
311+
[
312+
ShouldCause("a", "b", [], dag),
313+
],
314+
)
315+
self.assertEqual(
316+
should_not_cause_relations,
317+
[],
318+
)
319+
251320
def test_equivalent_metamorphic_relations(self):
252321
dag = CausalDAG(self.dag_dot_path)
253322
sc_mr_a = ShouldCause("X", "Y", ["A", "B", "C"], dag)

0 commit comments

Comments
 (0)