Skip to content

Commit 93e2b0b

Browse files
committed
test(shacl): ✅ regression test for zero-shape target profile
Add the `c-wrapper` profile fixture (pure inheritance from `c`, no own shapes) and a test asserting that validation still drives a pyshacl run on the merged shapes graph so inherited shapes are evaluated for the target profile.
1 parent bcb5cac commit 93e2b0b

2 files changed

Lines changed: 59 additions & 5 deletions

File tree

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Copyright (c) 2024-2026 CRS4
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
@prefix dct: <http://purl.org/dc/terms/> .
16+
@prefix prof: <http://www.w3.org/ns/dx/prof/> .
17+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
18+
19+
# A "wrapper" extension profile that inherits from c without declaring any
20+
# SHACL shape of its own. Used to exercise the zero-shape target profile
21+
# path: pyshacl must still run for inherited shapes to be evaluated.
22+
<https://w3id.org/c-wrapper>
23+
a prof:Profile ;
24+
rdfs:label "Profile C-wrapper" ;
25+
rdfs:comment """Pure inheritance from Profile C, no own checks."""@en ;
26+
dct:publisher <https://publisherCwrapper> ;
27+
prof:isProfileOf <https://w3id.org/c> ;
28+
prof:isTransitiveProfileOf <https://w3id.org/a>, <https://w3id.org/c> ;
29+
prof:hasToken "c-wrapper" ;
30+
.

tests/unit/requirements/test_profiles.py

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,11 @@
1616
import os
1717

1818
import pytest
19+
from requirements.shacl.checks import SHACLCheck
1920

2021
from rocrate_validator.constants import DEFAULT_PROFILE_IDENTIFIER
21-
from rocrate_validator.errors import (DuplicateRequirementCheck,
22-
InvalidProfilePath,
23-
ProfileSpecificationError)
24-
from rocrate_validator.models import (Profile, ValidationContext,
25-
ValidationSettings, Validator)
22+
from rocrate_validator.errors import DuplicateRequirementCheck, InvalidProfilePath, ProfileSpecificationError
23+
from rocrate_validator.models import Profile, ValidationContext, ValidationSettings, Validator
2624
from tests.ro_crates import InvalidFileDescriptorEntity, ValidROC
2725

2826
# set up logging
@@ -297,6 +295,32 @@ def test_load_valid_profile_with_override_on_inherited_profile(fake_profiles_pat
297295
assert len(requirements_checks) == 3, "The number of requirements should be 2"
298296

299297

298+
def test_zero_shape_target_profile_triggers_pyshacl_run(fake_profiles_path: str):
299+
"""Regression test for the 0-shape profile bug:
300+
when the target profile has no SHACL checks of its own,
301+
Validator must still drive a single pyshacl run
302+
on the merged shapes graph so inherited shapes get evaluated.
303+
Without the fix in `Validator.__ensure_target_shacl_run__`,
304+
no SHACLCheck would be recorded as executed for the wrapper target."""
305+
306+
settings = ValidationSettings(**{
307+
"profiles_path": fake_profiles_path,
308+
"profile_identifier": "c-wrapper",
309+
"rocrate_uri": ValidROC().wrroc_paper,
310+
"enable_profile_inheritance": True,
311+
"allow_requirement_check_override": True,
312+
"disable_check_for_duplicates": True,
313+
})
314+
result = Validator(settings).validate()
315+
316+
executed_shacl = [c for c in result.executed_checks
317+
if isinstance(c, SHACLCheck)]
318+
assert executed_shacl, (
319+
"Expected at least one inherited SHACLCheck to be executed for the "
320+
"c-wrapper target. None recorded — the zero-shape pyshacl run was "
321+
"skipped.")
322+
323+
300324
def test_profile_parents(check_overriding_profiles_path: str):
301325
"""Test the order of the loaded profiles."""
302326
logger.debug("The profiles path: %r", check_overriding_profiles_path)

0 commit comments

Comments
 (0)