Skip to content

Commit be5426b

Browse files
authored
Merge pull request #402 from ialarmedalien/unittest_to_pytest
Converting the "issue" tests to pytest
2 parents bda4df0 + 3876c7e commit be5426b

21 files changed

+523
-655
lines changed

linkml_runtime/loaders/loader_root.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def load(self, *args, **kwargs) -> Union[BaseModel, YAMLRoot]:
7575
:return: instance of target_class
7676
"""
7777
results = self.load_any(*args, **kwargs)
78-
if isinstance(results, BaseModel) or isinstance(results, YAMLRoot):
78+
if isinstance(results, (BaseModel, YAMLRoot)):
7979
return results
8080
else:
8181
raise ValueError(f"Result is not an instance of BaseModel or YAMLRoot: {type(results)}")
@@ -145,9 +145,9 @@ def _construct_target_class(
145145
elif isinstance(data_as_dict, dict):
146146
if issubclass(target_class, BaseModel):
147147
return target_class.model_validate(data_as_dict)
148-
else:
149-
return target_class(**data_as_dict)
150-
elif isinstance(data_as_dict, JsonObj):
148+
return target_class(**data_as_dict)
149+
150+
if isinstance(data_as_dict, JsonObj):
151151
return [target_class(**as_dict(x)) for x in data_as_dict]
152152
else:
153153
raise ValueError(f"Unexpected type {data_as_dict}")
@@ -170,7 +170,7 @@ def _read_source(
170170
if not isinstance(source, dict):
171171
# Try to get local version of schema, if one is known to exist
172172
try:
173-
if str(source) in URI_TO_LOCAL.keys():
173+
if str(source) in URI_TO_LOCAL:
174174
source = str(URI_TO_LOCAL[str(source)])
175175
except (TypeError, KeyError) as e:
176176
# Fine, use original `source` value

tests/test_issues/input/linkml_issue_478.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ classes:
99
- id
1010
- preferred label
1111
- SOURCE
12-
biosample processing:
12+
biosample_processing:
1313
is_a: named thing
1414
attributes:
1515
processingMethod:
@@ -23,4 +23,4 @@ classes:
2323
slots:
2424
id:
2525
preferred label:
26-
SOURCE:
26+
SOURCE:

tests/test_issues/test_dataclass_extensions_376.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
import sys
2-
import pytest
3-
import importlib.util
41
import dataclasses
2+
import importlib.util
3+
4+
import pytest
55

66

77
def import_patch_module():
8-
"""Fresh import to ensure warning is triggered"""
8+
"""Fresh import to ensure warning is triggered."""
99
spec = importlib.util.find_spec("linkml_runtime.utils.dataclass_extensions_376")
1010
mod = importlib.util.module_from_spec(spec)
1111
spec.loader.exec_module(mod)
1212
return mod
1313

1414

15-
def test_patch_module_emits_deprecation_warning():
16-
"""All Python versions: emits DeprecationWarning and defines compatibility symbols"""
15+
def test_patch_module_emits_deprecation_warning() -> None:
16+
"""All Python versions: emits DeprecationWarning and defines compatibility symbols."""
1717
with pytest.warns(DeprecationWarning):
1818
mod = import_patch_module()
1919

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,13 @@
1-
from unittest import TestCase
2-
1+
import pytest
32
import yaml.constructor
43

54
from linkml_runtime.linkml_model import SchemaDefinition
65
from linkml_runtime.loaders import yaml_loader
76
from tests.test_issues.environment import env
87

98

10-
class Issue1040TestCase(TestCase):
11-
"""
12-
https://github.com/linkml/linkml/issues/1040
13-
"""
14-
15-
env = env
16-
17-
def test_issue_1040_file_name(self):
18-
"""issue_1040.yaml has a parsing error is confusing as all getout when accompanied by a stack
19-
trace. We use this to make sure that the file name gets in correctly."""
20-
with self.assertRaises(yaml.constructor.ConstructorError) as e:
21-
yaml_loader.load(env.input_path("issue_1040.yaml"), SchemaDefinition)
22-
self.assertIn('"issue_1040.yaml"', str(e.exception))
9+
def test_issue_1040_file_name() -> None:
10+
"""issue_1040.yaml has a parsing error is confusing as all getout when accompanied by a stack
11+
trace. We use this to make sure that the file name gets in correctly."""
12+
with pytest.raises(yaml.constructor.ConstructorError, match='"issue_1040.yaml"'):
13+
yaml_loader.load(env.input_path("issue_1040.yaml"), SchemaDefinition)
Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,14 @@
1-
"""
2-
Created on 2023-03-24
1+
import pytest
32

