Skip to content

Commit 31b5cf8

Browse files
Merge branch 'main' into convert-test-reference-validator-to-pytest
2 parents 7fed648 + 66b3861 commit 31b5cf8

File tree

7 files changed

+246
-101
lines changed

7 files changed

+246
-101
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ are correct and expected given the context of the PR.
7272
2. Install all the dependencies from your project, which are typically specified in a `uv.lock` file.
7373

7474
```
75-
uv sync --all-extras --dev
75+
uv sync --all-extras --dev
7676
```
7777

7878
3. Run any python scripts or CLI commands by prefixing with `uv run`.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
id: S001
2+
name: Lord of the Rings
3+
genres:
4+
- fantasy
5+
creator:
6+
name: JRR Tolkien
7+
from_country: England
8+
books:
9+
- id: S001.1
10+
name: Fellowship of the Ring
11+
summary: Hobbits
12+
price: 5.99
13+
- id: S001.2
14+
name: The Two Towers
15+
summary: More hobbits
16+
price: 5.99
17+
- id: S001.3
18+
name: Return of the King
19+
summary: Yet more hobbits
20+
price: 6.99
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
id: S001
2+
name: Lord of the Rings
3+
genres:
4+
- fantasy
5+
creator:
6+
name: JRR Tolkien
7+
from_country: England
8+
books:
9+
- id: S001.1
10+
name: Fellowship of the Ring
11+
summary: Hobbits
12+
price: 5.99
13+
- id: S001.2
14+
name: The Two Towers
15+
summary: More hobbits
16+
price: 5.99
17+
- id: S001.3
18+
name: Return of the King
19+
summary: Yet more hobbits
20+
price: 6.99
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
persons:
2+
- id: P:001
3+
name: fred bloggs
4+
age_in_years: 33
5+
- id: P:002
6+
name: joe schmoe
7+
has_employment_history:
8+
- started_at_time: 2019-01-01
9+
is_current: true
10+
employed_at: ROR:1
11+
has_familial_relationships:
12+
- related_to: P:001
13+
type: SIBLING_OF
14+
has_medical_history:
15+
- started_at_time: 2019-01-01
16+
in_location: GEO:1234
17+
diagnosis:
18+
id: CODE:D0001
19+
name: headache
20+
in_code_system: DiseaseCodes
21+
procedure:
22+
id: CODE:P0001
23+
name: trepanation
24+
in_code_system: ProcedureCodes
25+
addresses:
26+
- street: 1 foo street
27+
city: foo city
28+
companies:
29+
- id: ROR:1
30+
name: foo
31+
activities:
32+
- id: A:1
33+
started_at_time: 2019-01-01
34+
was_associated_with: Agent:987
35+
code_systems:
36+
DiseaseCodes:
37+
id: DiseaseCodes
38+
name: disease codes
39+
ProcedureCodes:
40+
id: ProcedureCodes
41+
name: disease codes
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
persons:
2+
- id: P:001
3+
name: fred bloggs
4+
age_in_years: 33
5+
- id: P:002
6+
name: joe schmoe
7+
has_employment_history:
8+
- started_at_time: 2019-01-01
9+
is_current: true
10+
employed_at: ROR:1
11+
has_familial_relationships:
12+
- related_to: P:001
13+
type: SIBLING_OF
14+
has_medical_history:
15+
- started_at_time: 2019-01-01
16+
in_location: GEO:1234
17+
diagnosis:
18+
id: CODE:D0001
19+
name: headache
20+
in_code_system: DiseaseCodes
21+
procedure:
22+
id: CODE:P0001
23+
name: trepanation
24+
in_code_system: ProcedureCodes
25+
addresses:
26+
- street: 1 foo street
27+
city: foo city
28+
companies:
29+
- id: ROR:1
30+
name: foo
31+
activities:
32+
- id: A:1
33+
started_at_time: 2019-01-01
34+
was_associated_with: Agent:987
35+
code_systems:
36+
DiseaseCodes:
37+
id: DiseaseCodes
38+
name: disease codes
39+
ProcedureCodes:
40+
id: ProcedureCodes
41+
name: disease codes
Lines changed: 91 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import os
2-
import unittest
32
from pathlib import Path
43
from typing import Optional, TextIO, Union
54

5+
import pytest
66
from hbreader import FileInfo
77

8+
from linkml_runtime.dumpers import yaml_dumper
89
from linkml_runtime.loaders import RDFLoader, json_loader, rdf_loader, yaml_loader
910
from linkml_runtime.utils.yamlutils import YAMLRoot
1011
from tests.test_loaders_dumpers import LD_11_DIR, LD_11_SSL_SVR, LD_11_SVR
@@ -13,80 +14,92 @@
1314
from tests.test_loaders_dumpers.models.termci_schema import Package
1415

1516

