Skip to content

Commit

Permalink
add tests for Rules
Browse files Browse the repository at this point in the history
  • Loading branch information
mscarey committed Jun 29, 2019
1 parent 7a28fcd commit 1ea6c83
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 20 deletions.
4 changes: 4 additions & 0 deletions authorityspoke/procedures.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ def generic_factors(self) -> List[Optional[Factor]]:
"""
:class:`.Factor`\s that can be replaced without changing ``self``\s meaning.
If ``self.generic is True`` then the only generic :class:`.Factor` is ``self``.
This could happen if the :class:`.Procedure` was mentioned generically in an
:class:`.Argument` about preserving objections for appeal, for instance.
:returns:
``self``'s generic :class:`.Factor`\s,
which must be matched to other generic :class:`.Factor`\s to
Expand Down
2 changes: 1 addition & 1 deletion authorityspoke/selectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def set_exact_from_source(self, source: Union[Regime, Code]) -> Optional[str]:
elif source.__class__.__name__ == "Code":
code = source
else:
return None
raise TypeError(f'"source" parameter must be class "Regime" or "Code"')

section_text = code.section_text(self.path)
return self.exact_from_ends(section_text)
Expand Down
3 changes: 3 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,9 @@ def make_exhibit(
c = make_complex_fact

return {
"shooting_affidavit": Exhibit(
form="affidavit", statement=f["f_shooting"], stated_by=e["alice"]
),
"shooting_testimony": Exhibit(
form="testimony", statement=f["f_shooting"], stated_by=e["alice"]
),
Expand Down
52 changes: 35 additions & 17 deletions tests/test_evidence.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from authorityspoke.factors import Fact
from authorityspoke.factors import Evidence, Exhibit


class TestExhibits:
def test_make_exhibit_object(self, watt_factor):
e = Exhibit(form="testimony")
Expand All @@ -11,23 +12,32 @@ def test_make_exhibit_object(self, watt_factor):
# Equality

def test_equality(self, make_exhibit):
assert (
make_exhibit["no_shooting_entity_order_testimony"].means(make_exhibit["no_shooting_testimony"]
))
assert make_exhibit["no_shooting_entity_order_testimony"].means(
make_exhibit["no_shooting_testimony"]
)

def test_not_equal_different_speaker(self, make_exhibit):
assert not (
make_exhibit["no_shooting_different_witness_testimony"].means(make_exhibit["no_shooting_testimony"]
))
make_exhibit["no_shooting_different_witness_testimony"].means(
make_exhibit["no_shooting_testimony"]
)
)

def test_equal_complex_statement(self, make_exhibit):
assert (
make_exhibit["relevant_murder_nested_swap_testimony"].means(make_exhibit["relevant_murder_testimony"])
assert make_exhibit["relevant_murder_nested_swap_testimony"].means(
make_exhibit["relevant_murder_testimony"]
)

def test_not_equal_complex_statement(self, make_exhibit):
assert not (
make_exhibit["relevant_murder_alice_craig_testimony"].means(make_exhibit["relevant_murder_testimony"])
make_exhibit["relevant_murder_alice_craig_testimony"].means(
make_exhibit["relevant_murder_testimony"]
)
)

def test_not_equal_different_form(self, make_exhibit):
assert not make_exhibit["shooting_affidavit"].means(
make_exhibit["shooting_testimony"]
)

# Implication
Expand Down Expand Up @@ -106,13 +116,18 @@ def test_present_contradicts_same_absent(self, make_exhibit):
)

def test_more_specific_contradicts_absent(self, make_exhibit):
assert make_exhibit["reciprocal_testimony_absent"].contradicts(make_exhibit["reciprocal_testimony_specific"])
assert make_exhibit["reciprocal_testimony_specific"].contradicts(make_exhibit["reciprocal_testimony_absent"])
assert make_exhibit["reciprocal_testimony_absent"].contradicts(
make_exhibit["reciprocal_testimony_specific"]
)
assert make_exhibit["reciprocal_testimony_specific"].contradicts(
make_exhibit["reciprocal_testimony_absent"]
)

def test_no_contradiction_with_factor_subclass(self, make_exhibit, watt_factor):
assert not make_exhibit["shooting_testimony"].contradicts(watt_factor["f4"])
assert not watt_factor["f4"].contradicts(make_exhibit["shooting_testimony"])


class TestEvidence:
def test_make_evidence_object(self, watt_factor):
e = Evidence(Exhibit(form="testimony"), to_effect=watt_factor["f2"])
Expand All @@ -131,7 +146,6 @@ def test_default_len_based_on_unique_entity_slots(self, make_entity, make_factor
)
assert not e.generic


def test_no_extra_space_around_exhibit_in_string(self, make_opinion_with_holding):
"""
Don't expect the holdings imported from the JSON to
Expand All @@ -152,7 +166,11 @@ def test_get_entity_orders_no_statement(self, make_factor):
assert len(e.to_effect.context_factors) == 1