4-
@author: wf
5-
"""
6-
7-
from unittest import TestCase
83
from linkml_runtime.utils.metamodelcore import URI
94

105

11-
class Issue1355TestCase(TestCase):
12-
"""
13-
https://github.com/linkml/linkml/issues/1355
14-
improve invalid URL message
15-
"""
6+
def test_issue_1355_invalid_url_message() -> None:
7+
"""Check that quotes are used when referencing invalid urls to improve troubleshooting UX.
168
17-
def test_issue_1355_invalid_url_message(self):
18-
"""
19-
check that quotes are used when referencing invalid urls so that
20-
the visiblity of the problem gets better
21-
"""
22-
# note the trailing blank
23-
url = "https://ceur-ws.org/Vol-2931/ICBO_2019_paper_20.pdf "
24-
try:
25-
_uri = URI(url)
26-
except ValueError as vex:
27-
msg = str(vex)
28-
# 'https://ceur-ws.org/Vol-2931/ICBO_2019_paper_20.pdf ': is not a valid URI
29-
self.assertTrue(".pdf '" in msg)
9+
See https://github.com/linkml/linkml/issues/1355, improve invalid URL message
10+
"""
11+
# note the trailing blank
12+
url = "https://ceur-ws.org/Vol-2931/ICBO_2019_paper_20.pdf "
13+
with pytest.raises(ValueError, match="'https://ceur-ws.org/Vol-2931/ICBO_2019_paper_20.pdf ': is not a valid URI"):
14+
URI(url)

tests/test_issues/test_issue_163.py

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,31 @@
1-
import unittest
2-
from typing import Callable
1+
from collections.abc import Callable
32

4-
from linkml_runtime.dumpers import json_dumper, yaml_dumper, rdf_dumper
5-
from tests.test_issues.environment import env
6-
from tests.test_loaders_dumpers.loaderdumpertestcase import LoaderDumperTestCase
3+
from linkml_runtime.dumpers import json_dumper, rdf_dumper, yaml_dumper
74
from linkml_runtime.utils.compile_python import compile_python
5+
from tests.test_issues.environment import env
86

97

10-
class Issue368TestCase(LoaderDumperTestCase):
11-
env = env
12-
13-
def header(self, txt: str) -> str:
14-
return "\n" + ("=" * 20) + f" {txt} " + ("=" * 20)
15-
16-
def test_issue_368_enums(self):
17-
"""Test Enum generation"""
18-
19-
module = compile_python(env.input_path("issue_368.py"))
8+
def header(txt: str) -> str:
9+
return "\n" + ("=" * 20) + f" {txt} " + ("=" * 20)
2010

21-
enum_inst = module.SampleEnum("pva") # EnumInstanceImpl
22-
example = module.SampleClass(slot_1="pva")
23-
assert hasattr(example, "slot_1")
24-
assert example.slot_1.code.text == enum_inst.code.text
25-
assert str(example.slot_1) == "pva"
2611

27-
def dump_and_load(dumper: Callable, sfx: str) -> None:
28-
fname = env.actual_path(f"issue_368_1.{sfx}")
29-
dumper(example, fname)
30-
with open(fname) as f:
31-
print(f"\n----- {sfx} -----")
32-
print(f.read())
12+
def test_issue_368_enums() -> None:
13+
"""Test Enum generation."""
14+
module = compile_python(env.input_path("issue_368.py"))
3315

34-
dump_and_load(json_dumper.dump, "json")
35-
dump_and_load(yaml_dumper.dump, "yaml")
36-
dump_and_load(lambda obj, fname: rdf_dumper.dump(obj, fname, env.input_path("issue_368.context.jsonld")), "ttl")
16+
enum_inst = module.SampleEnum("pva") # EnumInstanceImpl
17+
example = module.SampleClass(slot_1="pva")
18+
assert hasattr(example, "slot_1")
19+
assert example.slot_1.code.text == enum_inst.code.text
20+
assert str(example.slot_1) == "pva"
3721

22+
def dump_and_load(dumper: Callable, sfx: str) -> None:
23+
fname = env.actual_path(f"issue_368_1.{sfx}")
24+
dumper(example, fname)
25+
with open(fname) as f:
26+
print(f"\n----- {sfx} -----")
27+
print(f.read())
3828

39-
if __name__ == "__main__":
40-
unittest.main()
29+
dump_and_load(json_dumper.dump, "json")
30+
dump_and_load(yaml_dumper.dump, "yaml")
31+
dump_and_load(lambda obj, fname: rdf_dumper.dump(obj, fname, env.input_path("issue_368.context.jsonld")), "ttl")

tests/test_issues/test_issue_6.py

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import unittest
2-
31
import hbreader
2+
import pytest
43
import yaml
54

65
from linkml_runtime.utils.yamlutils import DupCheckYamlLoader, TypedNode
@@ -13,26 +12,29 @@
1312
"""
1413