16-
class LoadersUnitTest(LoaderDumperTestCase):
17-
env = env
18-
19-
@classmethod
20-
def setUpClass(cls) -> None:
21-
cls.context_server = cls.check_context_servers([LD_11_SVR, LD_11_SSL_SVR])
22-
if not cls.context_server:
23-
cls.context_server = LD_11_DIR
24-
25-
def test_yaml_loader(self):
26-
"""Load obo_sample.yaml, emit obo_sample_yaml.yaml and compare to obo_sample_output.yaml"""
27-
self.loader_test("obo_sample.yaml", Package, yaml_loader)
28-
29-
def test_json_loader_path(self):
30-
"""Load obo_sample.json, emit obo_sample_json.yaml and check the results"""
31-
REPO_ROOT = Path(__file__).parent.parent.parent
32-
path = REPO_ROOT / "tests" / "test_loaders_dumpers" / "input" / "obo_sample.json"
33-
data = json_loader.load(Path(path), Package, base_dir=self.env.indir)
34-
assert isinstance(data, Package)
35-
assert "system" in data
36-
37-
def test_json_loader(self):
38-
"""Load obo_sample.json, emit obo_sample_json.yaml and check the results"""
39-
self.loader_test("obo_sample.json", Package, json_loader)
40-
41-
def test_json_load_to_dict(self):
42-
data = json_loader.load_as_dict("obo_sample.json", base_dir=self.env.indir)
43-
assert isinstance(data, dict)
44-
assert "system" in data
45-
46-
def test_yaml_load_to_dict(self):
47-
data = yaml_loader.load_as_dict("obo_sample.yaml", base_dir=self.env.indir)
48-
assert isinstance(data, dict)
49-
assert "system" in data
50-
51-
@unittest.skipIf(True, "This test will not work until https://github.com/digitalbazaar/pyld/issues/149 is fixed")
52-
def test_rdf_loader(self):
53-
"""Load obo_sample.ttl, emit obo_sample_ttl.yaml and check the results
54-
Load obo_sample.jsonld, emit obo_sample_jsonld.yaml and check the results
55-
"""
56-
if self.context_server == LD_11_DIR:
57-
raise unittest.SkipTest("*****> Loading skipped until JSON-LD processor can handle non-http files")
58-
59-
contexts = os.path.join(self.context_server, "termci_schema_inlined.context.jsonld")
60-
fmt = "turtle"
61-
62-
class RDFLoaderWrapper(RDFLoader):
63-
def load(
64-
self,
65-
source: Union[str, dict, TextIO],
66-
target_class: type[YAMLRoot],
67-
*,
68-
base_dir: Optional[str] = None,
69-
metadata: Optional[FileInfo] = None,
70-
**_,
71-
) -> YAMLRoot:
72-
return rdf_loader.load(
73-
source,
74-
target_class,
75-
base_dir=LoadersUnitTest.env.indir,
76-
fmt=fmt,
77-
metadata=metadata,
78-
contexts=contexts,
79-
)
80-
81-
def loads(
82-
self, source: str, target_class: type[YAMLRoot], *, metadata: Optional[FileInfo] = None, **_
83-
) -> YAMLRoot:
84-
return rdf_loader.loads(source, target_class, contexts=contexts, fmt=fmt, metadata=metadata)
85-
86-
self.loader_test("obo_sample.ttl", Package, RDFLoaderWrapper())
87-
fmt = "json-ld"
88-
self.loader_test("obo_sample.jsonld", Package, RDFLoaderWrapper())
89-
90-
91-
if __name__ == "__main__":
92-
unittest.main()
17+
def loader_test(filename: str, model: Union[type[YAMLRoot], type], loader) -> None:
18+
"""
19+
Standalone loader test function for pytest functions
20+
"""
21+
22+
# Create a test case instance to use the loader_test method
23+
test_case = LoaderDumperTestCase()
24+
test_case.env = env
25+
test_case.loader_test(filename, model, loader)
26+
27+
28+
@pytest.fixture(scope="module")
29+
def context_server():
30+
"""Set up context server for testing."""
31+
# Check context servers - this mimics the original setUpClass logic
32+
context_server = LoaderDumperTestCase.check_context_servers([LD_11_SVR, LD_11_SSL_SVR])
33+
if not context_server:
34+
context_server = LD_11_DIR
35+
return context_server
36+
37+
38+
def test_yaml_loader():
39+
loader_test("obo_sample.yaml", Package, yaml_loader)
40+
41+
42+
def test_json_loader_path():
43+
"""Load obo_sample.json using Path object and check the results"""
44+
REPO_ROOT = Path(__file__).parent.parent.parent
45+
path = REPO_ROOT / "tests" / "test_loaders_dumpers" / "input" / "obo_sample.json"
46+
data = json_loader.load(Path(path), Package, base_dir=env.indir)
47+
assert isinstance(data, Package)
48+
assert "system" in data
49+
50+
51+
def test_json_loader():
52+
"""Load obo_sample.json, emit obo_sample_json.yaml and check the results"""
53+
loader_test("obo_sample.json", Package, json_loader)
54+
55+
56+
def test_json_load_to_dict():
57+
"""Test loading JSON file as dictionary"""
58+
data = json_loader.load_as_dict("obo_sample.json", base_dir=env.indir)
59+
assert isinstance(data, dict)
60+
assert "system" in data
61+
62+
63+
def test_yaml_load_to_dict():
64+
"""Test loading YAML file as dictionary"""
65+
data = yaml_loader.load_as_dict("obo_sample.yaml", base_dir=env.indir)
66+
assert isinstance(data, dict)
67+
assert "system" in data
68+
69+
70+
@pytest.mark.skip(reason="This test will not work until https://github.com/digitalbazaar/pyld/issues/149 is fixed")
71+
def test_rdf_loader(context_server):
72+
"""Load obo_sample.ttl and obo_sample.jsonld, emit yaml and check the results"""
73+
if context_server == LD_11_DIR:
74+
pytest.skip("*****> Loading skipped until JSON-LD processor can handle non-http files")
75+
76+
contexts = os.path.join(context_server, "termci_schema_inlined.context.jsonld")
77+
fmt = "turtle"
78+
79+
class RDFLoaderWrapper(RDFLoader):
80+
def load(
81+
self,
82+
source: Union[str, dict, TextIO],
83+
target_class: type[YAMLRoot],
84+
*,
85+
base_dir: Optional[str] = None,
86+
metadata: Optional[FileInfo] = None,
87+
**_,
88+
) -> YAMLRoot:
89+
return rdf_loader.load(
90+
source,
91+
target_class,
92+
base_dir=env.indir,
93+
fmt=fmt,
94+
metadata=metadata,
95+
contexts=contexts,
96+
)
97+
98+
def loads(
99+
self, source: str, target_class: type[YAMLRoot], *, metadata: Optional[FileInfo] = None, **_
100+
) -> YAMLRoot:
101+
return rdf_loader.loads(source, target_class, contexts=contexts, fmt=fmt, metadata=metadata)
102+
103+
loader_test("obo_sample.ttl", Package, RDFLoaderWrapper())
104+
fmt = "json-ld"
105+
loader_test("obo_sample.jsonld", Package, RDFLoaderWrapper())
Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,39 @@
1-
import unittest
1+
from pathlib import Path
22

