1818import pytest
1919
2020from 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 )
21+ from rocrate_validator .errors import DuplicateRequirementCheck , InvalidProfilePath , ProfileSpecificationError
22+ from rocrate_validator .models import Profile , ValidationContext , ValidationSettings , Validator
23+ from rocrate_validator .requirements .shacl .checks import SHACLCheck
2624from tests .ro_crates import InvalidFileDescriptorEntity , ValidROC
2725
2826# set up logging
@@ -57,7 +55,7 @@ def test_load_invalid_profile_from_validation_context(fake_profiles_path: str):
5755 "profiles_path" : "/tmp/random_path_xxx" ,
5856 "profile_identifier" : DEFAULT_PROFILE_IDENTIFIER ,
5957 "rocrate_uri" : ValidROC ().wrroc_paper ,
60- "enable_profile_inheritance" : False
58+ "enable_profile_inheritance" : False ,
6159 }
6260
6361 settings = ValidationSettings (** settings )
@@ -79,7 +77,7 @@ def test_load_valid_profile_without_inheritance_from_validation_context(fake_pro
7977 "profiles_path" : fake_profiles_path ,
8078 "profile_identifier" : "c" ,
8179 "rocrate_uri" : ValidROC ().wrroc_paper ,
82- "enable_profile_inheritance" : False
80+ "enable_profile_inheritance" : False ,
8381 }
8482
8583 settings = ValidationSettings (** settings )
@@ -128,7 +126,8 @@ def test_profile_spec_properties(fake_profiles_path: str):
128126 assert profile .version == "1.0.0" , "The profile version should be 1.0.0"
129127 assert profile .is_profile_of == ["https://w3id.org/a" ], "The profileOf property should be ['a']"
130128 assert profile .is_transitive_profile_of == [
131- "https://w3id.org/a" ], "The transitiveProfileOf property should be ['a']"
129+ "https://w3id.org/a"
130+ ], "The transitiveProfileOf property should be ['a']"
132131
133132
134133def test_profiles_loading_free_folder_structure (profiles_with_free_folder_structure_path : str ):
@@ -206,8 +205,9 @@ def __perform_test__(profile_identifier: str, expected_inherited_profiles: list[
206205
207206 # The number of profiles should be 1
208207 profiles_names = [_ .token for _ in profile .inherited_profiles ]
209- assert profiles_names == expected_inherited_profiles , \
210- f"The number of profiles should be { expected_inherited_profiles } "
208+ assert (
209+ profiles_names == expected_inherited_profiles
210+ ), f"The number of profiles should be { expected_inherited_profiles } "
211211
212212 # Test the inheritance mode with 1 profile
213213 __perform_test__ ("a" , [])
@@ -252,7 +252,7 @@ def test_load_invalid_profile_with_override_on_same_profile(fake_profiles_path:
252252 "profile_identifier" : "invalid-duplicated-shapes" ,
253253 "rocrate_uri" : ValidROC ().wrroc_paper ,
254254 "enable_profile_inheritance" : True ,
255- "allow_requirement_check_override" : False
255+ "allow_requirement_check_override" : False ,
256256 }
257257
258258 settings = ValidationSettings (** settings )
@@ -275,7 +275,7 @@ def test_load_valid_profile_with_override_on_inherited_profile(fake_profiles_pat
275275 "profile_identifier" : "c-overridden" ,
276276 "rocrate_uri" : ValidROC ().wrroc_paper ,
277277 "enable_profile_inheritance" : True ,
278- "allow_requirement_check_override" : True
278+ "allow_requirement_check_override" : True ,
279279 }
280280
281281 settings = ValidationSettings (** settings )
@@ -297,6 +297,34 @@ def test_load_valid_profile_with_override_on_inherited_profile(fake_profiles_pat
297297 assert len (requirements_checks ) == 3 , "The number of requirements should be 2"
298298
299299
300+ def test_zero_shape_target_profile_triggers_pyshacl_run (fake_profiles_path : str ):
301+ """Regression test for the 0-shape profile bug:
302+ when the target profile has no SHACL checks of its own,
303+ Validator must still drive a single pyshacl run
304+ on the merged shapes graph so inherited shapes get evaluated.
305+ Without the fix in `Validator.__ensure_target_shacl_run__`,
306+ no SHACLCheck would be recorded as executed for the wrapper target."""
307+
308+ settings = ValidationSettings (
309+ ** {
310+ "profiles_path" : fake_profiles_path ,
311+ "profile_identifier" : "c-wrapper" ,
312+ "rocrate_uri" : ValidROC ().wrroc_paper ,
313+ "enable_profile_inheritance" : True ,
314+ "allow_requirement_check_override" : True ,
315+ "disable_check_for_duplicates" : True ,
316+ }
317+ )
318+ result = Validator (settings ).validate ()
319+
320+ executed_shacl = [c for c in result .executed_checks if isinstance (c , SHACLCheck )]
321+ assert executed_shacl , (
322+ "Expected at least one inherited SHACLCheck to be executed for the "
323+ "c-wrapper target. None recorded — the zero-shape pyshacl run was "
324+ "skipped."
325+ )
326+
327+
300328def test_profile_parents (check_overriding_profiles_path : str ):
301329 """Test the order of the loaded profiles."""
302330 logger .debug ("The profiles path: %r" , check_overriding_profiles_path )
@@ -366,29 +394,31 @@ def test_profile_check_overriding(check_overriding_profiles_path: str):
366394
367395 def check_profile (profile , check , inherited_profiles , overridden_by , override ):
368396 # Check inherited profiles
369- assert len (profile .inherited_profiles ) == len (inherited_profiles ), \
370- f"The number of inherited profiles should be { len (inherited_profiles )} "
397+ assert len (profile .inherited_profiles ) == len (
398+ inherited_profiles
399+ ), f"The number of inherited profiles should be { len (inherited_profiles )} "
371400 inherited_profiles_tokens = [_ .token for _ in profile .inherited_profiles ]
372- assert set (inherited_profiles_tokens ) == set (inherited_profiles ), \
373- f"The inherited profiles should be { inherited_profiles } "
401+ assert set (inherited_profiles_tokens ) == set (
402+ inherited_profiles
403+ ), f"The inherited profiles should be { inherited_profiles } "
374404
375405 # Check overridden status
376- logger .debug ("%r overridden by: %r" , check .identifier , [
377- _ .requirement .profile .identifier for _ in check .overridden_by ])
378- assert check .overridden == (len (overridden_by ) > 0 ), \
379- f"The check overridden status should be { len (overridden_by ) > 0 } "
380- assert len (check .overridden_by ) == len (overridden_by ), \
381- f"The number of overridden checks should be { len (overridden_by )} "
406+ logger .debug (
407+ "%r overridden by: %r" , check .identifier , [_ .requirement .profile .identifier for _ in check .overridden_by ]
408+ )
409+ assert check .overridden == (
410+ len (overridden_by ) > 0
411+ ), f"The check overridden status should be { len (overridden_by ) > 0 } "
412+ assert len (check .overridden_by ) == len (
413+ overridden_by
414+ ), f"The number of overridden checks should be { len (overridden_by )} "
382415 overridden_by_tokens = [_ .requirement .profile .identifier for _ in check .overridden_by ]
383- assert set (overridden_by_tokens ) == set (overridden_by ), \
384- f"The overridden checks should be { overridden_by } "
416+ assert set (overridden_by_tokens ) == set (overridden_by ), f"The overridden checks should be { overridden_by } "
385417
386418 # Check override status
387- assert len (check .overrides ) == len (override ), \
388- f"The number of overridden checks should be { len (override )} "
419+ assert len (check .overrides ) == len (override ), f"The number of overridden checks should be { len (override )} "
389420 override_tokens = [_ .requirement .profile .identifier for _ in check .overrides ]
390- assert set (override_tokens ) == set (override ), \
391- f"The overridden checks should be { override } "
421+ assert set (override_tokens ) == set (override ), f"The overridden checks should be { override } "
392422
393423 # Check the number of requirements and checks of each profile
394424 for profile in profiles :
0 commit comments