Skip to content

Commit 4659d59

Browse files
committed
Improve tests of base_descriptor
This adds checks for a couple of error conditions, and ensures all code paths are checked. It also tests that we don't end up with extra docstrings we're not expecting.
1 parent 70ab0ee commit 4659d59

File tree

1 file changed

+92
-1
lines changed

1 file changed

+92
-1
lines changed

tests/test_base_descriptor.py

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,80 @@ class Example:
3939
a body giving a longer description of what's going on.
4040
"""
4141

42+
my_property_with_only_description = MockProperty()
43+
"""
44+
This is a poorly formatted docstring that does not have
45+
a one-line title. It should result in the property name
46+
being used as a title, and this text as description.
47+
"""
48+
49+
# This line looks like an attribute assignment with a docstring,
50+
# but it's not - because we are not assigning to a simple name.
51+
# This tests that such assignments won't cause errors.
52+
my_property_with_nice_docs.attribute = "dummy value"
53+
"""A spurious docstring."""
54+
55+
# As above, this is testing that we safely ignore assignments
56+
# that are not to simple names. The code below should not
57+
# cause an error, but will cause a ``continue`` statement
58+
# to skip actions, testing another code path when the
59+
# class is analysed.
60+
dict_attribute = {}
61+
dict_attribute["foo"] = "bar"
62+
"""Here is a spurious docstring that should be ignored."""
63+
64+
base_descriptor = BaseDescriptor()
65+
"""This descriptor should raise NotImplementedError."""
66+
4267

4368
def test_docstrings_are_retrieved():
44-
"""Check that the docstring can be picked up from the class definition."""
69+
"""Check that the docstring can be picked up from the class definition.
70+
71+
This test checks that:
72+
* We get docstrings for exactly the attributes we expect.
73+
* The one-line docstrings are picked up correctly.
74+
* The docstring-inspection code isn't confused by spurious docstrings
75+
next to assignments that are not to simple names. (see comments on
76+
the class definition of `Example`).
77+
78+
Detection and interpretation of multiline docstrings is tested in
79+
`test_basedescriptor_with_good_docstring`.
80+
"""
4581
docs = get_class_attribute_docstrings(Example)
4682
assert docs["my_constant"] == "A number that is all mine."
4783
assert docs["my_property"] == "Docs for my_property."
84+
expected_names = [
85+
"my_constant",
86+
"my_property",
87+
"my_property_with_nice_docs",
88+
"my_property_with_only_description",
89+
"base_descriptor",
90+
]
91+
assert set(docs.keys()) == set(expected_names)
92+
93+
94+
def test_non_classes_raise_errors():
95+
"""Check we validate the input object.
96+
97+
If `get_class_attribute_docstrings` is called on something other than
98+
a class, we should raise an error.
99+
"""
100+
101+
def dummy():
102+
pass
103+
104+
with pytest.raises(TypeError):
105+
get_class_attribute_docstrings(dummy)
106+
107+
108+
def test_uncheckable_class():
109+
"""Check we don't crash if we can't check a class.
110+
111+
If `inspect.getsource` fails, we should return an empty dict.
112+
"""
113+
MyClass = type("MyClass", (), {"intattr": 10})
114+
doc = get_class_attribute_docstrings(MyClass)
115+
assert doc == {}
48116

49117

50118
def test_docstrings_are_cached():
@@ -66,6 +134,26 @@ def test_basedescriptor_with_good_docstring():
66134
assert prop.description.startswith("The docstring")
67135

68136

137+
def test_basedescriptor_with_oneline_docstring():
138+
"""Check we get the right documentation properties for a one-liner."""
139+
prop = Example.my_property
140+
assert prop.name == "my_property"
141+
assert prop.title == "Docs for my_property."
142+
assert prop.description.startswith("Docs for my_property.")
143+
144+
145+
def test_basedescriptor_with_bad_multiline_docstring():
146+
"""Check a docstring with no title produces the expected result.
147+
148+
A multiline docstring with no title (i.e. no blank second line)
149+
should result in the whole docstring being used as the description.
150+
"""
151+
prop = Example.my_property_with_only_description
152+
assert prop.name == "my_property_with_only_description"
153+
assert prop.title == "This is a poorly formatted docstring that does not have"
154+
assert prop.description.startswith("This is a poorly formatted")
155+
156+
69157
def test_basedescriptor_orphaned():
70158
"""Check the right error is raised if we ask for the name outside a class."""
71159
prop = MockProperty()
@@ -92,3 +180,6 @@ def test_basedescriptor_get():
92180
e = Example()
93181
assert e.my_property == "An example value."
94182
assert isinstance(Example.my_property, MockProperty)
183+
with pytest.raises(NotImplementedError):
184+
# BaseDescriptor requires `instance_get` to be overridden.
185+
e.base_descriptor

0 commit comments

Comments
 (0)