3+
import pytest
4+
from hbreader import FileInfo
5+
from pydantic import BaseModel
6+
7+
from linkml_runtime.dumpers import yaml_dumper
38
from linkml_runtime.loaders import json_loader, yaml_loader
49
from tests.test_loaders_dumpers.environment import env
5-
from tests.test_loaders_dumpers.loaderdumpertestcase import LoaderDumperTestCase
610
from tests.test_loaders_dumpers.models.books_normalized_pydantic import BookSeries
711
from tests.test_loaders_dumpers.models.kitchen_sink_pydantic import Dataset
812

913

10-
class PydanticLoadersUnitTest(LoaderDumperTestCase):
11-
env = env
12-
13-
def test_yaml_loader_single(self):
14-
"""Load obo_sample.yaml, emit obo_sample_yaml.yaml and compare to obo_sample_output.yaml"""
15-
self.loader_test("book_series_lotr.yaml", BookSeries, yaml_loader)
16-
17-
def test_json_loader(self):
18-
"""Load obo_sample.json, emit obo_sample_json.yaml and check the results"""
19-
self.loader_test("book_series_lotr.json", BookSeries, json_loader)
20-
21-
def test_yaml_loader_kitchen_sink(self):
22-
self.loader_test("kitchen_sink_normalized_inst_01.yaml", Dataset, yaml_loader)
23-
24-
def test_json_loader_kitchen_sink(self):
25-
self.loader_test("kitchen_sink_normalized_inst_01.json", Dataset, json_loader)
26-
27-
28-
if __name__ == "__main__":
29-
unittest.main()
14+
@pytest.mark.parametrize(
15+
"filename,model,loader",
16+
[
17+
("book_series_lotr.yaml", BookSeries, yaml_loader),
18+
("book_series_lotr.json", BookSeries, json_loader),
19+
("kitchen_sink_normalized_inst_01.yaml", Dataset, yaml_loader),
20+
("kitchen_sink_normalized_inst_01.json", Dataset, json_loader),
21+
],
22+
)
23+
def test_loader_basemodel(filename, model, loader):
24+
name = Path(filename).stem
25+
type = Path(filename).suffix.lstrip(".")
26+
expected_yaml_file = env.input_path(f"{name}_{type}.yaml")
27+
28+
metadata = FileInfo()
29+
30+
python_obj: BaseModel = loader.load(filename, model, metadata=metadata, base_dir=env.indir)
31+
32+
# Load expected output
33+
with open(expected_yaml_file) as expf:
34+
expected = expf.read()
35+
36+
got = yaml_dumper.dumps(python_obj)
37+
expected_trimmed = expected.replace("\r\n", "\n").strip()
38+
got_trimmed = got.replace("\r\n", "\n").strip()
39+
assert expected_trimmed == got_trimmed

0 commit comments

Comments
 (0)