Coverage for tests / test_provenance.py: 100%
74 statements
« prev ^ index » next coverage.py v7.12.0, created at 2026-07-17 16:43 +0000
« prev ^ index » next coverage.py v7.12.0, created at 2026-07-17 16:43 +0000
1#!/usr/bin/env python3
3# SPDX-FileCopyrightText: 2025-2026 Arcangelo Massari <arcangelo.massari@unibo.it>
4#
5# SPDX-License-Identifier: ISC
7"""
8Tests for the provenance generator script.
9"""
11import os
12import sys
13import tempfile
14import shutil
15import pytest
16from rdflib import Dataset, URIRef, Namespace
17from rdflib.namespace import RDF
19# Add the src directory to the path so we can import the module
20sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
21from changes_metadata_manager.generate_provenance import generate_provenance_snapshots
24@pytest.fixture
25def test_environment():
26 """Set up test data and environment."""
27 test_dir = tempfile.mkdtemp(dir="./tests/")
28 test_ttl = os.path.join(test_dir, "test_data.ttl")
29 test_output = tempfile.mktemp(suffix=".nq")
31 # Create test data file
32 with open(test_ttl, "w") as f:
33 f.write("""
34@prefix ex: <http://example.org/> .
35@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
36@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
37@prefix crm: <http://www.cidoc-crm.org/cidoc-crm/> .
39ex:item1 a crm:E22_Human-Made_Object ;
40 rdfs:label "Test Manuscript" .
42ex:item2 a crm:E21_Person ;
43 rdfs:label "John Doe" .
44 """)
46 yield {"test_dir": test_dir, "test_ttl": test_ttl, "test_output": test_output}
48 # Clean up
49 if os.path.exists(test_dir):
50 shutil.rmtree(test_dir)
51 if os.path.exists(test_output):
52 os.remove(test_output)
55def test_provenance_generation(test_environment):
56 """Test that provenance snapshots are generated correctly."""
57 # Get test environment variables
58 test_dir = test_environment["test_dir"]
59 test_output = test_environment["test_output"]
61 # Generate provenance snapshots
62 agent_orcid = "https://orcid.org/0000-0002-8420-0696"
63 primary_source = "https://example.org/primary-source"
64 generate_provenance_snapshots(
65 test_dir,
66 test_output,
67 output_format="trig",
68 agent_orcid=agent_orcid,
69 primary_source=primary_source,
70 )
72 # Check that the output file was created
73 assert os.path.exists(test_output), "Output file was not created"
75 # Load the output file
76 dataset = Dataset()
77 dataset.parse(test_output, format="trig")
79 # Define namespaces
80 PROV = Namespace("http://www.w3.org/ns/prov#")
82 # Check that we have the expected named graphs
83 expected_graphs = [
84 URIRef("http://example.org/item1/prov/"),
85 URIRef("http://example.org/item2/prov/"),
86 ]
87 actual_graphs = [g.identifier for g in dataset.graphs()]
89 for graph in expected_graphs:
90 assert graph in actual_graphs, f"Expected graph {graph} not found"
92 # Check that snapshots are typed as prov:Entity
93 item1_prov_graph = dataset.graph(URIRef("http://example.org/item1/prov/"))
94 item2_prov_graph = dataset.graph(URIRef("http://example.org/item2/prov/"))
96 item1_snapshot = URIRef("http://example.org/item1/prov/se/1")
97 item2_snapshot = URIRef("http://example.org/item2/prov/se/1")
99 assert (item1_snapshot, RDF.type, PROV.Entity) in item1_prov_graph, (
100 "item1 snapshot is not typed as prov:Entity"
101 )
102 assert (item2_snapshot, RDF.type, PROV.Entity) in item2_prov_graph, (
103 "item2 snapshot is not typed as prov:Entity"
104 )
106 # Check for specializationOf relationship
107 assert (
108 item1_snapshot,
109 PROV.specializationOf,
110 URIRef("http://example.org/item1"),
111 ) in item1_prov_graph
112 assert (
113 item2_snapshot,
114 PROV.specializationOf,
115 URIRef("http://example.org/item2"),
116 ) in item2_prov_graph
118 # Check for primary source relationship
119 assert (
120 item1_snapshot,
121 PROV.hadPrimarySource,
122 URIRef(primary_source),
123 ) in item1_prov_graph, "item1 snapshot missing primary source"
124 assert (
125 item2_snapshot,
126 PROV.hadPrimarySource,
127 URIRef(primary_source),
128 ) in item2_prov_graph, "item2 snapshot missing primary source"
131def test_input_format_parameter(test_environment):
132 """Test that the input_format parameter works correctly."""
133 # Get test environment variables
134 test_dir = test_environment["test_dir"]
135 test_output = test_environment["test_output"]
137 # Create a file with an unknown extension but containing Turtle content
138 test_unknown = os.path.join(test_dir, "unknown_format.xyz")
139 with open(test_unknown, "w") as f:
140 f.write("""
141@prefix ex: <http://example.org/> .
142@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
143@prefix crm: <http://www.cidoc-crm.org/cidoc-crm/> .
145ex:item3 a crm:E22_Human-Made_Object ;
146 rdfs:label "Test Object with Unknown Format" .
147 """)
149 # Generate provenance snapshots, specifying the format explicitly
150 agent_orcid = "https://orcid.org/0000-0002-8420-0696"
151 primary_source = "https://example.org/primary-source"
152 generate_provenance_snapshots(
153 test_dir,
154 test_output,
155 input_format="turtle",
156 output_format="trig",
157 agent_orcid=agent_orcid,
158 primary_source=primary_source,
159 )
161 # Check that the output file was created
162 assert os.path.exists(test_output), "Output file was not created"
164 # Load the output file
165 dataset = Dataset()
166 dataset.parse(test_output, format="trig")
168 # Define namespaces
169 PROV = Namespace("http://www.w3.org/ns/prov#")
171 # Check that we have the expected named graph for item3
172 item3_graph = URIRef("http://example.org/item3/prov/")
173 actual_graphs = [g.identifier for g in dataset.graphs()]
174 assert item3_graph in actual_graphs, f"Expected graph {item3_graph} not found"
176 # Check that snapshot is typed as prov:Entity
177 item3_prov_graph = dataset.graph(item3_graph)
178 item3_snapshot = URIRef("http://example.org/item3/prov/se/1")
179 assert (item3_snapshot, RDF.type, PROV.Entity) in item3_prov_graph, (
180 "item3 snapshot is not typed as prov:Entity"
181 )
184def test_empty_directory(test_environment):
185 """Test that the script handles empty directories correctly."""
186 # Create an empty directory
187 empty_dir = tempfile.mkdtemp(dir="./tests/")
188 test_output = test_environment["test_output"]
190 try:
191 # Generate provenance snapshots for the empty directory
192 agent_orcid = "https://orcid.org/0000-0002-8420-0696"
193 primary_source = "https://example.org/primary-source"
194 generate_provenance_snapshots(
195 empty_dir,
196 test_output,
197 agent_orcid=agent_orcid,
198 primary_source=primary_source,
199 )
201 # Check that the output file was not created
202 assert not os.path.exists(test_output), (
203 "Output file should not be created for empty directory"
204 )
205 finally:
206 # Clean up
207 if os.path.exists(empty_dir):
208 shutil.rmtree(empty_dir)
211if __name__ == "__main__":
212 pytest.main()