Skip to content

Commit

Permalink
Fix tests and excluded constraints (#34)
Browse files Browse the repository at this point in the history
* Fix tests used unsuitable assertion

* Test serialize_features with multiple intervals

* Fix output order of warnings was random

* Make test assertion cleaner

* Improve readability
  • Loading branch information
Aonokishi authored Sep 15, 2024
1 parent 650d7d9 commit 13a1fc5
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 53 deletions.
8 changes: 4 additions & 4 deletions cfmtoolbox/plugins/featureide_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,10 @@ def parse_formula_value_and_feature(

def parse_constraints(
constraints: Element | None, features: list[Feature]
) -> tuple[list[Constraint], list[Constraint], set[Element]]:
) -> tuple[list[Constraint], list[Constraint], list[Element]]:
require_constraints: list[Constraint] = []
exclude_constraints: list[Constraint] = []
eliminated_constraints: set[Element] = set()
eliminated_constraints: list[Element] = list()

if constraints is None or len(constraints) == 0:
return (require_constraints, exclude_constraints, eliminated_constraints)
Expand All @@ -131,7 +131,7 @@ def parse_constraints(
raise TypeError("No valid constraint rule found in constraints")

if rule[0].tag != FormulaTypes.IMP.value:
eliminated_constraints.add(rule)
eliminated_constraints.append(rule)
return (require_constraints, exclude_constraints, eliminated_constraints)

try:
Expand All @@ -142,7 +142,7 @@ def parse_constraints(
rule[0][1], features
)
except TooComplexConstraintError:
eliminated_constraints.add(rule)
eliminated_constraints.append(rule)
continue

is_require = first_feature_value == second_feature_value
Expand Down
2 changes: 1 addition & 1 deletion tests/data/dessert.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<var>Choux</var>
</imp>
</rule>
<rule>
<rule>
<imp>
<disj>
<var>Croissant</var>
Expand Down
77 changes: 39 additions & 38 deletions tests/plugins/test_featureide_import.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import xml.etree.ElementTree as ET
from pathlib import Path
from textwrap import dedent
from xml.etree.ElementTree import Element, SubElement

import pytest
Expand Down Expand Up @@ -283,11 +282,11 @@ def test_parse_formula_value_and_feature_raises_too_complex_contraint_error_with

@pytest.mark.parametrize(
["constraints", "expectation"],
[(None, ([], [], set([]))), (Element("constraints"), ([], [], set([])))],
[(None, ([], [], [])), (Element("constraints"), ([], [], []))],
)
def test_parse_constraints_can_parse_without_constraints(
constraints: Element,
expectation: tuple[list[Constraint], list[Constraint], set[int]],
expectation: tuple[list[Constraint], list[Constraint], list[int]],
):
assert parse_constraints(constraints, []) == expectation

Expand Down Expand Up @@ -402,7 +401,7 @@ def test_parse_constraint_can_parse_constraint_with_elimination():
assert len(require) == 0
assert len(exclude) == 0
assert len(eliminated) == 1
assert eliminated == set([rule])
assert eliminated == [rule]


def test_parse_cfm(capsys):
Expand All @@ -413,16 +412,18 @@ def test_parse_cfm(capsys):
exclude_constraints = cfm.exclude_constraints

output = capsys.readouterr()
expected_rule = """<rule>
<imp>
<conj>
<var>Bread</var>
<var>Swiss</var>
</conj>
<var>Tomato</var>
</imp>
</rule>
"""
expectation = """The following constraints were exterminated:
<rule>
\t\t\t<imp>
\t\t\t\t<conj>
\t\t\t\t\t<var>Bread</var>
\t\t\t\t\t<var>Swiss</var>
\t\t\t\t</conj>
\t\t\t\t<var>Tomato</var>
\t\t\t</imp>
\t\t</rule>
\t
"""

assert len(cfm.features) == 11
assert cfm.features[0].name == "Sandwich"
Expand All @@ -447,7 +448,7 @@ def test_parse_cfm(capsys):
assert exclude_constraints[0].first_feature.name == "Wheat"
assert exclude_constraints[0].second_feature.name == "Tomato"

assert dedent(expected_rule) in output.err
assert expectation == output.err


def test_parse_cfm_can_parse_multiple_eliminated_constraints(capsys):
Expand All @@ -457,34 +458,34 @@ def test_parse_cfm_can_parse_multiple_eliminated_constraints(capsys):
require_constraints = cfm.require_constraints
exclude_constraints = cfm.exclude_constraints

expected_rule_one = """<rule>
<imp>
<conj>
<var>Tart</var>
<var>Shortcake</var>
</conj>
<var>Choux</var>
</imp>
</rule>
"""

expected_rule_two = """<rule>
<imp>
<disj>
<var>Croissant</var>
<var>Spongecake</var>
</disj>
<var>Eclair</var>
</imp>
</rule>
"""
expectation = """The following constraints were exterminated:
<rule>
\t\t\t<imp>
\t\t\t\t<conj>
\t\t\t\t\t<var>Tart</var>
\t\t\t\t\t<var>Shortcake</var>
\t\t\t\t</conj>
\t\t\t\t<var>Choux</var>
\t\t\t</imp>
\t\t</rule>
\t\t
<rule>
\t\t\t<imp>
\t\t\t\t<disj>
\t\t\t\t\t<var>Croissant</var>
\t\t\t\t\t<var>Spongecake</var>
\t\t\t\t</disj>
\t\t\t\t<var>Eclair</var>
\t\t\t</imp>
\t\t</rule>
\t
"""

output = capsys.readouterr()

assert len(exclude_constraints) == 0
assert len(require_constraints) == 0
assert dedent(expected_rule_one) in output.err
assert dedent(expected_rule_two) in output.err
assert expectation == output.err


def test_parse_cfm_does_not_print_extermination_without_eliminated_constraints(capsys):
Expand Down
50 changes: 40 additions & 10 deletions tests/plugins/test_uvl_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ def test_serialize_root_feature():
expectation = """features
\tSandwich
\t\t[0..2]"""

root = Feature(
"Sandwich",
Cardinality([Interval(1, 1)]),
Expand All @@ -178,7 +179,7 @@ def test_serialize_root_feature():
assert expectation in root_export


def test_serialize_root_feature_raises_type_error_on_group_instance_compounded_cardinality():
def test_serialize_root_feature_raises_type_error_for_group_instance_compounded_cardinality():
sandwich = Feature(
"Sandwich",
Cardinality([Interval(1, 1)]),
Expand All @@ -191,7 +192,7 @@ def test_serialize_root_feature_raises_type_error_on_group_instance_compounded_c
serialize_root_feature(sandwich)


def test_serialize_root_feature_raises_type_error_on_group_type_compounded_cardinality():
def test_serialize_root_feature_raises_type_error_for_group_type_compounded_cardinality():
sandwich = Feature(
"Sandwich",
Cardinality([Interval(1, 1)]),
Expand All @@ -204,7 +205,33 @@ def test_serialize_root_feature_raises_type_error_on_group_type_compounded_cardi
serialize_root_feature(sandwich)


def test_serialize_features_raises_type_error_on_compounded_cardinality():
def test_serialize_features_raises_type_error_for_instance_compounded_cardinality():
sandwich = Feature(
"Sandwich",
Cardinality([Interval(1, 1), Interval(1, 1)]),
Cardinality([Interval(0, 2)]),
Cardinality([Interval(0, 2)]),
None,
[],
)
with pytest.raises(TypeError, match="UVL cannot handle compounded cardinalities"):
serialize_features(sandwich)


def test_serialize_features_raises_type_error_for_group_type_compounded_cardinality():
sandwich = Feature(
"Sandwich",
Cardinality([Interval(1, 1)]),
Cardinality([Interval(0, 2), Interval(1, 1)]),
Cardinality([Interval(0, 2)]),
None,
[],
)
with pytest.raises(TypeError, match="UVL cannot handle compounded cardinalities"):
serialize_features(sandwich)


def test_serialize_features_raises_type_error_for_group_instance_compounded_cardinality():
sandwich = Feature(
"Sandwich",
Cardinality([Interval(1, 1)]),
Expand Down Expand Up @@ -365,10 +392,11 @@ def test_serialize_features():
\t\tVeggie cardinality [0..1]
\t\t\tor
\t\t\t\tLettuce cardinality [0..*]
\t\t\t\tTomato cardinality [0..*]"""
\t\t\t\tTomato cardinality [0..*]
"""

export = serialize_features(sandwich)
assert expectation in export
assert expectation == export


@pytest.mark.parametrize(
Expand Down Expand Up @@ -429,7 +457,7 @@ def test_serialize_constraints(is_required: bool, expectation: str):
assert serialize_constraints(constraints, is_required) == expectation


def test_serialize_constraints_raises_type_error_on_compounded_cardinality_on_first_feature_cardinality():
def test_serialize_constraints_raises_type_error_for_compounded_cardinality_on_first_feature_cardinality():
sandwich = Feature(
"Sandwich",
Cardinality([Interval(1, 1)]),
Expand All @@ -454,7 +482,7 @@ def test_serialize_constraints_raises_type_error_on_compounded_cardinality_on_fi
serialize_constraints([constraint], is_required=True)


def test_serialize_constraints_raises_type_error_on_compounded_cardinality_on_second_feature_cardinality():
def test_serialize_constraints_raises_type_error_for_compounded_cardinality_on_second_feature_cardinality():
sandwich = Feature(
"Sandwich",
Cardinality([Interval(1, 1)]),
Expand Down Expand Up @@ -513,7 +541,8 @@ def test_serialize_all_constraints():

expectation = """constraints
\t(Sandwich = 3) => ((Bread >= 0) & (Bread <= 2))
\t!((Sandwich = 3) & ((Bread >= 0) & (Bread <= 2)))\n"""
\t!((Sandwich = 3) & ((Bread >= 0) & (Bread <= 2)))
"""

assert expectation == export

Expand Down Expand Up @@ -547,6 +576,7 @@ def test_export_uvl_from_featureide_cfm():
\t(Sourdough = 1) => (Cheddar = 1)
\t(Tomato = 1) => (Gouda = 1)
\t(Swiss = 1) => (Lettuce = 1)
\t!((Wheat = 1) & (Tomato = 1))\n"""
\t!((Wheat = 1) & (Tomato = 1))
"""

assert expectation in export.decode()
assert expectation == export.decode()

0 comments on commit 13a1fc5

Please sign in to comment.