def assert_errors(result, expected_errors):
    """Assert that result errors match expected errors

    Uses substring matching to coorelate expected to actual errrors.

    Raise if any expected error is not matched or if any actual
    errors are found that were not matched by an expected error.

    This function has O(n**2) complexity on the number of errors.
    """
    def find_and_remove(expected_error):
        for i, actual_error in enumerate(actual_errors):
            if expected_error in actual_error:
                del actual_errors[i]
                return True
        return False

    actual_errors = list(result.errors)
    missing_errors = [e for e in expected_errors if not find_and_remove(e)]
    errors = []
    if missing_errors:
        errors.append("missing expected errors:")
        errors.extend(missing_errors)
    if actual_errors:
        if errors:
            errors.append("")
        errors.append("unexpected errors:")
        errors.extend(actual_errors)
    assert not errors, "\n".join(errors)