fishertools 0.2.1__py3-none-any.whl → 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fishertools/__init__.py +16 -5
- fishertools/errors/__init__.py +11 -3
- fishertools/errors/exception_types.py +282 -0
- fishertools/errors/explainer.py +87 -1
- fishertools/errors/models.py +73 -1
- fishertools/errors/patterns.py +40 -0
- fishertools/examples/cli_example.py +156 -0
- fishertools/examples/learn_example.py +65 -0
- fishertools/examples/logger_example.py +176 -0
- fishertools/examples/menu_example.py +101 -0
- fishertools/examples/storage_example.py +175 -0
- fishertools/input_utils.py +185 -0
- fishertools/learn/__init__.py +19 -2
- fishertools/learn/examples.py +88 -1
- fishertools/learn/knowledge_engine.py +321 -0
- fishertools/learn/repl/__init__.py +19 -0
- fishertools/learn/repl/cli.py +31 -0
- fishertools/learn/repl/code_sandbox.py +229 -0
- fishertools/learn/repl/command_handler.py +544 -0
- fishertools/learn/repl/command_parser.py +165 -0
- fishertools/learn/repl/engine.py +479 -0
- fishertools/learn/repl/models.py +121 -0
- fishertools/learn/repl/session_manager.py +284 -0
- fishertools/learn/repl/test_code_sandbox.py +261 -0
- fishertools/learn/repl/test_code_sandbox_pbt.py +148 -0
- fishertools/learn/repl/test_command_handler.py +224 -0
- fishertools/learn/repl/test_command_handler_pbt.py +189 -0
- fishertools/learn/repl/test_command_parser.py +160 -0
- fishertools/learn/repl/test_command_parser_pbt.py +100 -0
- fishertools/learn/repl/test_engine.py +190 -0
- fishertools/learn/repl/test_session_manager.py +310 -0
- fishertools/learn/repl/test_session_manager_pbt.py +182 -0
- fishertools/learn/test_knowledge_engine.py +241 -0
- fishertools/learn/test_knowledge_engine_pbt.py +180 -0
- fishertools/patterns/__init__.py +46 -0
- fishertools/patterns/cli.py +175 -0
- fishertools/patterns/logger.py +140 -0
- fishertools/patterns/menu.py +99 -0
- fishertools/patterns/storage.py +127 -0
- fishertools/readme_transformer.py +631 -0
- fishertools/safe/__init__.py +6 -1
- fishertools/safe/files.py +329 -1
- fishertools/transform_readme.py +105 -0
- fishertools-0.4.0.dist-info/METADATA +104 -0
- fishertools-0.4.0.dist-info/RECORD +131 -0
- {fishertools-0.2.1.dist-info → fishertools-0.4.0.dist-info}/WHEEL +1 -1
- tests/test_documentation_properties.py +329 -0
- tests/test_documentation_structure.py +349 -0
- tests/test_errors/test_exception_types.py +446 -0
- tests/test_errors/test_exception_types_pbt.py +333 -0
- tests/test_errors/test_patterns.py +52 -0
- tests/test_input_utils/__init__.py +1 -0
- tests/test_input_utils/test_input_utils.py +65 -0
- tests/test_learn/test_examples.py +179 -1
- tests/test_learn/test_explain_properties.py +307 -0
- tests/test_patterns_cli.py +611 -0
- tests/test_patterns_docstrings.py +473 -0
- tests/test_patterns_logger.py +465 -0
- tests/test_patterns_menu.py +440 -0
- tests/test_patterns_storage.py +447 -0
- tests/test_readme_enhancements_v0_3_1.py +2036 -0
- tests/test_readme_transformer/__init__.py +1 -0
- tests/test_readme_transformer/test_readme_infrastructure.py +1023 -0
- tests/test_readme_transformer/test_transform_readme_integration.py +431 -0
- tests/test_safe/test_files.py +726 -1
- fishertools-0.2.1.dist-info/METADATA +0 -256
- fishertools-0.2.1.dist-info/RECORD +0 -81
- {fishertools-0.2.1.dist-info → fishertools-0.4.0.dist-info}/licenses/LICENSE +0 -0
- {fishertools-0.2.1.dist-info → fishertools-0.4.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Property-based tests for pattern docstrings in fishertools.patterns.
|
|
3
|
+
|
|
4
|
+
Tests the correctness property that all pattern classes and functions have
|
|
5
|
+
comprehensive docstrings explaining their purpose and usage.
|
|
6
|
+
|
|
7
|
+
**Validates: Requirements 7.3, 12.1**
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import pytest
|
|
11
|
+
import inspect
|
|
12
|
+
from hypothesis import given, strategies as st
|
|
13
|
+
|
|
14
|
+
from fishertools.patterns.menu import simple_menu
|
|
15
|
+
from fishertools.patterns.storage import JSONStorage
|
|
16
|
+
from fishertools.patterns.logger import SimpleLogger
|
|
17
|
+
from fishertools.patterns.cli import SimpleCLI
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class TestAllPatternsHaveDocstrings:
|
|
21
|
+
"""
|
|
22
|
+
Property 10: All Patterns Have Docstrings
|
|
23
|
+
|
|
24
|
+
For all pattern classes and functions, they should have non-empty docstrings
|
|
25
|
+
explaining their purpose.
|
|
26
|
+
|
|
27
|
+
**Validates: Requirements 7.3, 12.1**
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def test_simple_menu_has_docstring(self):
|
|
31
|
+
"""Test that simple_menu() has a docstring."""
|
|
32
|
+
assert simple_menu.__doc__ is not None
|
|
33
|
+
assert len(simple_menu.__doc__) > 0
|
|
34
|
+
assert simple_menu.__doc__.strip() != ""
|
|
35
|
+
|
|
36
|
+
def test_simple_menu_docstring_is_meaningful(self):
|
|
37
|
+
"""Test that simple_menu() docstring is meaningful."""
|
|
38
|
+
docstring = simple_menu.__doc__
|
|
39
|
+
|
|
40
|
+
# Should contain key information
|
|
41
|
+
assert "menu" in docstring.lower()
|
|
42
|
+
assert "options" in docstring.lower()
|
|
43
|
+
|
|
44
|
+
# Should be substantial
|
|
45
|
+
assert len(docstring) >= 100
|
|
46
|
+
|
|
47
|
+
def test_simple_menu_docstring_has_parameters(self):
|
|
48
|
+
"""Test that simple_menu() docstring documents parameters."""
|
|
49
|
+
docstring = simple_menu.__doc__
|
|
50
|
+
|
|
51
|
+
# Should mention parameters
|
|
52
|
+
assert "Parameters" in docstring or "parameters" in docstring.lower()
|
|
53
|
+
assert "options" in docstring.lower()
|
|
54
|
+
|
|
55
|
+
def test_simple_menu_docstring_has_returns(self):
|
|
56
|
+
"""Test that simple_menu() docstring documents return value."""
|
|
57
|
+
docstring = simple_menu.__doc__
|
|
58
|
+
|
|
59
|
+
# Should mention return value
|
|
60
|
+
assert "Returns" in docstring or "returns" in docstring.lower()
|
|
61
|
+
|
|
62
|
+
def test_simple_menu_docstring_has_example(self):
|
|
63
|
+
"""Test that simple_menu() docstring includes an example."""
|
|
64
|
+
docstring = simple_menu.__doc__
|
|
65
|
+
|
|
66
|
+
# Should include example
|
|
67
|
+
assert "Example" in docstring or "example" in docstring.lower()
|
|
68
|
+
|
|
69
|
+
def test_jsonstorage_class_has_docstring(self):
|
|
70
|
+
"""Test that JSONStorage class has a docstring."""
|
|
71
|
+
assert JSONStorage.__doc__ is not None
|
|
72
|
+
assert len(JSONStorage.__doc__) > 0
|
|
73
|
+
assert JSONStorage.__doc__.strip() != ""
|
|
74
|
+
|
|
75
|
+
def test_jsonstorage_class_docstring_is_meaningful(self):
|
|
76
|
+
"""Test that JSONStorage class docstring is meaningful."""
|
|
77
|
+
docstring = JSONStorage.__doc__
|
|
78
|
+
|
|
79
|
+
# Should contain key information
|
|
80
|
+
assert "JSON" in docstring or "json" in docstring.lower()
|
|
81
|
+
assert "storage" in docstring.lower() or "save" in docstring.lower()
|
|
82
|
+
|
|
83
|
+
# Should be substantial
|
|
84
|
+
assert len(docstring) >= 100
|
|
85
|
+
|
|
86
|
+
def test_jsonstorage_init_has_docstring(self):
|
|
87
|
+
"""Test that JSONStorage.__init__() has a docstring."""
|
|
88
|
+
assert JSONStorage.__init__.__doc__ is not None
|
|
89
|
+
assert len(JSONStorage.__init__.__doc__) > 0
|
|
90
|
+
|
|
91
|
+
def test_jsonstorage_save_has_docstring(self):
|
|
92
|
+
"""Test that JSONStorage.save() has a docstring."""
|
|
93
|
+
assert JSONStorage.save.__doc__ is not None
|
|
94
|
+
assert len(JSONStorage.save.__doc__) > 0
|
|
95
|
+
assert "save" in JSONStorage.save.__doc__.lower()
|
|
96
|
+
|
|
97
|
+
def test_jsonstorage_load_has_docstring(self):
|
|
98
|
+
"""Test that JSONStorage.load() has a docstring."""
|
|
99
|
+
assert JSONStorage.load.__doc__ is not None
|
|
100
|
+
assert len(JSONStorage.load.__doc__) > 0
|
|
101
|
+
assert "load" in JSONStorage.load.__doc__.lower()
|
|
102
|
+
|
|
103
|
+
def test_jsonstorage_exists_has_docstring(self):
|
|
104
|
+
"""Test that JSONStorage.exists() has a docstring."""
|
|
105
|
+
assert JSONStorage.exists.__doc__ is not None
|
|
106
|
+
assert len(JSONStorage.exists.__doc__) > 0
|
|
107
|
+
assert "exist" in JSONStorage.exists.__doc__.lower()
|
|
108
|
+
|
|
109
|
+
def test_jsonstorage_class_docstring_has_parameters(self):
|
|
110
|
+
"""Test that JSONStorage class docstring documents parameters."""
|
|
111
|
+
docstring = JSONStorage.__doc__
|
|
112
|
+
|
|
113
|
+
# Should mention parameters
|
|
114
|
+
assert "Parameters" in docstring or "parameters" in docstring.lower()
|
|
115
|
+
assert "file_path" in docstring.lower()
|
|
116
|
+
|
|
117
|
+
def test_jsonstorage_class_docstring_has_methods(self):
|
|
118
|
+
"""Test that JSONStorage class docstring documents methods."""
|
|
119
|
+
docstring = JSONStorage.__doc__
|
|
120
|
+
|
|
121
|
+
# Should mention methods
|
|
122
|
+
assert "Methods" in docstring or "methods" in docstring.lower()
|
|
123
|
+
assert "save" in docstring.lower()
|
|
124
|
+
assert "load" in docstring.lower()
|
|
125
|
+
|
|
126
|
+
def test_jsonstorage_class_docstring_has_example(self):
|
|
127
|
+
"""Test that JSONStorage class docstring includes an example."""
|
|
128
|
+
docstring = JSONStorage.__doc__
|
|
129
|
+
|
|
130
|
+
# Should include example
|
|
131
|
+
assert "Example" in docstring or "example" in docstring.lower()
|
|
132
|
+
|
|
133
|
+
def test_simplelogger_class_has_docstring(self):
|
|
134
|
+
"""Test that SimpleLogger class has a docstring."""
|
|
135
|
+
assert SimpleLogger.__doc__ is not None
|
|
136
|
+
assert len(SimpleLogger.__doc__) > 0
|
|
137
|
+
assert SimpleLogger.__doc__.strip() != ""
|
|
138
|
+
|
|
139
|
+
def test_simplelogger_class_docstring_is_meaningful(self):
|
|
140
|
+
"""Test that SimpleLogger class docstring is meaningful."""
|
|
141
|
+
docstring = SimpleLogger.__doc__
|
|
142
|
+
|
|
143
|
+
# Should contain key information
|
|
144
|
+
assert "log" in docstring.lower()
|
|
145
|
+
assert "file" in docstring.lower() or "message" in docstring.lower()
|
|
146
|
+
|
|
147
|
+
# Should be substantial
|
|
148
|
+
assert len(docstring) >= 100
|
|
149
|
+
|
|
150
|
+
def test_simplelogger_init_has_docstring(self):
|
|
151
|
+
"""Test that SimpleLogger.__init__() has a docstring."""
|
|
152
|
+
assert SimpleLogger.__init__.__doc__ is not None
|
|
153
|
+
assert len(SimpleLogger.__init__.__doc__) > 0
|
|
154
|
+
|
|
155
|
+
def test_simplelogger_info_has_docstring(self):
|
|
156
|
+
"""Test that SimpleLogger.info() has a docstring."""
|
|
157
|
+
assert SimpleLogger.info.__doc__ is not None
|
|
158
|
+
assert len(SimpleLogger.info.__doc__) > 0
|
|
159
|
+
assert "info" in SimpleLogger.info.__doc__.lower()
|
|
160
|
+
|
|
161
|
+
def test_simplelogger_warning_has_docstring(self):
|
|
162
|
+
"""Test that SimpleLogger.warning() has a docstring."""
|
|
163
|
+
assert SimpleLogger.warning.__doc__ is not None
|
|
164
|
+
assert len(SimpleLogger.warning.__doc__) > 0
|
|
165
|
+
assert "warning" in SimpleLogger.warning.__doc__.lower()
|
|
166
|
+
|
|
167
|
+
def test_simplelogger_error_has_docstring(self):
|
|
168
|
+
"""Test that SimpleLogger.error() has a docstring."""
|
|
169
|
+
assert SimpleLogger.error.__doc__ is not None
|
|
170
|
+
assert len(SimpleLogger.error.__doc__) > 0
|
|
171
|
+
assert "error" in SimpleLogger.error.__doc__.lower()
|
|
172
|
+
|
|
173
|
+
def test_simplelogger_class_docstring_has_parameters(self):
|
|
174
|
+
"""Test that SimpleLogger class docstring documents parameters."""
|
|
175
|
+
docstring = SimpleLogger.__doc__
|
|
176
|
+
|
|
177
|
+
# Should mention parameters
|
|
178
|
+
assert "Parameters" in docstring or "parameters" in docstring.lower()
|
|
179
|
+
assert "file_path" in docstring.lower()
|
|
180
|
+
|
|
181
|
+
def test_simplelogger_class_docstring_has_methods(self):
|
|
182
|
+
"""Test that SimpleLogger class docstring documents methods."""
|
|
183
|
+
docstring = SimpleLogger.__doc__
|
|
184
|
+
|
|
185
|
+
# Should mention methods
|
|
186
|
+
assert "Methods" in docstring or "methods" in docstring.lower()
|
|
187
|
+
assert "info" in docstring.lower()
|
|
188
|
+
assert "warning" in docstring.lower()
|
|
189
|
+
assert "error" in docstring.lower()
|
|
190
|
+
|
|
191
|
+
def test_simplelogger_class_docstring_has_example(self):
|
|
192
|
+
"""Test that SimpleLogger class docstring includes an example."""
|
|
193
|
+
docstring = SimpleLogger.__doc__
|
|
194
|
+
|
|
195
|
+
# Should include example
|
|
196
|
+
assert "Example" in docstring or "example" in docstring.lower()
|
|
197
|
+
|
|
198
|
+
def test_simplecli_class_has_docstring(self):
|
|
199
|
+
"""Test that SimpleCLI class has a docstring."""
|
|
200
|
+
assert SimpleCLI.__doc__ is not None
|
|
201
|
+
assert len(SimpleCLI.__doc__) > 0
|
|
202
|
+
assert SimpleCLI.__doc__.strip() != ""
|
|
203
|
+
|
|
204
|
+
def test_simplecli_class_docstring_is_meaningful(self):
|
|
205
|
+
"""Test that SimpleCLI class docstring is meaningful."""
|
|
206
|
+
docstring = SimpleCLI.__doc__
|
|
207
|
+
|
|
208
|
+
# Should contain key information
|
|
209
|
+
assert "CLI" in docstring or "command" in docstring.lower()
|
|
210
|
+
assert "interface" in docstring.lower() or "command" in docstring.lower()
|
|
211
|
+
|
|
212
|
+
# Should be substantial
|
|
213
|
+
assert len(docstring) >= 100
|
|
214
|
+
|
|
215
|
+
def test_simplecli_init_has_docstring(self):
|
|
216
|
+
"""Test that SimpleCLI.__init__() has a docstring."""
|
|
217
|
+
assert SimpleCLI.__init__.__doc__ is not None
|
|
218
|
+
assert len(SimpleCLI.__init__.__doc__) > 0
|
|
219
|
+
|
|
220
|
+
def test_simplecli_command_has_docstring(self):
|
|
221
|
+
"""Test that SimpleCLI.command() has a docstring."""
|
|
222
|
+
assert SimpleCLI.command.__doc__ is not None
|
|
223
|
+
assert len(SimpleCLI.command.__doc__) > 0
|
|
224
|
+
assert "command" in SimpleCLI.command.__doc__.lower()
|
|
225
|
+
|
|
226
|
+
def test_simplecli_run_has_docstring(self):
|
|
227
|
+
"""Test that SimpleCLI.run() has a docstring."""
|
|
228
|
+
assert SimpleCLI.run.__doc__ is not None
|
|
229
|
+
assert len(SimpleCLI.run.__doc__) > 0
|
|
230
|
+
assert "run" in SimpleCLI.run.__doc__.lower() or "execute" in SimpleCLI.run.__doc__.lower()
|
|
231
|
+
|
|
232
|
+
def test_simplecli_class_docstring_has_parameters(self):
|
|
233
|
+
"""Test that SimpleCLI class docstring documents parameters."""
|
|
234
|
+
docstring = SimpleCLI.__doc__
|
|
235
|
+
|
|
236
|
+
# Should mention parameters
|
|
237
|
+
assert "Parameters" in docstring or "parameters" in docstring.lower()
|
|
238
|
+
assert "name" in docstring.lower()
|
|
239
|
+
assert "description" in docstring.lower()
|
|
240
|
+
|
|
241
|
+
def test_simplecli_class_docstring_has_methods(self):
|
|
242
|
+
"""Test that SimpleCLI class docstring documents methods."""
|
|
243
|
+
docstring = SimpleCLI.__doc__
|
|
244
|
+
|
|
245
|
+
# Should mention methods
|
|
246
|
+
assert "Methods" in docstring or "methods" in docstring.lower()
|
|
247
|
+
assert "command" in docstring.lower()
|
|
248
|
+
assert "run" in docstring.lower()
|
|
249
|
+
|
|
250
|
+
def test_simplecli_class_docstring_has_example(self):
|
|
251
|
+
"""Test that SimpleCLI class docstring includes an example."""
|
|
252
|
+
docstring = SimpleCLI.__doc__
|
|
253
|
+
|
|
254
|
+
# Should include example
|
|
255
|
+
assert "Example" in docstring or "example" in docstring.lower()
|
|
256
|
+
|
|
257
|
+
def test_all_pattern_classes_have_docstrings(self):
|
|
258
|
+
"""Test that all pattern classes have docstrings."""
|
|
259
|
+
pattern_classes = [JSONStorage, SimpleLogger, SimpleCLI]
|
|
260
|
+
|
|
261
|
+
for cls in pattern_classes:
|
|
262
|
+
assert cls.__doc__ is not None, f"{cls.__name__} missing docstring"
|
|
263
|
+
assert len(cls.__doc__) > 0, f"{cls.__name__} has empty docstring"
|
|
264
|
+
assert cls.__doc__.strip() != "", f"{cls.__name__} has whitespace-only docstring"
|
|
265
|
+
|
|
266
|
+
def test_all_pattern_functions_have_docstrings(self):
|
|
267
|
+
"""Test that all pattern functions have docstrings."""
|
|
268
|
+
pattern_functions = [simple_menu]
|
|
269
|
+
|
|
270
|
+
for func in pattern_functions:
|
|
271
|
+
assert func.__doc__ is not None, f"{func.__name__} missing docstring"
|
|
272
|
+
assert len(func.__doc__) > 0, f"{func.__name__} has empty docstring"
|
|
273
|
+
assert func.__doc__.strip() != "", f"{func.__name__} has whitespace-only docstring"
|
|
274
|
+
|
|
275
|
+
def test_all_pattern_public_methods_have_docstrings(self):
|
|
276
|
+
"""Test that all public methods in pattern classes have docstrings."""
|
|
277
|
+
pattern_classes = [JSONStorage, SimpleLogger, SimpleCLI]
|
|
278
|
+
|
|
279
|
+
for cls in pattern_classes:
|
|
280
|
+
# Get all public methods
|
|
281
|
+
for name, method in inspect.getmembers(cls, predicate=inspect.isfunction):
|
|
282
|
+
if not name.startswith('_'):
|
|
283
|
+
assert method.__doc__ is not None, f"{cls.__name__}.{name} missing docstring"
|
|
284
|
+
assert len(method.__doc__) > 0, f"{cls.__name__}.{name} has empty docstring"
|
|
285
|
+
|
|
286
|
+
def test_docstrings_contain_meaningful_content(self):
|
|
287
|
+
"""Test that docstrings contain meaningful content."""
|
|
288
|
+
pattern_items = [
|
|
289
|
+
(simple_menu, "simple_menu"),
|
|
290
|
+
(JSONStorage, "JSONStorage"),
|
|
291
|
+
(SimpleLogger, "SimpleLogger"),
|
|
292
|
+
(SimpleCLI, "SimpleCLI")
|
|
293
|
+
]
|
|
294
|
+
|
|
295
|
+
for item, name in pattern_items:
|
|
296
|
+
docstring = item.__doc__
|
|
297
|
+
|
|
298
|
+
# Should have substantial content
|
|
299
|
+
assert len(docstring) >= 50, f"{name} docstring too short"
|
|
300
|
+
|
|
301
|
+
# Should contain alphabetic characters
|
|
302
|
+
assert any(c.isalpha() for c in docstring), f"{name} docstring has no text"
|
|
303
|
+
|
|
304
|
+
def test_docstrings_follow_format(self):
|
|
305
|
+
"""Test that docstrings follow a consistent format."""
|
|
306
|
+
pattern_classes = [JSONStorage, SimpleLogger, SimpleCLI]
|
|
307
|
+
|
|
308
|
+
for cls in pattern_classes:
|
|
309
|
+
docstring = cls.__doc__
|
|
310
|
+
|
|
311
|
+
# Should have a summary line
|
|
312
|
+
lines = docstring.strip().split('\n')
|
|
313
|
+
assert len(lines) > 1, f"{cls.__name__} docstring too short"
|
|
314
|
+
|
|
315
|
+
# First line should be a summary
|
|
316
|
+
summary = lines[0].strip()
|
|
317
|
+
assert len(summary) > 10, f"{cls.__name__} summary too short"
|
|
318
|
+
|
|
319
|
+
def test_method_docstrings_document_parameters(self):
|
|
320
|
+
"""Test that method docstrings document their parameters."""
|
|
321
|
+
# Check JSONStorage.save
|
|
322
|
+
save_doc = JSONStorage.save.__doc__
|
|
323
|
+
assert "Parameters" in save_doc or "parameters" in save_doc.lower()
|
|
324
|
+
assert "data" in save_doc.lower()
|
|
325
|
+
|
|
326
|
+
# Check SimpleLogger.info
|
|
327
|
+
info_doc = SimpleLogger.info.__doc__
|
|
328
|
+
assert "Parameters" in info_doc or "parameters" in info_doc.lower()
|
|
329
|
+
assert "message" in info_doc.lower()
|
|
330
|
+
|
|
331
|
+
# Check SimpleCLI.command
|
|
332
|
+
command_doc = SimpleCLI.command.__doc__
|
|
333
|
+
assert "Parameters" in command_doc or "parameters" in command_doc.lower()
|
|
334
|
+
|
|
335
|
+
def test_method_docstrings_document_returns(self):
|
|
336
|
+
"""Test that method docstrings document return values."""
|
|
337
|
+
# Check JSONStorage.load
|
|
338
|
+
load_doc = JSONStorage.load.__doc__
|
|
339
|
+
assert "Returns" in load_doc or "returns" in load_doc.lower()
|
|
340
|
+
|
|
341
|
+
# Check JSONStorage.exists
|
|
342
|
+
exists_doc = JSONStorage.exists.__doc__
|
|
343
|
+
assert "Returns" in exists_doc or "returns" in exists_doc.lower()
|
|
344
|
+
|
|
345
|
+
def test_docstrings_are_not_just_pass_statements(self):
|
|
346
|
+
"""Test that docstrings are actual documentation, not just pass."""
|
|
347
|
+
pattern_items = [
|
|
348
|
+
simple_menu,
|
|
349
|
+
JSONStorage,
|
|
350
|
+
SimpleLogger,
|
|
351
|
+
SimpleCLI
|
|
352
|
+
]
|
|
353
|
+
|
|
354
|
+
for item in pattern_items:
|
|
355
|
+
docstring = item.__doc__
|
|
356
|
+
|
|
357
|
+
# Should not be just "pass" or similar
|
|
358
|
+
assert docstring.lower().strip() != "pass"
|
|
359
|
+
assert docstring.lower().strip() != "todo"
|
|
360
|
+
assert docstring.lower().strip() != "..."
|
|
361
|
+
|
|
362
|
+
def test_docstrings_have_examples(self):
|
|
363
|
+
"""Test that main docstrings include usage examples."""
|
|
364
|
+
pattern_items = [
|
|
365
|
+
(simple_menu, "simple_menu"),
|
|
366
|
+
(JSONStorage, "JSONStorage"),
|
|
367
|
+
(SimpleLogger, "SimpleLogger"),
|
|
368
|
+
(SimpleCLI, "SimpleCLI")
|
|
369
|
+
]
|
|
370
|
+
|
|
371
|
+
for item, name in pattern_items:
|
|
372
|
+
docstring = item.__doc__
|
|
373
|
+
|
|
374
|
+
# Should include example
|
|
375
|
+
assert "Example" in docstring or "example" in docstring.lower(), \
|
|
376
|
+
f"{name} docstring missing example"
|
|
377
|
+
|
|
378
|
+
def test_docstrings_have_notes_or_warnings(self):
|
|
379
|
+
"""Test that docstrings include helpful notes."""
|
|
380
|
+
pattern_items = [
|
|
381
|
+
(simple_menu, "simple_menu"),
|
|
382
|
+
(JSONStorage, "JSONStorage"),
|
|
383
|
+
(SimpleLogger, "SimpleLogger"),
|
|
384
|
+
(SimpleCLI, "SimpleCLI")
|
|
385
|
+
]
|
|
386
|
+
|
|
387
|
+
for item, name in pattern_items:
|
|
388
|
+
docstring = item.__doc__
|
|
389
|
+
|
|
390
|
+
# Should include note or important information
|
|
391
|
+
has_note = "Note" in docstring or "note" in docstring.lower()
|
|
392
|
+
has_important = "Important" in docstring or "important" in docstring.lower()
|
|
393
|
+
|
|
394
|
+
assert has_note or has_important, \
|
|
395
|
+
f"{name} docstring missing notes or important information"
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
class TestDocstringQuality:
|
|
399
|
+
"""Test the quality and completeness of docstrings."""
|
|
400
|
+
|
|
401
|
+
def test_simple_menu_docstring_mentions_exit(self):
|
|
402
|
+
"""Test that simple_menu docstring mentions exit behavior."""
|
|
403
|
+
docstring = simple_menu.__doc__
|
|
404
|
+
|
|
405
|
+
assert "quit" in docstring.lower() or "exit" in docstring.lower()
|
|
406
|
+
|
|
407
|
+
def test_jsonstorage_docstring_mentions_directory_creation(self):
|
|
408
|
+
"""Test that JSONStorage docstring mentions directory creation."""
|
|
409
|
+
docstring = JSONStorage.__doc__
|
|
410
|
+
|
|
411
|
+
assert "director" in docstring.lower() or "create" in docstring.lower()
|
|
412
|
+
|
|
413
|
+
def test_simplelogger_docstring_mentions_timestamp(self):
|
|
414
|
+
"""Test that SimpleLogger docstring mentions timestamp format."""
|
|
415
|
+
docstring = SimpleLogger.__doc__
|
|
416
|
+
|
|
417
|
+
assert "timestamp" in docstring.lower() or "time" in docstring.lower()
|
|
418
|
+
|
|
419
|
+
def test_simplecli_docstring_mentions_decorator(self):
|
|
420
|
+
"""Test that SimpleCLI docstring mentions decorator usage."""
|
|
421
|
+
docstring = SimpleCLI.__doc__
|
|
422
|
+
|
|
423
|
+
assert "decorator" in docstring.lower() or "@" in docstring
|
|
424
|
+
|
|
425
|
+
def test_all_docstrings_are_accessible(self):
|
|
426
|
+
"""Test that all docstrings are accessible via help()."""
|
|
427
|
+
pattern_items = [simple_menu, JSONStorage, SimpleLogger, SimpleCLI]
|
|
428
|
+
|
|
429
|
+
for item in pattern_items:
|
|
430
|
+
# Should be able to get help
|
|
431
|
+
help_text = inspect.getdoc(item)
|
|
432
|
+
assert help_text is not None
|
|
433
|
+
assert len(help_text) > 0
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
class TestDocstringConsistency:
|
|
437
|
+
"""Test consistency across docstrings."""
|
|
438
|
+
|
|
439
|
+
def test_all_class_docstrings_have_similar_structure(self):
|
|
440
|
+
"""Test that all class docstrings follow a similar structure."""
|
|
441
|
+
pattern_classes = [JSONStorage, SimpleLogger, SimpleCLI]
|
|
442
|
+
|
|
443
|
+
for cls in pattern_classes:
|
|
444
|
+
docstring = cls.__doc__
|
|
445
|
+
|
|
446
|
+
# Should have Parameters section
|
|
447
|
+
assert "Parameters" in docstring or "parameters" in docstring.lower()
|
|
448
|
+
|
|
449
|
+
# Should have Methods section (for classes)
|
|
450
|
+
assert "Methods" in docstring or "methods" in docstring.lower()
|
|
451
|
+
|
|
452
|
+
# Should have Example section
|
|
453
|
+
assert "Example" in docstring or "example" in docstring.lower()
|
|
454
|
+
|
|
455
|
+
def test_all_method_docstrings_have_parameters_section(self):
|
|
456
|
+
"""Test that all methods with parameters document them."""
|
|
457
|
+
# JSONStorage.save has parameters
|
|
458
|
+
save_doc = JSONStorage.save.__doc__
|
|
459
|
+
assert "Parameters" in save_doc or "parameters" in save_doc.lower()
|
|
460
|
+
|
|
461
|
+
# SimpleLogger.info has parameters
|
|
462
|
+
info_doc = SimpleLogger.info.__doc__
|
|
463
|
+
assert "Parameters" in info_doc or "parameters" in info_doc.lower()
|
|
464
|
+
|
|
465
|
+
def test_all_method_docstrings_have_returns_section(self):
|
|
466
|
+
"""Test that all methods document their return values."""
|
|
467
|
+
# JSONStorage.load returns data
|
|
468
|
+
load_doc = JSONStorage.load.__doc__
|
|
469
|
+
assert "Returns" in load_doc or "returns" in load_doc.lower()
|
|
470
|
+
|
|
471
|
+
# JSONStorage.exists returns bool
|
|
472
|
+
exists_doc = JSONStorage.exists.__doc__
|
|
473
|
+
assert "Returns" in exists_doc or "returns" in exists_doc.lower()
|