/ dev / clint / tests / rules / test_redundant_test_docstring.py
test_redundant_test_docstring.py
  1  from pathlib import Path
  2  
  3  from clint.config import Config
  4  from clint.index import SymbolIndex
  5  from clint.linter import lint_file
  6  from clint.rules.redundant_test_docstring import RedundantTestDocstring
  7  
  8  
  9  def test_redundant_docstrings_are_flagged(index: SymbolIndex) -> None:
 10      code = '''
 11  def test_feature_a():
 12      """
 13      This test verifies that feature A works correctly.
 14      It has multiple lines of documentation.
 15      """
 16      assert True
 17  
 18  def test_feature_behavior():
 19      """Test feature."""
 20      assert True
 21  
 22  def test_c():
 23      """Test the complex interaction between modules."""
 24      assert True
 25  
 26  def test_validation_logic():
 27      """Test validation."""
 28      assert True
 29  
 30  def test_feature_d():
 31      assert True
 32  '''
 33  
 34      config = Config(select={RedundantTestDocstring.name})
 35      violations = lint_file(Path("test_something.py"), code, config, index)
 36      # All single-line docstrings should be flagged
 37      # (test_feature_behavior, test_c, and test_validation_logic)
 38      assert len(violations) == 3
 39      assert all(isinstance(v.rule, RedundantTestDocstring) for v in violations)
 40  
 41  
 42  def test_docstring_word_overlap(index: SymbolIndex) -> None:
 43      code = '''
 44  def test_very_long_function_name():
 45      """Short."""
 46      assert True
 47  
 48  def test_short():
 49      """This is a much longer docstring than the function name."""
 50      assert True
 51  
 52  def test_data_validation():
 53      """Test data validation"""
 54      assert True
 55  
 56  def test_multi():
 57      """Line 1
 58      Line 2"""
 59      assert True
 60  
 61  def test_foo_bar_baz():
 62      """Test qux."""
 63      assert True
 64  '''
 65  
 66      config = Config(select={RedundantTestDocstring.name})
 67      violations = lint_file(Path("test_length.py"), code, config, index)
 68      # All single-line docstrings should be flagged
 69      # (test_very_long_function_name, test_short, test_data_validation, test_foo_bar_baz)
 70      assert len(violations) == 4
 71  
 72  
 73  def test_class_docstrings_follow_same_rules(index: SymbolIndex) -> None:
 74      code = '''
 75  class TestFeature:
 76      """
 77      Tests for the Feature module.
 78      Includes comprehensive test coverage.
 79      """
 80      def test_method(self):
 81          assert True
 82  
 83  class TestFeatureImplementation:
 84      """Test feature."""
 85      pass
 86  
 87  class TestShort:
 88      """This is a longer docstring than the class name TestShort."""
 89      pass
 90  '''
 91  
 92      config = Config(select={RedundantTestDocstring.name})
 93      violations = lint_file(Path("test_classes.py"), code, config, index)
 94      # Both classes with single-line docstrings should be flagged
 95      assert len(violations) == 2
 96  
 97  
 98  def test_non_test_files_are_ignored(index: SymbolIndex) -> None:
 99      code = '''
100  def test_something():
101      """Short."""
102      assert True
103  
104  class TestFeature:
105      """Test."""
106      pass
107  '''
108  
109      config = Config(select={RedundantTestDocstring.name})
110      violations = lint_file(Path("regular_module.py"), code, config, index)
111      assert len(violations) == 0
112  
113  
114  def test_supports_test_suffix_files(index: SymbolIndex) -> None:
115      code = '''
116  def test_feature_implementation():
117      """Test feature."""
118      assert True
119  
120  class TestClassImplementation:
121      """Test class."""
122      pass
123  '''
124  
125      config = Config(select={RedundantTestDocstring.name})
126      violations = lint_file(Path("module_test.py"), code, config, index)
127      assert len(violations) == 2
128  
129  
130  def test_multiline_docstrings_are_always_allowed(index: SymbolIndex) -> None:
131      code = '''def test_with_multiline():
132      """
133      Multi-line.
134      """
135      assert True
136  
137  def test_with_multiline_compact():
138      """Line 1
139      Line 2"""
140      assert True
141  
142  class TestWithMultilineDoc:
143      """
144      Multi
145      Line
146      """
147      pass
148  
149  class TestCompactMultiline:
150      """Line1
151      Line2"""
152      pass
153  '''
154  
155      config = Config(select={RedundantTestDocstring.name})
156      violations = lint_file(Path("test_multiline.py"), code, config, index)
157      assert len(violations) == 0
158  
159  
160  def test_error_message_content(index: SymbolIndex) -> None:
161      code = '''def test_data_processing_validation():
162      """Test data processing."""
163      pass
164  
165  class TestDataProcessingValidation:
166      """Test data processing."""
167      pass
168  '''
169  
170      config = Config(select={RedundantTestDocstring.name})
171      violations = lint_file(Path("test_messages.py"), code, config, index)
172      assert len(violations) == 2
173  
174      func_violation = violations[0]
175      assert "rarely provide meaningful context" in func_violation.rule.message
176      assert "Consider removing it" in func_violation.rule.message
177  
178      class_violation = violations[1]
179      assert "rarely provide meaningful context" in class_violation.rule.message
180      assert "Consider removing it" in class_violation.rule.message
181  
182  
183  def test_module_single_line_docstrings_are_flagged(index: SymbolIndex) -> None:
184      code = '''"""This is a test module."""
185  def test_something():
186      assert True
187  '''
188  
189      config = Config(select={RedundantTestDocstring.name})
190      violations = lint_file(Path("test_module.py"), code, config, index)
191      assert len(violations) == 1
192      assert isinstance(violations[0].rule, RedundantTestDocstring)
193      assert "rarely provide meaningful context" in violations[0].rule.message
194  
195  
196  def test_module_multiline_docstrings_are_allowed(index: SymbolIndex) -> None:
197      code = '''"""
198  This is a test module.
199  It has multiple lines.
200  """
201  def test_something():
202      assert True
203  '''
204  
205      config = Config(select={RedundantTestDocstring.name})
206      violations = lint_file(Path("test_module.py"), code, config, index)
207      assert len(violations) == 0
208  
209  
210  def test_module_without_docstring_is_not_flagged(index: SymbolIndex) -> None:
211      code = """def test_something():
212      assert True
213  """
214  
215      config = Config(select={RedundantTestDocstring.name})
216      violations = lint_file(Path("test_module.py"), code, config, index)
217      assert len(violations) == 0
218  
219  
220  def test_non_test_module_docstrings_are_ignored(index: SymbolIndex) -> None:
221      code = '''"""This is a regular module."""
222  def some_function():
223      pass
224  '''
225  
226      config = Config(select={RedundantTestDocstring.name})
227      violations = lint_file(Path("regular_module.py"), code, config, index)
228      assert len(violations) == 0