1514

16-
class Issue6TestCase(unittest.TestCase):
17-
def test_loc_function(self):
18-
inp = yaml.load(hbreader.hbread(inp_yaml), DupCheckYamlLoader)
19-
self.assertEqual('File "<unicode string>", line 3, col 8: ', TypedNode.yaml_loc(inp["foo"]["x"]))
20-
self.assertEqual('File "<unicode string>", line 3, col 8', TypedNode.yaml_loc(inp["foo"]["x"], suffix=""))
21-
self.assertEqual('File "<unicode string>", line 4, col 8: ', TypedNode.yaml_loc(inp["foo"]["y"]))
22-
self.assertEqual(
23-
'File "<unicode string>", line 4, col 8I yam that I yam',
24-
TypedNode.yaml_loc(inp["foo"]["y"], suffix=inp["foo"]["y"]),
25-
)
26-
self.assertEqual('File "<unicode string>", line 5, col 8: ', TypedNode.yaml_loc(inp["foo"]["z"]))
27-
28-
with self.assertWarns(DeprecationWarning) as cm:
29-
self.assertEqual('File "<unicode string>", line 3, col 8', TypedNode.loc(inp["foo"]["x"]))
30-
self.assertEqual("Call to deprecated method loc. (Use yaml_loc instead)", cm.warning.args[0])
31-
32-
self.assertEqual("", TypedNode.yaml_loc(None))
33-
self.assertEqual("", TypedNode.yaml_loc("abc"))
34-
self.assertEqual("", TypedNode.yaml_loc(["a", "b"]))
35-
36-
37-
if __name__ == "__main__":
38-
unittest.main()
15+
def test_loc_function() -> None:
16+
"""Test the TypedNode.yaml_loc function."""
17+
inp = yaml.load(hbreader.hbread(inp_yaml), DupCheckYamlLoader)
18+
assert TypedNode.yaml_loc(inp["foo"]["x"]) == 'File "<unicode string>", line 3, col 8: '
19+
assert TypedNode.yaml_loc(inp["foo"]["x"], suffix="") == 'File "<unicode string>", line 3, col 8'
20+
assert TypedNode.yaml_loc(inp["foo"]["y"]) == 'File "<unicode string>", line 4, col 8: '
21+
assert (
22+
TypedNode.yaml_loc(inp["foo"]["y"], suffix=inp["foo"]["y"])
23+
== 'File "<unicode string>", line 4, col 8I yam that I yam'
24+
)
25+
assert TypedNode.yaml_loc(inp["foo"]["z"]) == 'File "<unicode string>", line 5, col 8: '
26+
27+
28+
def test_yaml_loc_warning() -> None:
29+
"""Test that a warning is emitted when using the `loc` method."""
30+
inp = yaml.load(hbreader.hbread(inp_yaml), DupCheckYamlLoader)
31+
with pytest.warns(DeprecationWarning) as warning_list:
32+
assert TypedNode.loc(inp["foo"]["x"]) == 'File "<unicode string>", line 3, col 8'
33+
assert len(warning_list) == 1
34+
assert str(warning_list[0].message) == "Call to deprecated method loc. (Use yaml_loc instead)"
35+
36+
37+
@pytest.mark.parametrize("loc", [None, "abc", ["a", "b"]])
38+
def test_yaml_loc_empty_str(loc) -> None:
39+
"""Test yaml_loc values that translate to an empty string."""
40+
assert TypedNode.yaml_loc(loc) == ""
Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import unittest
2-
31
from linkml_runtime.linkml_model import SchemaDefinition
42
from linkml_runtime.utils.yamlutils import from_yaml
53

