Skip to content

Commit

Permalink
Convert translate_algebra tests to pytest
Browse files Browse the repository at this point in the history
As far as I can tell all the tests inside test/translate_algebra
basically did the following:

```python
query_tree = parser.parseQuery(self.query_text)
query_algebra = algebra.translateQuery(query_tree)
self.query_from_algebra = translateAlgebra(query_algebra)

query_tree_2 = parser.parseQuery(self.query_from_algebra)
query_algebra_2 = algebra.translateQuery(query_tree_2)
self.query_from_query_from_algebra = translateAlgebra(query_algebra_2)
_pprint_query(self.query_from_query_from_algebra)
```

One test tried to also execute the query, but against a None valued
variable. And then there was some exception handling in specific place.

This change converts all of this to pytest using parameterization.

There are two tests that fail, and seem to also fail in the old test
structure, they are:

```python
AlgebraTest(
    "test_other__service1",
    "Test if a nested service pattern is properly translated"
    "into the query text.",
    pytest.mark.xfail(raises=RecursionError),
),
AlgebraTest(
    "test_property_path__negated_property_set",
    "Test if a negated property set gets properly translated into the query text.",
    pytest.mark.xfail(raises=TypeError, reason="fails in translateAlgebra"),
),
```
  • Loading branch information
aucampia committed Dec 31, 2021
1 parent 43d8622 commit e8c719a
Show file tree
Hide file tree
Showing 44 changed files with 268 additions and 1,065 deletions.
268 changes: 268 additions & 0 deletions test/test_translate_algebra.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
import logging
from dataclasses import dataclass, field
from io import StringIO
from pathlib import Path
from typing import Collection, Tuple, Union, cast

import pytest
from _pytest.mark.structures import Mark, MarkDecorator, ParameterSet

import rdflib.plugins.sparql.algebra as algebra
import rdflib.plugins.sparql.parser as parser
from rdflib.plugins.sparql.algebra import translateAlgebra


@pytest.fixture
def data_path() -> Path:
return Path(__file__).parent / "test_translate_algebra"


@dataclass
class AlgebraTest:
id: str
description: str
marks: Union[MarkDecorator, Collection[Union[MarkDecorator, Mark]]] = field(
default_factory=lambda: cast(Tuple[MarkDecorator], tuple())
)

@property
def filename(self) -> str:
return f"{self.id}.txt"

def pytest_param(self) -> ParameterSet:
return pytest.param(self, id=self.id, marks=self.marks)


def _format_query(query: str) -> str:
buffer = StringIO()
p = "{"
q = "}"
i = 0
f = 1

for e in query:
if e in p:
if not f:
buffer.write("\n")
buffer.write(" " * i + e)
buffer.write("\n")
i += 4
f = 1
elif e in q:
if not f:
buffer.write("\n")
i -= 4
f = 1
buffer.write(" " * i + e)
buffer.write("\n")
else:
if f:
buffer.write(" " * i)
buffer.write(e)
return buffer.getvalue()


