Coverage for tests/test_objects.py: 100.00%
75 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-09 17:28 +0100
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-09 17:28 +0100
1"""Tests for [the `objects` module][pytkdocs.objects]."""
3import os
5from pytkdocs.loader import Loader
6from pytkdocs.objects import Attribute, Class, Function, Method, Module, Object
7from tests import FIXTURES_DIR
10def test_creating_module() -> None:
11 """Create a Module."""
12 assert Module(name="my_object", path="my.dotted.path", file_path="/my/absolute/path.py")
15def test_creating_class() -> None:
16 """Create a Class."""
17 assert Class(name="my_object", path="my.dotted.path", file_path="/my/absolute/path.py")
20def test_creating_method() -> None:
21 """Create a Method."""
22 assert Method(name="my_object", path="my.dotted.path", file_path="/my/absolute/path.py")
25def test_creating_function() -> None:
26 """Create a Function."""
27 assert Function(name="my_object", path="my.dotted.path", file_path="/my/absolute/path.py")
30def test_creating_attribute() -> None:
31 """Create an Attribute."""
32 assert Attribute(name="my_object", path="my.dotted.path", file_path="/my/absolute/path.py")
35def test_add_child() -> None:
36 """Add a child."""
37 parent = Module(name="my_module", path="my.dotted.path", file_path="/my/absolute/path.py")
38 child = Attribute(name="my_attribute", path="my.dotted.path.my_attribute", file_path="/my/absolute/path.py")
39 parent.add_child(child)
40 assert parent.children[0] is child
41 assert parent.attributes[0] is child
44def test_do_not_add_child_if_parent_is_not_self() -> None:
45 """Don't add a child the parent is not the right one."""
46 parent = Module(name="my_module", path="my.dotted.path", file_path="/my/absolute/path.py")
47 child = Attribute(name="my_attribute", path="my.other.path.my_attribute", file_path="/my/absolute/path.py")
48 parent.add_child(child)
49 assert not parent.children
50 assert not parent.attributes
53def test_get_root() -> None:
54 """Get the root object."""
55 root = Module(name="my_module", path="my.dotted.path", file_path="")
56 node1 = Class(name="my_class1", path="my.dotted.path.my_class1", file_path="")
57 node2 = Class(name="my_class2", path="my.dotted.path.my_class2", file_path="")
58 leaf = Method(name="my_method", path="my.dotted.path.my_class1.my_method", file_path="")
60 root.add_children([node1, node2])
61 node1.add_child(leaf)
63 assert root.root is root
64 assert node1.root is root
65 assert node2.root is root
66 assert leaf.root is root
69def test_relative_file_path_for_root() -> None:
70 """Get the relative file of a shallow object."""
71 obj = Object(
72 name="nested_class",
73 path="tests.fixtures.nested_class",
74 file_path=str(FIXTURES_DIR / "nested_class.py"),
75 )
76 assert obj.relative_file_path == os.path.join("tests", "fixtures", "nested_class.py")
79def test_relative_file_path_for_leaf() -> None:
80 """Get the relative file path of a deep object."""
81 obj = Loader().get_object_documentation("tests.fixtures.pkg1")
82 leaf = obj.children[0].children[0].children[0].children[0]
83 assert leaf.relative_file_path == os.path.join(
84 "tests",
85 "fixtures",
86 "pkg1",
87 "pkg2",
88 "pkg3",
89 "pkg4",
90 "pkg5",
91 "__init__.py",
92 )
95def test_no_relative_file_path_for_non_existent_package() -> None:
96 """Cannot find relative file path."""
97 obj = Object(name="o", path="a.b.o", file_path="/some/non_existent/path/a/b/o.py")
98 assert not obj.relative_file_path
101def test_no_relative_file_path_for_wrong_path() -> None:
102 """Cannot find relative file path with wrong dotted path."""
103 obj = Object(name="o", path="wrong.dotted.path", file_path=str(FIXTURES_DIR / "nested_class.py"))
104 assert not obj.relative_file_path
107def test_no_relative_file_path_for_wrong_file_path() -> None:
108 """Cannot find relative file path with wrong file path."""
109 obj = Object(name="o", path="tests.fixtures.nested_class", file_path="/wrong/module/path.py")
110 assert not obj.relative_file_path
113def test_add_children() -> None:
114 """Add multiple children at once."""
115 root = Object(name="o", path="o", file_path="o.py")
117 class_ = Class(name="c", path="o.c", file_path="o.py")
118 attribute = Attribute(name="a", path="o.c.a", file_path="o.py")
119 class_.add_child(attribute)
121 root.add_children(
122 [
123 # class has wrong path
124 Class(name="w", path="wrong.path.w", file_path="/wrong/path/w.py"),
125 # class OK
126 class_,
127 # not a direct child,
128 attribute,
129 # function OK
130 Function(name="f", path="o.f", file_path="o.py"),
131 # not a direct child, not even a child of known child
132 Method(name="missing_node", path="o.mn.missing_node", file_path="o.py"),
133 ],
134 )
136 assert len(root.children) == 2
137 assert root.classes
138 assert root.classes[0] is class_
139 assert root.functions
140 assert root.functions[0].name == "f"
143def test_has_contents() -> None:
144 """Check if an object has contents."""
145 obj = Loader().get_object_documentation("tests.fixtures.pkg1")
146 assert obj.has_contents()
148 obj = Loader().get_object_documentation("tests.fixtures.__init__")
149 assert not obj.children
150 assert obj.has_contents() # we specified that the root always 'has contents'
152 obj = Loader().get_object_documentation("tests.fixtures.no_contents")
153 assert obj.children
154 assert obj.has_contents
155 assert not obj.children[0].has_contents()
158def test_has_no_contents() -> None:
159 """Check that an object has no contents."""
160 # TODO