From 022927109a47fdf24bfc45e20fbdbc000217d986 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Aur=C3=A9lien=20Lamercerie?=
 <aurelien.lamercerie@tetras-libre.fr>
Date: Tue, 8 Aug 2023 14:19:59 +0200
Subject: [PATCH] Update module Ontology to extract all elements

---
 .gitignore                                    |   4 +
 .../__pycache__/metrics.cpython-311.pyc       | Bin 1704 -> 2460 bytes
 .../__pycache__/ontology.cpython-311.pyc      | Bin 1930 -> 8889 bytes
 ontoScorer/__pycache__/scorer.cpython-311.pyc | Bin 1726 -> 1772 bytes
 ontoScorer/metrics.py                         |   9 +-
 ontoScorer/ontology.py                        | 143 ++++++++++++++++--
 ontoScorer/scorer.py                          |   2 +-
 tests/context.py                              |  10 ++
 tests/test_data/ontology_a.ttl                | 104 +++++++++++++
 tests/test_data/ontology_b.ttl                | 109 +++++++++++++
 tests/test_ontology.py                        |  86 ++++++++++-
 11 files changed, 446 insertions(+), 21 deletions(-)
 create mode 100644 tests/context.py
 create mode 100644 tests/test_data/ontology_a.ttl
 create mode 100644 tests/test_data/ontology_b.ttl

