In this example we can ask to ontologies questions we expect them to answer.
Consider this simple ontology:
@prefix example: <http://example.onto/> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
example:Human rdfs:subClassOf example:Mortal .
example:name a owl:DatatypeProperty ;
rdfs:domain example:Human ;
rdfs:range xsd:string .
example:age a owl:DatatypeProperty ;
rdfs:domain example:Human ;
rdfs:range xsd:nonNegativeInteger .
example:Icaro a example:Human ;
example:name "Icaro" ;
example:age 26 .
It states that humans (instances of example:Human) can have name and age. Moreover, it defines an instance of example:Human, example:Icaro, that has a name Icaro and age of 26. So, we might want to check if the ontology can answer: is there any humans with the properties names and ages?
In Diderot we can check this by using this simple Python code below. In lines 6-13 we translated the question stated before as a SPARQL query. Then, in line 15, we call self.assert_that(can_answer(QUESTION).from_ontology(ONTOLOGY_FILE)) with an ontology file and a question as parameters to check if the ontology can answer the given question.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | from diderot import DiderotTestCase, can_answer
class ExpectedFactsTestCase(DiderotTestCase):
def test_check_can_answer(self):
QUESTION = """
SELECT ?human ?age ?name
WHERE {
?human a <http://example.onto/Human> ;
<http://example.onto/age> 26 ;
<http://example.onto/name> "Icaro" .
}
"""
ONTOLOGY_FILE = "example/db/answering_competency_question/ontology.n3"
self.assert_that(can_answer(QUESTION).from_ontology(ONTOLOGY_FILE))
|
Only SELECT and ASK queries are accepted. The test will pass if the query result is not empty (for SELECT queries) or True (for ASK queries).
If we ask to the aforementioned ontology if there is any god (that don’t exist, at least in the database) the test will fail:
$ make test
======================================================================
FAIL: test_is_there_a_god (test.test_competency_question_answering.ExpectedFactsTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File /path/test_competency_question_answering.py", line 51, in test_is_there_a_god
self.assert_that(can_answer(QUESTION).from_ontology(ONTOLOGY_FILE))
File /path/case.py", line 30, in assert_that
raise AssertionError(assertion.assertion_error_message)
AssertionError: ASK query returned false.
Query:
ASK {
?god a <http://example.onto/God> .
}
However, in this case we only wanted to check if the ontology can answer the question. Another useful use case is to check if the ontology can answer the question with a specific expected answer.
This can be done with the Python code below. The new thing is the argument EXPECTED_ANSWER passed to with_answer(). It states expected results for the SPARQL query as a list of tuples of python primitive types (int, string, etc) or a RDFlib.URIRef for URIs. The tuples should follow the order of the variables in the SELECT clause in the SPARQL query. So, the tuple (URIRef("http://example.onto/Icaro"), 26, "Icaro") match the variables ?human, ?age, ?name, respectively.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | from diderot import DiderotTestCase, can_answer
from rdflib import URIRef
class ExpectedFactsTestCase(DiderotTestCase):
def test_check_can_answer_with_answer(self):
QUESTION = """
SELECT ?human ?age ?name
WHERE {
?human a <http://example.onto/Human> ;
<http://example.onto/age> ?age ;
<http://example.onto/name> ?name .
}
"""
EXPECTED_ANSWER = [(URIRef("http://example.onto/Icaro"), 26, "Icaro")]
ONTOLOGY_FILE = "example/db/answering_competency_question/ontology.n3"
self.assert_that(can_answer(QUESTION).from_ontology(ONTOLOGY_FILE).\
with_answer(EXPECTED_ANSWER))
|
If expected answers and query results are not equal, the test will fail:
$ make test
======================================================================
FAIL: test_unexpected_answer (test.test_competency_question_answering.ExpectedFactsTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/path/test_competency_question_answering.py", line 75, in test_unexpected_answer
with_answer(EXPECTED_ANSWER))
File "/path/diderot/case.py", line 30, in assert_that
raise AssertionError(assertion.assertion_error_message)
AssertionError: Query result is different from expected answer.
given
X = [(rdflib.URIRef('http://example.onto/Icaro'), \
rdflib.Literal(u'26', datatype=rdflib.URIRef('http://www.w3.org/2001/XMLSchema#integer')),\
rdflib.Literal(u'Icaro'))]
and
Y = [(rdflib.URIRef('http://example.onto/Icaro'), \
64, \
'Icaro Medeiros')]
X[0][1] is rdflib.Literal(u'26', datatype=rdflib.URIRef('http://www.w3.org/2001/XMLSchema#integer'))
whereas Y[0][1] is 64
Note that the query result returns a rdflib.Literal object, that is transformed to a python primitive type (such as int or string) when trying to compare with expected answers if it is not a URI reference.