+
+ def assert_subfield(self, idx, path, value):
+ assert path
+
+ field = self.result[idx]
+ for p in path:
+ assert isinstance(field, dict)
+ assert p in field
+ field = field[p]
+
+ if isinstance(value, float):
+ assert Almost(value) == float(field)
+ elif value.startswith("^"):
+ assert re.fullmatch(value, field)
+ elif isinstance(field, dict):
+ assert field, eval('{' + value + '}')
+ else:
+ assert str(field) == str(value)
+
+
+ def assert_address_field(self, idx, field, value):
+ """ Check that result rows`idx` has a field `field` with value `value`
+ in its address. If idx is None, then all results are checked.
+ """
+ if idx is None:
+ todo = range(len(self.result))
+ else:
+ todo = [int(idx)]
+
+ for idx in todo:
+ assert 'address' in self.result[idx], \
+ "Result row {} has no field 'address'.\nFull row: {}"\
+ .format(idx, json.dumps(self.result[idx], indent=4))
+
+ address = self.result[idx]['address']
+ assert field in address, \
+ "Result row {} has no field '{}' in address.\nFull address: {}"\
+ .format(idx, field, json.dumps(address, indent=4))
+
+ assert address[field] == value, \
+ "\nBad value for row {} field '{}' in address. Expected: {}, got: {}.\nFull address: {}"""\
+ .format(idx, field, value, address[field], json.dumps(address, indent=4))
+
+ def match_row(self, row, context=None):