diff --git a/.gitignore b/.gitignore
index b0a5122..ad06501 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,5 @@
+*.pyc
+__pycache__
+*.todo
+
 env/*
diff --git a/ontoScorer/__pycache__/metrics.cpython-311.pyc b/ontoScorer/__pycache__/metrics.cpython-311.pyc
index b3d7b0f5b4273d827168b62f4a05c4bc64426e93..261155446af384b3fa8a8d952545d43dda6c6dec 100644
GIT binary patch
delta 1178
zcmZ3%J4cvrIWI340|Ns?r{SfPEi4oHB-|Vr7#OBAq%fo~<}l<kMlt3xMKR?vM=>*k
z#F%nea#^ET85x)u+!<1sTNqMUmN79ftY!k40m4yiDXhT^nrssj40tpdZ*lnNmE`B-
zr&n&AAj-(dH+dPOsX8kI0|PSy1H<QOj0_CzZ0+pR8A=#IdLcN4v4x?AaRKAxkBlNt
z%NQ6KRzt)Y7#Lg_Q2EOk85mZ>wRW+i7{k=UP{RZ<#t2m#0b|%Y*%vT@Y?tU{L$#rn
zxr058F@<@u9Fw>-TN+~uOAAL0GrDoLtdpylLYPYUC)Y5^3vj?(pTZE#pvmetc_XtJ
zzZp1;(-~?QV#R71YbL*E6i0L8M5Z3`V1|_pD;aOG<R#{&u4KB!q-Su8IXS1e7!=qF
z3PpUAU74-b6c`v78W=7pL_p96<^{sbB^F66lv*MM5xJlcQ6w;V9kV1hTMbb|24ZWG
zFarZakqC$oV_;x_+XoVmoUF{E&n5+8f(*5t%+Jgt2-cv<TqF(>mSA9Dn5@Ap!^Q{V
zfz)d;N=&X{He>{8uoIF634?5aYnc3xSsqDsy(CBl$X`VQ3=9mKoVS>ZQ%i1fr>B<0
zC+8#<7pE5AVlB<f%+D(VC8Hux`YmDs>EQ+upyXA=1JcM*#LK|Ia7(BtH7&I$H7_|e
zJ|CJIZwaNR=A{-TmZYX2#JCf4azGa7f^A@{j4vrFO})id8DCJ8no^_$GFu)L9H1Cg
z00ReyBEHFcSrn5%-YLGyz`*e1M+3uM8F^^Pn|oe254~g_deJ=mih1}2g@}s^5myu<
zF3Ln+k%_#(AxXT-2b15h)G`W8&SKS8<_Eb%8$^Jt1&2`)IIKYqD*_R`lXtKxt8lSu
ze_+5QAR0i*{507o|7TTjz9kF_m*C|5qSPWi5EGPPi`YOmfRuq_7orPf%`Xm{-29Z%
voK(9aLk0#0Q1&a%n(V=*>3M@e;{q!Bz#_n?{ec0K_y`jF0wU04!S(<EV*m?Z

delta 607
zcmbOuyn>f+IWI340|Ns?*u^s`*O({rNm!XMFfdGKNMT4}%wfo7jAG1Xiek!Tj$&qH
zU}A7*NMUMWNMT;a#K5qc38W8%qgYZ{f*CYfC*~MzTp`NH$UAu-qp1iB0|Nsy0|Ue7
zR}2gc?TqbA(-}G^Phb%@>10~Q$iT3g5u_D_YneM3(->12TR3W%T^N=zFfgnJ34?Jh
zO9xXLV+zyce@x<x%#$6M<+<V3mav2PlTDe8*;5#T88n&wCJV5-X{}_?WWL3uXK;%-
zIj8uRU{PvXYEf!la%y~XPGWI!YH=~hQ3?tTMZA;QS*$1TVAW;hpUlf@D_kVRz`#%>
z!oa|w$y_7~Vv9{SW0Pm&1u-QiN3&_Ufkh=je14EJ_FJr_d71fnMIa-KI6>kdUl)Nw
zw1^eN<pwEZE8+pM#X*EL0|Ue4-)yqH#cT`=3<?Pe3JMBEyps*t75PBc7dJ96F#Pz@
zz;I*o7WP_3{>erh+RA(&jS3(F<hUY`)kR=Ov4g}w1kdCK4rLW~R_zZAm;^)vNSU7|
z>*V7c3YtYA4%nv<Ignw$IBatBQ%ZAE?TS<x7#KjYQyei_i&NA50}C&s_6G(`;v-1x
L3y46I1)B;0r`>e}

diff --git a/ontoScorer/__pycache__/ontology.cpython-311.pyc b/ontoScorer/__pycache__/ontology.cpython-311.pyc
index aafe00e11d0aad998e8c002a193da51608e8d62d..b71e1d0f3cad1e8ed6574796cb86610805e54287 100644
GIT binary patch
literal 8889
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

delta 1222
zcmdn#+QnbLoR^o2fq{YH+=VkKRV)k)k3k$5W`Qz3+b}RNOlL@8NMX!j$YqRT%w>vV
zVg&J-a+q^jqF5Lim>Ap{QkYv9QdpKTF)*xVg6d?5VohNUX3%7N2@=p`y2a{Vlvt2)
zi`hTiN0adu=VVq!c}BI#t=#G?AXSqeaL;CC2xeHxIC&wD1p6)4bdc)F`*<XzZm|@n
z=A_-?&Ce^z&&f}(j4wzm$tVWdGkG7Qznq{yR9r7UJ~J<~BtD*xfq|jel!1Yvf#Jqv
zDPAL{&kU3Oc=H+kCV%HuaN=iRU?>9l{1#(+F*5@LgMxxWkswHrn}LC$N(^pXPJUua
zJj_yIkeO;=Gw)80<kOsNDkm`c0tYMOgUJ`96j@RjYndj0lv1u|TE@u0u$mF%XApK_
zh;@o#W?-mgu4SoZtzk-GuHt22sAZ~QEnx%6LvR)>xEZoR-eM?HF9Ep)BFRw0jA~{K
z69YpnTP=GH;{qfzAd2fjR1G_-21bS+=NiUf22B>fB9Qr-%zl1;FF|h9WWU8+oLW-E
z!@$6Bi@l^Mvmht6xCrE$TddAGiN(c5tRNZY#FP|Gjv{c#fdcmyA4F+MaeQ)qX<o@K
z#^PIy1-BUUZz(ax-{MLJ>5R`y%uOxkfP}9C2tWdvce1^ZWW59^IEx^`DI_{kb&6^S
z`wdB{4!#@W(o?Fgi)&sI*Sw%*b5Y#(in#3u1{O{YFwyDW;n-0)LGcEU)QrT7Jn|iW
zH~0mnI#2QJs_Uq`tDw0;aUstVo{78@7$;cW5D=fvJ&AjU*F^#KD+1~l1k``r;1}!Q
zD-vd4n7mO&+)ECev}+i$Kw$>PHH-*$8dESs5hnu!gC=7U$j_QgVE^CZ%P+}DErO>D
zNIHy{*HBghc}WQDr5pUhJvB4puE-i+;5WX&VGOd8!B3NYvOkMfJt$_2ctPn+oq>U2
zB?DLz5;p80Q4j%=E)D>j)xZFOADEa~wLUPw2`*+<K@b;8aB;ATe_((UB8;pi9~dx+
zB4JPpDFWHyr^$AUttcfeCo`!Clno%!E&vhH1IJ!LVsa`t1%NdaX@i^x$_QZB{^GF7
z%}*)KNwq7|V_;waC8y$K1_p)?%#4hTA4C`!<t{MDVj|BQ3~Cop(FYbWMw1T=n8Zhr
M*cT9iCJPQT0MtYoBLDyZ

diff --git a/ontoScorer/__pycache__/scorer.cpython-311.pyc b/ontoScorer/__pycache__/scorer.cpython-311.pyc
index 15863905c230a177ffba8eb4a80f491d1fd94ecb..7696fe257f510bead13598ef2ee71e027b9b4612 100644
GIT binary patch
delta 162
zcmdnT`-YcyIWI340|NuYC&NoA>Kl2dF>$dlFfcGPFfe?cF?lVM?_>=Y9;OAXlMgZp
zt1;9tWP#LzaScNj6PUrkz_5&ofnha_H(8#!n$c<UY-VL8o*tg-9CDX9<YtsykvH4H
qa>c^`B1ga#j(`g=wD~&oB}PV<$*Wiu_yQR}Ffg&g$jMh(UjhKS>L{!L

delta 132
zcmaFEyN{Q5IWI340|NuY^NVLv_%`xRW19Gyld){_S|(prCWab@EEbR?2xqZ^ND!`J
z$YKW3Alx_Ek-3`Da`IkgWl6aXmL8rf9C8a-t|*vY;4p`y%}gwp7#STWUu9L`w)nun
M#0nuMGqb$}03Y2TO#lD@

diff --git a/ontoScorer/metrics.py b/ontoScorer/metrics.py
index e905353..73fd413 100644
--- a/ontoScorer/metrics.py
+++ b/ontoScorer/metrics.py
@@ -8,6 +8,7 @@
 #==============================================================================
 
 from sklearn.metrics import precision_score, recall_score, f1_score
+from ontoScorer.ontology import Ontology
 
 class Metrics:
     def __init__(self):
@@ -15,12 +16,14 @@ class Metrics:
         self.recall = 0
         self.f1 = 0
 
-    def calculate(self, reference_classes, generated_classes):
+    def calculate(self, reference_ontology, generated_ontology):
+        reference_classes = set([cls.name() for cls in reference_ontology.get_classes()])
+        generated_classes = set([cls.name() for cls in generated_ontology.get_classes()])
+
         all_classes = reference_classes.union(generated_classes)
         y_true = [1 if cls in reference_classes else 0 for cls in all_classes]
         y_pred = [1 if cls in generated_classes else 0 for cls in all_classes]
 
         self.precision = precision_score(y_true, y_pred)
         self.recall = recall_score(y_true, y_pred)
-        self.f1 = f1_score(y_true, y_pred)
-
+        self.f1 = f1_score(y_true, y_pred)
\ No newline at end of file
diff --git a/ontoScorer/ontology.py b/ontoScorer/ontology.py
index f9403cb..90d4329 100644
--- a/ontoScorer/ontology.py
+++ b/ontoScorer/ontology.py
@@ -2,34 +2,149 @@
 # -*-coding:Utf-8 -*
 
 #==============================================================================
-# ontoScorer: [brief description of the module]
+# Ontology Analyzer
 #------------------------------------------------------------------------------
-# Detailed module description, if needed
+# Extracts various elements (Classes, Object Properties, Data Properties, 
+# Individuals, Annotations) from RDF/OWL ontologies. Enables foundational 
+# comparisons between different ontologies.
 #==============================================================================
 
-from rdflib import Graph, OWL
+from rdflib import Graph, RDF, RDFS, OWL
+from rdflib import URIRef, BNode
 from rdflib.namespace import split_uri
 
+
+#==============================================================================
+# Classes: Element, NamedElement and BlankElement
+#==============================================================================
+
+class Element:
+    def __init__(self, reference, graph):
+        self.reference = reference
+        self.graph = graph
+
+    def properties(self):
+        """Retrieve properties associated with the element."""
+        return list(self.graph.predicate_objects(subject=self.reference))
+
+    def name(self):
+        raise NotImplementedError("The method name() must be implemented by subclasses.")
+
+class NamedElement(Element):
+    def __init__(self, uri, graph):
+        super().__init__(uri, graph)
+        self.uri = uri
+
+    def __str__(self):
+        return str(self.uri)
+
+    def name(self):
+        _, element_name = split_uri(self.uri)
+        return element_name
+
+class BlankElement(Element):
+    def __init__(self, bnode, graph):
+        super().__init__(bnode, graph)
+        self.id = str(bnode)
+
+    def __str__(self):
+        return f"BNode: {self.id}"
+
+    def name(self):
+        return self.id
+
+
+
+#==============================================================================
+# Class: Ontology
+#==============================================================================
+
 class Ontology:
+    
+    #--------------------------------------------------------------------------
+    # Constructor(s)
+    #--------------------------------------------------------------------------
+    
     def __init__(self, ontology_path):
+        """Initialize the Ontology object."""
         self.path = ontology_path
         self.graph = self.load_ontology(ontology_path)
         self.classes = self.get_classes()
 
+
+    #--------------------------------------------------------------------------
+    # Base Method(s)
+    #--------------------------------------------------------------------------
+    
     def load_ontology(self, path):
+        """Load the ontology from the given path into an RDF graph."""
         g = Graph()
         g.parse(path, format="ttl")
         return g
 
+    def _get_elements_of_type(self, rdf_type):
+        """Extract all elements of a specific RDF type from the ontology."""
+        elements = []
+        for s, _, o in self.graph.triples((None, RDF.type, rdf_type)):
+            if isinstance(s, BNode):
+                elements.append(BlankElement(s, self.graph))
+            elif isinstance(s, URIRef):
+                elements.append(NamedElement(s, self.graph))
+        return elements
+
+
+    #--------------------------------------------------------------------------
+    # Extracting Method(s)
+    #--------------------------------------------------------------------------
+    
     def get_classes(self):
-        classes = set()
-        triplets_count = 0
-        for s, p, o in self.graph.triples((None, None, None)):
-            triplets_count += 1
-            if o == OWL.Class:
-                _, class_name = split_uri(s)
-                classes.add(class_name)
-        return classes
-
-    def compare_to(self, other_ontology):
-        return self.classes, other_ontology.classes
\ No newline at end of file
+        """Extract all classes from the ontology."""
+        return self._get_elements_of_type(OWL.Class)
+
+    def get_object_properties(self):
+        """Extract all object properties from the ontology."""
+        return self._get_elements_of_type(OWL.ObjectProperty)
+
+    def get_data_properties(self):
+        """Extract all data properties from the ontology."""
+        return self._get_elements_of_type(OWL.DatatypeProperty)
+    
+    def get_restrictions(self):
+        """Extract all restrictons from the ontology."""
+        return self._get_elements_of_type(OWL.Restriction)
+
+    def get_individuals(self) -> list:
+        """Extract all individuals from the ontology."""
+        all_types = set(self.graph.subjects(RDF.type))
+        non_individuals = {element.reference for element in 
+                           self.get_classes() + 
+                           self.get_object_properties() + 
+                           self.get_data_properties()}
+        
+        individuals = all_types - non_individuals
+        
+        return [NamedElement(i, self.graph) if isinstance(i, URIRef) else BlankElement(i, self.graph) 
+                for i in individuals]
+
+    def get_annotations(self):
+        """Extract all annotation comments from the ontology."""
+        annotations = set()
+        for _, _, o in self.graph.triples((None, RDFS.label, None)):
+            annotations.add(str(o))
+        return annotations
+
+
+    #--------------------------------------------------------------------------
+    # Comparison Method(s)
+    #--------------------------------------------------------------------------
+    
+    def compare_to(self, other_ontology) -> tuple:
+        """Compare classes of the current ontology with another."""
+        self_classes = {c.name() for c in self.classes}
+        other_classes = {c.name() for c in other_ontology.classes}
+        
+        # Pour des comparaisons plus avancées, ajustez ce code
+        unique_to_self = self_classes - other_classes
+        unique_to_other = other_classes - self_classes
+        
+        return unique_to_self, unique_to_other
diff --git a/ontoScorer/scorer.py b/ontoScorer/scorer.py
index 2ed8085..763d930 100644
--- a/ontoScorer/scorer.py
+++ b/ontoScorer/scorer.py
@@ -19,7 +19,7 @@ class OntoScorer:
 
     def compare(self):
         self.comparison_result = self.reference_ontology.compare_to(self.generated_ontology)
-        self.metrics.calculate(*self.comparison_result)
+        self.metrics.calculate(self.reference_ontology, self.generated_ontology)
 
     def generate_report(self):
         report = Report(self.reference_ontology,
diff --git a/tests/context.py b/tests/context.py
new file mode 100644
index 0000000..c611d6e
--- /dev/null
+++ b/tests/context.py
@@ -0,0 +1,10 @@
+import os
+import sys
+
+CURRENT_DIRPATH = os.path.dirname(os.path.abspath(__file__))
+LIB_PATH = os.path.dirname(f'{CURRENT_DIRPATH}/../..')
+print(f'Test Context: {LIB_PATH}')
+sys.path.insert(0, os.path.abspath(LIB_PATH))
+
+import ontoScorer
+ 
diff --git a/tests/test_data/ontology_a.ttl b/tests/test_data/ontology_a.ttl
new file mode 100644
index 0000000..2b5ee47
--- /dev/null
+++ b/tests/test_data/ontology_a.ttl
@@ -0,0 +1,104 @@
+@prefix ns1: <https://tenet.tetras-libre.fr/base-ontology#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<https://tenet.tetras-libre.fr/extract-result#SolarSystem> a owl:Individual,
+        <https://tenet.tetras-libre.fr/extract-result#system>,
+        <https://tenet.tetras-libre.fr/extract-result#system-hasPart-object>,
+        <https://tenet.tetras-libre.fr/extract-result#system-hasPart-sun> ;
+    rdfs:label "SolarSystem" ;
+    ns1:fromStructure "unknown" .
+
+<https://tenet.tetras-libre.fr/extract-result#direct> a owl:ObjectProperty ;
+    rdfs:label "direct" ;
+    rdfs:subPropertyOf ns1:Out_ObjectProperty ;
+    ns1:fromStructure "unknown" .
+
+<https://tenet.tetras-libre.fr/extract-result#gravitation-bind-system> a owl:Class ;
+    rdfs:subClassOf [ a owl:Restriction ;
+            owl:onProperty <https://tenet.tetras-libre.fr/extract-result#bind> ;
+            owl:someValuesFrom <https://tenet.tetras-libre.fr/extract-result#system> ],
+        <https://tenet.tetras-libre.fr/extract-result#gravitation> ;
+    ns1:fromStructure "unknown" .
+
+<https://tenet.tetras-libre.fr/extract-result#hasManner> a owl:ObjectProperty ;
+    rdfs:label "hasManner" ;
+    rdfs:subPropertyOf ns1:Out_ObjectProperty ;
+    ns1:fromStructure "unknown" .
+
+<https://tenet.tetras-libre.fr/extract-result#not-direct> a owl:ObjectProperty ;
+    rdfs:subPropertyOf ns1:Out_ObjectProperty ;
+    ns1:fromStructure "unknown" .
+
+<https://tenet.tetras-libre.fr/extract-result#object-orbit-hasManner-direct-sun> a owl:Class ;
+    rdfs:subClassOf [ a owl:Restriction ;
+            owl:onProperty <https://tenet.tetras-libre.fr/extract-result#orbit-hasManner-direct> ;
+            owl:someValuesFrom <https://tenet.tetras-libre.fr/extract-result#sun> ],
+        <https://tenet.tetras-libre.fr/extract-result#object> ;
+    ns1:fromStructure "unknown" .
+
+<https://tenet.tetras-libre.fr/extract-result#object-orbit-hasManner-not-direct-sun> a owl:Class ;
+    rdfs:subClassOf [ a owl:Restriction ;
+            owl:onProperty <https://tenet.tetras-libre.fr/extract-result#orbit-hasManner-not-direct> ;
+            owl:someValuesFrom <https://tenet.tetras-libre.fr/extract-result#sun> ],
+        <https://tenet.tetras-libre.fr/extract-result#object> ;
+    ns1:fromStructure "unknown" .
+
+<https://tenet.tetras-libre.fr/extract-result#bind> a owl:ObjectProperty ;
+    rdfs:label "bind" ;
+    rdfs:subPropertyOf ns1:Out_ObjectProperty ;
+    ns1:fromStructure "unknown" .
+
+<https://tenet.tetras-libre.fr/extract-result#gravitation> a owl:Class ;
+    rdfs:label "gravitation" ;
+    rdfs:subClassOf ns1:Entity ;
+    ns1:fromStructure "unknown" .
+
+<https://tenet.tetras-libre.fr/extract-result#orbit-hasManner-direct> a owl:ObjectProperty ;
+    rdfs:subPropertyOf <https://tenet.tetras-libre.fr/extract-result#orbit> ;
+    ns1:fromStructure "unknown" .
+
+<https://tenet.tetras-libre.fr/extract-result#orbit-hasManner-not-direct> a owl:ObjectProperty ;
+    rdfs:subPropertyOf <https://tenet.tetras-libre.fr/extract-result#orbit> ;
+    ns1:fromStructure "unknown" .
+
+<https://tenet.tetras-libre.fr/extract-result#system-hasPart-object> a owl:Class ;
+    rdfs:subClassOf [ a owl:Restriction ;
+            owl:onProperty <https://tenet.tetras-libre.fr/extract-result#hasPart> ;
+            owl:someValuesFrom <https://tenet.tetras-libre.fr/extract-result#object> ],
+        <https://tenet.tetras-libre.fr/extract-result#system> ;
+    ns1:fromStructure "unknown" .
+
+<https://tenet.tetras-libre.fr/extract-result#system-hasPart-sun> a owl:Class ;
+    rdfs:subClassOf [ a owl:Restriction ;
+            owl:onProperty <https://tenet.tetras-libre.fr/extract-result#hasPart> ;
+            owl:someValuesFrom <https://tenet.tetras-libre.fr/extract-result#sun> ],
+        <https://tenet.tetras-libre.fr/extract-result#system> ;
+    ns1:fromStructure "unknown" .
+
+<https://tenet.tetras-libre.fr/extract-result#hasPart> a owl:ObjectProperty ;
+    rdfs:label "hasPart" ;
+    rdfs:subPropertyOf ns1:Out_ObjectProperty ;
+    ns1:fromStructure "unknown" .
+
+<https://tenet.tetras-libre.fr/extract-result#orbit> a owl:ObjectProperty ;
+    rdfs:label "orbit" ;
+    rdfs:subPropertyOf ns1:Out_ObjectProperty ;
+    ns1:fromStructure "unknown" .
+
+<https://tenet.tetras-libre.fr/extract-result#object> a owl:Class ;
+    rdfs:label "object" ;
+    rdfs:subClassOf ns1:Entity ;
+    ns1:fromStructure "unknown" .
+
+<https://tenet.tetras-libre.fr/extract-result#sun> a owl:Class ;
+    rdfs:label "sun" ;
+    rdfs:subClassOf ns1:Entity ;
+    ns1:fromStructure "unknown" .
+
+<https://tenet.tetras-libre.fr/extract-result#system> a owl:Class ;
+    rdfs:label "system" ;
+    rdfs:subClassOf ns1:Entity,
+        ns1:Undetermined_Thing ;
+    ns1:fromStructure "unknown" .
+
diff --git a/tests/test_data/ontology_b.ttl b/tests/test_data/ontology_b.ttl
new file mode 100644
index 0000000..2b97132
--- /dev/null
+++ b/tests/test_data/ontology_b.ttl
@@ -0,0 +1,109 @@
+@prefix base: <https://reference.tetras-libre.fr/base-ontology#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix result: <https://reference.tetras-libre.fr/expected-result#> .
+
+result:SolarSystem a owl:Individual,
+        result:system,
+        result:system-isBindBy-gravitation,
+        result:system-hasPart-object-orbit-sun,
+        result:system-hasPart-sun ;
+    rdfs:label "SolarSystem" .
+
+result:direct a owl:ObjectProperty ;
+    rdfs:label "direct" ;
+    rdfs:subPropertyOf base:Out_ObjectProperty .
+
+result:gravitation-bind-system a owl:Class ;
+    rdfs:subClassOf [ a owl:Restriction ;
+            owl:onProperty result:bind ;
+            owl:someValuesFrom result:system ],
+        result:gravitation .
+
+result:hasManner a owl:ObjectProperty ;
+    rdfs:label "hasManner" ;
+    rdfs:subPropertyOf base:Out_ObjectProperty .
+
+result:not-direct a owl:ObjectProperty ;
+    rdfs:subPropertyOf base:Out_ObjectProperty .
+
+result:object-orbit-sun a owl:Class ;
+    rdfs:subClassOf [ a owl:Restriction ;
+            owl:onProperty result:orbit ;
+            owl:someValuesFrom result:sun ],
+        result:object .
+
+result:object-orbit-hasManner-direct-sun a owl:Class ;
+    rdfs:subClassOf [ a owl:Restriction ;
+            owl:onProperty result:orbit-hasManner-direct ;
+            owl:someValuesFrom result:sun ],
+        result:object-orbit-sun .
+
+result:object-orbit-hasManner-not-direct-sun a owl:Class ;
+    rdfs:subClassOf [ a owl:Restriction ;
+            owl:onProperty result:orbit-hasManner-not-direct ;
+            owl:someValuesFrom result:sun ],
+        result:object-orbit-sun .
+
+result:gravitation a owl:Class ;
+    rdfs:label "gravitation" ;
+    rdfs:subClassOf base:Entity .
+
+result:system-isBindBy-gravitation a owl:Class ;
+    rdfs:subClassOf [ a owl:Restriction ;
+            owl:onProperty result:isBindBy ;
+            owl:someValuesFrom result:gravitation ],
+        result:system .
+
+result:system-hasPart-object a owl:Class ;
+    rdfs:subClassOf [ a owl:Restriction ;
+            owl:onProperty result:hasPart ;
+            owl:someValuesFrom result:object ],
+        result:system .
+
+result:system-hasPart-object-orbit-sun a owl:Class ;
+    rdfs:subClassOf [ a owl:Restriction ;
+            owl:onProperty result:hasPart ;
+            owl:someValuesFrom result:object-orbit-sun ],
+        result:system-hasPart-object .
+
+result:system-hasPart-sun a owl:Class ;
+    rdfs:subClassOf [ a owl:Restriction ;
+            owl:onProperty result:hasPart ;
+            owl:someValuesFrom result:sun ],
+        result:system .
+
+result:bind a owl:ObjectProperty ;
+    rdfs:label "bind" ;
+    rdfs:subPropertyOf base:Out_ObjectProperty .
+
+result:isBindBy owl:inverseOf result:bind ;
+    rdfs:label "isBindBy" ;
+    rdfs:subPropertyOf base:Out_ObjectProperty .
+
+result:orbit a owl:ObjectProperty ;
+    rdfs:label "orbit" ;
+    rdfs:subPropertyOf base:Out_ObjectProperty .
+
+result:orbit-hasManner-direct a owl:ObjectProperty ;
+    rdfs:subPropertyOf result:orbit .
+
+result:orbit-hasManner-not-direct a owl:ObjectProperty ;
+    rdfs:subPropertyOf result:orbit .
+
+result:hasPart a owl:ObjectProperty ;
+    rdfs:label "hasPart" ;
+    rdfs:subPropertyOf base:Out_ObjectProperty .
+
+result:object a owl:Class ;
+    rdfs:label "object" ;
+    rdfs:subClassOf base:Entity .
+
+result:system a owl:Class ;
+    rdfs:label "system" ;
+    rdfs:subClassOf base:Entity.
+
+result:sun a owl:Class ;
+    rdfs:label "sun" ;
+    rdfs:subClassOf base:Entity .
+
diff --git a/tests/test_ontology.py b/tests/test_ontology.py
index 4415d78..8da3b2e 100644
--- a/tests/test_ontology.py
+++ b/tests/test_ontology.py
@@ -2,9 +2,89 @@
 # -*-coding:Utf-8 -*
 
 #==============================================================================
-# ontoScorer: [brief description of the module]
+# test_ontology: Ontology Testing Module
 #------------------------------------------------------------------------------
-# Detailed module description, if needed
+# Contains tests for verifying functionality of the Ontology class.
 #==============================================================================
 
-# TODO
+import unittest
+import os
+from context import ontoScorer
+from ontoScorer.ontology import Ontology
+from rdflib import URIRef
+
+class TestOntology(unittest.TestCase):
+
+    def setUp(self):
+        # Test ontology paths
+        DATA_FOLDER_PATH = f'{os.path.dirname(os.path.abspath(__file__))}/test_data'
+        self.ontology1_path = f"{DATA_FOLDER_PATH}/ontology_a.ttl"
+        self.ontology2_path = f"{DATA_FOLDER_PATH}/ontology_b.ttl"
+        self.onto1 = Ontology(self.ontology1_path)
+        self.onto2 = Ontology(self.ontology2_path)
+
+    def test_load_ontology(self):
+        self.assertIsNotNone(self.onto1.graph)
+        self.assertIsNotNone(self.onto2.graph)
+
+    def test_get_classes(self):
+        classes1_names = {c.name() for c in self.onto1.get_classes()}
+        classes2_names = {c.name() for c in self.onto2.get_classes()}
+        
+        self.assertIn("gravitation-bind-system", classes1_names)
+        self.assertIn("gravitation-bind-system", classes1_names)
+        self.assertIn("object-orbit-hasManner-direct-sun", classes1_names)
+        self.assertIn("object-orbit-hasManner-not-direct-sun", classes1_names)
+        self.assertIn("gravitation", classes1_names)
+        self.assertIn("system-hasPart-object", classes1_names)
+        self.assertIn("system-hasPart-sun", classes1_names)
+        self.assertIn("object", classes1_names)
+        self.assertIn("sun", classes1_names)
+        self.assertIn("system", classes1_names)
+        self.assertNotIn("system-isBindBy-gravitation", classes1_names)
+        self.assertIn("system-isBindBy-gravitation", classes2_names)
+
+    def test_get_object_properties(self):
+        object_properties_names = {op.name() for op in self.onto1.get_object_properties()}
+        
+        self.assertIn("direct", object_properties_names)
+        self.assertIn("hasManner", object_properties_names)
+        self.assertIn("not-direct", object_properties_names)
+        self.assertIn("bind", object_properties_names)
+        self.assertIn("orbit-hasManner-direct", object_properties_names)
+        self.assertIn("orbit-hasManner-not-direct", object_properties_names)
+        self.assertIn("hasPart", object_properties_names)
+        self.assertIn("orbit", object_properties_names)
+
+    def test_get_data_properties(self):
+        data_properties_names = {dp.name() for dp in self.onto1.get_data_properties()}
+        
+        self.assertEqual(len(data_properties_names), 0)
+
+    def test_get_restrictions(self):
+        restrictions = self.onto1.get_restrictions()
+        expected_restrictions_count = 5 
+        self.assertEqual(len(restrictions), expected_restrictions_count)
+
+    def test_get_individuals(self):
+        individuals_names = {ind.name() for ind in self.onto1.get_individuals()}
+        
+        self.assertIn("SolarSystem", individuals_names)
+        self.assertNotIn("gravitation", individuals_names)
+
+    def test_get_annotations(self):
+        annotations = self.onto1.get_annotations()
+        self.assertIn("SolarSystem", annotations)
+        self.assertIn("direct", annotations)
+        self.assertIn("gravitation", annotations)
+        self.assertIn("orbit", annotations)
+        self.assertIn("object", annotations)
+        self.assertIn("sun", annotations)
+        self.assertIn("system", annotations)
+
+    def test_compare_to(self):
+        comparison_result = self.onto1.compare_to(self.onto2)
+        self.assertIsInstance(comparison_result, tuple)
+
+if __name__ == "__main__":
+    unittest.main()
-- 
GitLab