algebra_tests = [
AlgebraTest(
"test_functions__functional_forms",
"Test if functional forms are properly translated into the query text.",
),
AlgebraTest(
"test_functions__functional_forms_not_exists",
"Test if the not exists form is properly translated into the query text.",
),
AlgebraTest(
"test_functions__functions_on_dates_and_time",
"Test if functions on dates and time are properly translated into the query text.",
),
AlgebraTest(
"test_functions__functions_on_numerics",
"Test if functions on numerics are properly translated into the query text.",
),
AlgebraTest(
"test_functions__functions_on_rdf_terms",
"Test if functions on rdf terms are properly translated into the query text.",
),
AlgebraTest(
"test_functions__functions_on_strings",
"Test if functions on strings are properly translated into the query text.",
),
AlgebraTest(
"test_functions__hash_functions",
"Test if hash functions are properly translated into the query text.",
),
AlgebraTest(
"test_graph_patterns__aggregate_join",
"Test if aggregate join including all aggregation functions"
"are properly translated into the query text.",
),
AlgebraTest(
"test_graph_patterns__bgp",
"Test if basic graph patterns are properly translated into the query text.",
),
AlgebraTest(
"test_graph_patterns__extend",
'Test if "extend" (=Bind explicitly or implicitly in projection)'
"gets properly translated into the query text.",
),
AlgebraTest(
"test_graph_patterns__filter",
"Test if filter gets properly translated into the query text.",
),
AlgebraTest(
"test_graph_patterns__graph",
'Test if "graph" gets properly translated into the query text.',
),
AlgebraTest(
"test_graph_patterns__group",
'Test if "group" gets properly translated into the query text.',
),
AlgebraTest(
"test_graph_patterns__having",
'Test if "having" gets properly translated into the query text.',
),
AlgebraTest(
"test_graph_patterns__join",
'Test if "join" gets properly translated into the query text.',
),
AlgebraTest(
"test_graph_patterns__left_join",
'Test if "left join" gets properly translated into "OPTIONAL {...}" in the query text.',
),
AlgebraTest(
"test_graph_patterns__minus",
'Test if "minus" gets properly translated into the query text.',
),
AlgebraTest(
"test_graph_patterns__union",
'Test if "union" gets properly translated into the query text.',
),
AlgebraTest(
"test_integration__complex_query1",
"Test a query with multiple graph patterns and solution modifiers"
"gets properly translated into the query text.",
),
AlgebraTest(
"test_operators__arithmetics",
"Test if arithmetics are properly translated into the query text.",
),
AlgebraTest(
"test_operators__conditional_and",
'Test if "conditional ands (&&)" are properly translated into the query text.',
),
AlgebraTest(
"test_operators__conditional_or",
'Test if "conditional ors (||)" are properly translated into the query text.',
),
AlgebraTest(
"test_operators__relational",
"Test if relational expressions are properly translated into the query text.",
),
AlgebraTest(
"test_operators__unary",
"Test if unary expressions are properly translated into the query text.",
),
AlgebraTest(
"test_other__service1",
"Test if a nested service pattern is properly translated"
"into the query text.",
pytest.mark.xfail(raises=RecursionError),
),
AlgebraTest(
"test_other__service2",
'Test if "service" along with its service string is properly translated'
"into the query text.",
),
AlgebraTest(
"test_other__values",
'Test if "values" gets properly translated into the query text.',
),
AlgebraTest(
"test_property_path__alternative_path",
"Test if an alternative path gets properly translated into the query text.",
),
AlgebraTest(
"test_property_path__inverse_path",
"Test if an inverse path gets properly translated into the query text.",
),
AlgebraTest(
"test_property_path__negated_property_set",
"Test if a negated property set gets properly translated into the query text.",
pytest.mark.xfail(raises=TypeError, reason="fails in translateAlgebra"),
),
AlgebraTest(
"test_property_path__one_or_more_path",
"Test if a oneOrMore path gets properly translated into the query text.",
),
AlgebraTest(
"test_property_path__sequence_path",
"Test if a sequence path gets properly translated into the query text.",
),
AlgebraTest(
"test_property_path__zero_or_more_path",
"Test if a zeroOrMore path gets properly translated into the query text.",
),
AlgebraTest(
"test_property_path__zero_or_one_path",
"Test if a zeroOrOne path gets properly translated into the query text.",
),
AlgebraTest(
"test_solution_modifiers__distinct",
'Test if "distinct" gets properly translated into the query text.',
),
AlgebraTest(
"test_solution_modifiers__order_by",
'Test if "order by" gets properly translated into the query text.',
),
AlgebraTest(
"test_solution_modifiers__reduced",
'Test if "reduced" gets properly translated into the query text.',
),
AlgebraTest(
"test_solution_modifiers__slice",
"Test if slice get properly translated into the limit and offset.",
),
AlgebraTest(
"test_solution_modifiers__to_multiset",
"Test if subqueries get properly translated into the query text.",
),
]


def test_all_files_used(data_path: Path) -> None:
all_files_names = {path.name for path in data_path.glob("*")}
expected_files = {test.filename for test in algebra_tests}

# These files are not being used, and they are empty, they were likely
# added as placeholders.
unused_files = {
"test_property_path__predicate_path.txt",
"test_solution_modifiers__project.txt",
}
all_files_names.difference_update(unused_files)

assert expected_files == all_files_names


@pytest.mark.parametrize("test_spec", [test.pytest_param() for test in algebra_tests])
def test_roundtrip(test_spec: AlgebraTest, data_path: Path) -> None:
"""
The query must also be executable and shall not violate any SPARQL query syntax.
"""
query_text = (data_path / test_spec.filename).read_text()

logging.info("checking expectation: %s", test_spec.description)
query_tree = parser.parseQuery(query_text)
query_algebra = algebra.translateQuery(query_tree)
query_from_algebra = translateAlgebra(query_algebra)

query_tree_2 = parser.parseQuery(query_from_algebra)
query_algebra_2 = algebra.translateQuery(query_tree_2)
query_from_query_from_algebra = translateAlgebra(query_algebra_2)
logging.debug(
"query_from_query_from_algebra = \n%s",
_format_query(query_from_query_from_algebra),
)
assert (
query_from_algebra == query_from_query_from_algebra
), f"failed expectation: {test_spec.description}"

0 comments on commit e8c719a

Please sign in to comment.