@@ -12,22 +10,17 @@
1210
string:
1311
base: str
1412
uri: xsd:string
15-
13+
1614
slots:
1715
name:
1816
"""
1917

2018

21-
class IsolatedNameTestCase(unittest.TestCase):
22-
def test_it(self):
23-
"""Dangling name should not throw a type error"""
24-
error_thrown = False
25-
try:
26-
from_yaml(model_txt, SchemaDefinition)
27-
except TypeError as e:
28-
error_thrown = True
29-
self.assertFalse(error_thrown, msg="Type error should not be thrown")
30-
31-
32-
if __name__ == "__main__":
33-
unittest.main()
19+
def test_read_dangling_name() -> None:
20+
"""Dangling name should not throw a type error."""
21+
error_thrown = False
22+
try:
23+
from_yaml(model_txt, SchemaDefinition)
24+
except TypeError:
25+
error_thrown = True
26+
assert error_thrown is False

tests/test_issues/test_issue_718.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
import pytest
1+
from __future__ import annotations
2+
23
from dataclasses import dataclass
3-
from typing import Optional, ClassVar
4+
from typing import ClassVar
45

6+
import pytest
57
import yaml
68

7-
from linkml_runtime.utils.yamlutils import YAMLRoot, DupCheckYamlLoader
9+
from linkml_runtime.utils.yamlutils import DupCheckYamlLoader, YAMLRoot
810

911

1012
@pytest.mark.xfail(reason="Reporting line numbers should happen at load time not when instantiating dataclasses")
11-
def test_issue_38():
13+
def test_issue_38() -> None:
1214
# The goal is to provide line numbers on error messages. We've tweaked the parser so that it returns augmented
1315
# str's and int's with the line numbers on them. The problem we are trying to address now is that the dataclass
1416
# constructor doesn't support **argv out of the box. We can certainly tweak the generator to emit the __init__
@@ -18,8 +20,8 @@ def test_issue_38():
1820
class FesterBesterTester(YAMLRoot):
1921
cv: ClassVar[int] = 42
2022

21-
a: Optional[int] = 0
22-
b: Optional[str] = None
23+
a: int | None = 0
24+
b: str | None = None
2325

2426
with pytest.raises(TypeError, match="unexpected keyword argument 'c'"):
2527
FesterBesterTester(a=12, b="Sell", c="buy")

0 commit comments

Comments
 (0)