def test_identical_simple(schema, entity_id): """Everything should be reported as matches.""" fixture: Dict = { "some_multiple_text": ["foo"], "outer": { "some_multiple_text": ["bar", "baq"], "inner": { "some_multiple_text": ["baz"] } } } observation: Dict = copy.deepcopy(fixture) # 3 Matches expected: Outcome = Outcome() expected.matches.append( ValueMatch(entity_id, "immutable", "/some_multiple_text", "MultipleText", json.dumps(["foo"]))) expected.matches.append( ValueMatch(entity_id, "immutable", "/outer/some_multiple_text", "MultipleText", json.dumps(["bar", "baq"]))) expected.matches.append( ValueMatch(entity_id, "immutable", "/outer/inner/some_multiple_text", "MultipleText", json.dumps(["baz"]))) actual: Outcome = Outcome() crawl: CrawlImmutable = CrawlImmutable(entity_id, schema, fixture, observation, actual) crawl() assert expected == actual
def test_list_na_absent_match(complex_track, empty_track, entity_id): """If the fixture has an explicit |--|NA|--| and the item is missing in the actual, count it as a match.""" schema: Schema = Schema(empty_track, complex_track) fixture: Dict = { "outer": [{ "the_folder": { "inner": [{ "some_text": "foo" }, { "some_text": POLYTROPOS_NA }], } }] } observed: Dict = { "outer": [{ "the_folder": { "inner": [{ "some_text": "foo" }, {}], } }] } expected: Outcome = Outcome() expected.matches.append( ValueMatch(entity_id, "immutable", "/outer", "List", json.dumps(fixture["outer"]))) actual: Outcome = Outcome() crawl: CrawlImmutable = CrawlImmutable(entity_id, schema, fixture, observed, actual) crawl() assert expected == actual
def test_empty_actual(schema, entity_id): """Everything should be reported as missing.""" fixture: Dict = { "some_multiple_text": ["foo"], "outer": { "some_multiple_text": ["bar", "baq"], "inner": { "some_multiple_text": ["baz"] } } } observed: Dict = {} expected: Outcome = Outcome() expected.missings.append( MissingValue(entity_id, "immutable", "/some_multiple_text", "MultipleText", json.dumps(["foo"]))) expected.missings.append( MissingValue(entity_id, "immutable", "/outer/some_multiple_text", "MultipleText", json.dumps(["bar", "baq"]))) expected.missings.append( MissingValue(entity_id, "immutable", "/outer/inner/some_multiple_text", "MultipleText", json.dumps(["baz"]))) actual: Outcome = Outcome() crawl: CrawlImmutable = CrawlImmutable(entity_id, schema, fixture, observed, actual) crawl() assert expected == actual
def test_list_has_sentinal_value_raises(complex_track, empty_track, entity_id, bad_value): """If the fixture has an explicit |--|NA|--| and the item has the same string, an error is raised because we need to choose a new, truly unique sentinel value for missing data.""" schema: Schema = Schema(empty_track, complex_track) fixture: Dict = { "outer": [{ "the_folder": { "inner": [{ "some_text": "foo" }, { "some_text": POLYTROPOS_NA }], } }] } observed: Dict = { "outer": [{ "the_folder": { "inner": [{ "some_text": "foo" }, { "some_text": bad_value }], } }] } actual: Outcome = Outcome() crawl: CrawlImmutable = CrawlImmutable(entity_id, schema, fixture, observed, actual) with pytest.raises(ValueError): crawl()
def test_simple_na_present_with_value_mismatch(simple_track, empty_track, entity_id): """If the fixture has an explicit |--|NA|--| and the item is present in the actual with a non-null value, count it as a mismatch.""" schema: Schema = Schema(empty_track, simple_track) fixture: Dict = { "some_multiple_text": POLYTROPOS_NA, "outer": { "some_multiple_text": ["foo", "bar"] } } observation: Dict = { "some_multiple_text": ["123"], "outer": { "some_multiple_text": ["foo", "bar"] } } expected: Outcome = Outcome() expected.mismatches.append(ValueMismatch(entity_id, "immutable", "/some_multiple_text", "MultipleText", POLYTROPOS_NA, json.dumps(["123"]))) expected.matches.append(ValueMatch(entity_id, "immutable", "/outer/some_multiple_text", "MultipleText", json.dumps(["foo", "bar"]))) actual: Outcome = Outcome() crawl: CrawlImmutable = CrawlImmutable(entity_id, schema, fixture, observation, actual) crawl() assert expected == actual
def test_folder_na_present_as_none_mismatch(simple_track, empty_track, entity_id): """If the fixture has an explicit |--|NA|--| and the item is present in the actual with the value None, count it as a mismatch.""" schema: Schema = Schema(empty_track, simple_track) fixture: Dict = { "some_text": "bar", "outer": { "some_text": POLYTROPOS_NA, } } observation: Dict = { "some_text": "bar", "outer": { "some_text": None, } } expected: Outcome = Outcome() expected.mismatches.append( ValueMismatch(entity_id, "immutable", "/outer/some_text", "Text", POLYTROPOS_NA, None)) expected.matches.append( ValueMatch(entity_id, "immutable", "/some_text", "Text", "bar")) actual: Outcome = Outcome() crawl: CrawlImmutable = CrawlImmutable(entity_id, schema, fixture, observation, actual) crawl() assert expected == actual
def test_empty_both(schema, entity_id): """Outcomes should remain empty.""" fixture: Dict = {} observed: Dict = {} expected: Outcome = Outcome() actual: Outcome = Outcome() crawl: CrawlImmutable = CrawlImmutable(entity_id, schema, fixture, observed, actual) crawl() assert expected == actual
def test_simple_actual_has_sentinel_value_raises(simple_track, empty_track, entity_id, bad_value): """If the fixture has an explicit |--|NA|--|, and the observation has that actual string literal, it raises an error so that we can change the sentinel value.""" schema: Schema = Schema(empty_track, simple_track) fixture: Dict = {"some_text": POLYTROPOS_NA, "outer": {"some_text": "foo"}} observation: Dict = {"some_text": bad_value, "outer": {"some_text": "foo"}} actual: Outcome = Outcome() crawl: CrawlImmutable = CrawlImmutable(entity_id, schema, fixture, observation, actual) with pytest.raises(ValueError): crawl()
def _crawl(self, schema: Schema, fixture: Composite, actual: Composite) -> None: for period in fixture.periods: f_period: Dict = fixture.content[period] a_period: Optional[Dict] = actual.content.get(period) crawl_period: CrawlPeriod = CrawlPeriod(self.entity_id, schema, f_period, a_period, self.outcome, period) crawl_period() if "immutable" in fixture.content: f_immutable: Dict = fixture.content["immutable"] a_immutable: Optional[Dict] = actual.content.get("immutable") crawl_immutable: CrawlImmutable = CrawlImmutable( self.entity_id, schema, f_immutable, a_immutable, self.outcome) crawl_immutable()
def test_simple_na_absent_match(simple_track, empty_track, entity_id): """If the fixture has an explicit |--|NA|--| and the item is missing in the actual, count it as a match.""" schema: Schema = Schema(empty_track, simple_track) fixture: Dict = {"some_text": POLYTROPOS_NA, "outer": {"some_text": "foo"}} observation: Dict = {"outer": {"some_text": "foo"}} expected: Outcome = Outcome() expected.matches.append( ValueMatch(entity_id, "immutable", "/some_text", "Text", POLYTROPOS_NA)) expected.matches.append( ValueMatch(entity_id, "immutable", "/outer/some_text", "Text", "foo")) actual: Outcome = Outcome() crawl: CrawlImmutable = CrawlImmutable(entity_id, schema, fixture, observation, actual) crawl() assert expected == actual
def test_fixture_boolean_spec_folder(simple_track: Track, empty_track: Track, entity_id: str): schema: Schema = Schema(empty_track, simple_track) fixture: Dict = { "outer": True } observation: Dict = { "outer": { "some_multiple_text": ["foo", "bar"] } } expected: Outcome = Outcome() expected.invalids.append(InvalidPath(entity_id, "/outer", "immutable", True)) actual: Outcome = Outcome() crawl: CrawlImmutable = CrawlImmutable(entity_id, schema, fixture, observation, actual) crawl() assert expected == actual
def test_whole_folder_absent_match(simple_track, empty_track, entity_id): """If the fixture has an explicit |--|NA|--| nested inside a folder, and the whole folder is absent, that is a match (at least for that variable).""" schema: Schema = Schema(empty_track, simple_track) fixture: Dict = {"some_text": "bar", "outer": {"some_text": POLYTROPOS_NA}} observation: Dict = {"some_text": "bar"} expected: Outcome = Outcome() expected.matches.append( ValueMatch(entity_id, "immutable", "/outer/some_text", "Text", POLYTROPOS_NA)) expected.matches.append( ValueMatch(entity_id, "immutable", "/some_text", "Text", "bar")) actual: Outcome = Outcome() crawl: CrawlImmutable = CrawlImmutable(entity_id, schema, fixture, observation, actual) crawl() assert expected == actual
def test_list_na_present_as_none_mismatch(complex_track, empty_track, entity_id): """If the fixture has an explicit |--|NA|--| and the item is present in the actual with the value None, count it as a mismatch.""" schema: Schema = Schema(empty_track, complex_track) fixture: Dict = { "outer": [ { "the_folder": { "inner": [ {"some_multiple_text": ["foo", "bar"]}, {"some_multiple_text": POLYTROPOS_NA} ], } } ] } observed: Dict = { "outer": [ { "the_folder": { "inner": [ {"some_multiple_text": ["foo", "bar"]}, {"some_multiple_text": None} ], } } ] } expected: Outcome = Outcome() expected.mismatches.append(ValueMismatch(entity_id, "immutable", "/outer", "List", json.dumps(fixture["outer"]), json.dumps(observed["outer"]))) actual: Outcome = Outcome() crawl: CrawlImmutable = CrawlImmutable(entity_id, schema, fixture, observed, actual) crawl() assert expected == actual
def test_empty_fixture(schema, entity_id): """Outcomes should remain empty, even though actual has values.""" fixture: Dict = {} observed: Dict = { "some_multiple_text": ["foo"], "outer": { "some_multiple_text": ["bar", "baq"], "inner": { "some_multiple_text": ["baz"] } } } expected: Outcome = Outcome() actual: Outcome = Outcome() crawl: CrawlImmutable = CrawlImmutable(entity_id, schema, fixture, observed, actual) crawl() assert expected == actual