def test_evidence_str(self, make_evidence):
assert str(make_evidence["reciprocal"]).lower().startswith("evidence of testimony by")
assert (
str(make_evidence["reciprocal"])
.lower()
.startswith("evidence of testimony by")
)

def test_equality_with_entity_order(self, make_predicate, make_evidence):
e = make_evidence
Expand All @@ -167,8 +185,10 @@ def test_unequal_due_to_entity_order(self, make_evidence):

def test_unequal_different_attributes(self, make_evidence):
assert not (
make_evidence["no_shooting_no_effect_entity_order"].means(make_evidence["no_shooting_different_witness"]
))
make_evidence["no_shooting_no_effect_entity_order"].means(
make_evidence["no_shooting_different_witness"]
)
)

def test_implication_missing_witness(self, make_evidence):
e = make_evidence
Expand All @@ -181,9 +201,7 @@ def test_implication_missing_effect(self, make_evidence):
def test_no_implication_of_fact(
self, make_predicate, make_evidence, watt_mentioned
):
cool_fact = Fact(
make_predicate["p_no_shooting"], case_factors=watt_mentioned
)
cool_fact = Fact(make_predicate["p_no_shooting"], case_factors=watt_mentioned)
assert not make_evidence["no_shooting"] > cool_fact
assert not cool_fact > make_evidence["no_shooting"]

Expand Down
10 changes: 8 additions & 2 deletions tests/test_procedures.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,14 @@ def test_entities_of_inputs_for_identical_procedure(
assert f["f2"] in c1_again.inputs
assert f["f2"].context_factors == (watt_mentioned[1], watt_mentioned[0])

# Same Meaning
def test_wrong_role_for_added_factor(self, watt_factor, make_procedure):
with pytest.raises(ValueError):
new = make_procedure["c1"].add_factor(
incoming=watt_factor["f8"], role="generic"
)


class TestProcedureSameMeaning:
def test_procedure_equality(self, make_procedure, caplog):
caplog.set_level(logging.DEBUG)
assert make_procedure["c1"].means(make_procedure["c1_again"])
Expand Down Expand Up @@ -119,7 +125,7 @@ def test_procedure_implication_with_exact_quantity(self, make_procedure):

c2 = make_procedure["c2"]
c2_exact_quantity = make_procedure["c2_exact_quantity"]
assert c2_exact_quantity >= c2
assert c2_exact_quantity.implies(c2)

def test_procedure_general_quantity_does_not_imply_exact(
self, watt_factor, make_procedure
Expand Down
32 changes: 32 additions & 0 deletions tests/test_rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ def test_holding_len(self, make_holding):
assert len(make_holding["h1"]) == 2
assert len(make_holding["h3"]) == 5

def test_wrong_role_for_added_enactment(self, make_enactment, make_holding):
with pytest.raises(ValueError):
new = make_holding["h1"].add_enactment(
incoming=make_enactment["due_process_14"], role="inputs"
)


class TestSameMeaning:
def test_identical_holdings_equal(self, make_holding):
Expand All @@ -104,6 +110,17 @@ def test_holdings_equivalent_entity_orders_equal(self, make_holding):
"""
assert make_holding["h1"].means(make_holding["h1_entity_order"])

def test_added_enactment_changes_meaning(self, make_complex_rule, make_enactment):
due_process_rule = (
make_complex_rule["accept_murder_fact_from_relevance"]
+ make_enactment["due_process_5"]
)

assert not due_process_rule.means(
make_complex_rule["accept_murder_fact_from_relevance"])
assert not make_complex_rule["accept_murder_fact_from_relevance"].means(
due_process_rule)

def test_holdings_different_entities_unequal(self, make_holding):
assert not make_holding["h1"].means(make_holding["h1_easy"])

Expand Down Expand Up @@ -762,6 +779,21 @@ def test_add_complex_rule(self, make_factor, make_complex_rule):
assert new_rule.inputs == make_complex_rule["accept_relevance_testimony_ALL"].inputs
assert make_complex_rule["accept_murder_fact_from_relevance"].outputs[0] in new_rule.outputs

def test_add_disconnected_rules_returns_none(self, make_holding):
assert make_holding["h1"] + make_holding["h2_ALL"] is None

def test_rule_requiring_more_enactments_wont_add(self, make_enactment, make_complex_rule):
"""
This requirement might be changed, so that if the second
Rule requires more Enactments the method will just assume they're
available.
"""
due_process_rule = (
make_complex_rule["accept_murder_fact_from_relevance"]
+ make_enactment["due_process_5"]
)
assert make_complex_rule["accept_relevance_testimony_ALL"] + due_process_rule is None

class TestUnion:

def test_union_contradictory_outputs(self, make_opinion_with_holding):
Expand Down

0 comments on commit 1ea6c83

Please sign in to comment.