Total Complexity | 58 |
Total Lines | 488 |
Duplicated Lines | 0 % |
Complex classes like coalib.tests.output.ConsoleInteractionTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | import tempfile |
||
101 | class ConsoleInteractionTest(unittest.TestCase): |
||
102 | def setUp(self): |
||
103 | self.log_printer = LogPrinter(ConsolePrinter(print_colored=False)) |
||
104 | self.console_printer = ConsolePrinter(print_colored=False) |
||
105 | self.file_diff_dict = {} |
||
106 | self.local_bears = OrderedDict([("default", [KeywordBear]), |
||
107 | ("test", [LineLengthBear, |
||
108 | KeywordBear])]) |
||
109 | self.global_bears = OrderedDict([("default", [SomeglobalBear]), |
||
110 | ("test", [SomeglobalBear])]) |
||
111 | |||
112 | OpenEditorAction.is_applicable = staticmethod(lambda *args: False) |
||
113 | ApplyPatchAction.is_applicable = staticmethod(lambda *args: False) |
||
114 | |||
115 | def test_require_settings(self): |
||
116 | self.assertRaises(TypeError, acquire_settings, self.log_printer, 0) |
||
117 | self.assertEqual(acquire_settings(self.log_printer, {0: 0}), {}) |
||
118 | |||
119 | with simulate_console_inputs(0, 1, 2) as generator: |
||
120 | self.assertEqual(acquire_settings(self.log_printer, |
||
121 | {"setting": ["help text", |
||
122 | "SomeBear"]}), |
||
123 | {"setting": 0}) |
||
124 | |||
125 | self.assertEqual(acquire_settings(self.log_printer, |
||
126 | {"setting": ["help text", |
||
127 | "SomeBear", |
||
128 | "AnotherBear"]}), |
||
129 | {"setting": 1}) |
||
130 | |||
131 | self.assertEqual(acquire_settings(self.log_printer, |
||
132 | {"setting": ["help text", |
||
133 | "SomeBear", |
||
134 | "AnotherBear", |
||
135 | "YetAnotherBear"]}), |
||
136 | {"setting": 2}) |
||
137 | |||
138 | self.assertEqual(generator.last_input, 2) |
||
139 | |||
140 | def test_print_result(self): |
||
141 | print_result(self.console_printer, |
||
142 | self.log_printer, |
||
143 | None, |
||
144 | self.file_diff_dict, |
||
145 | "illegal value", |
||
146 | {}) |
||
147 | |||
148 | with simulate_console_inputs(0): |
||
149 | print_result(self.console_printer, |
||
150 | self.log_printer, |
||
151 | None, |
||
152 | self.file_diff_dict, |
||
153 | Result("origin", "msg", diffs={}), |
||
154 | {}) |
||
155 | |||
156 | (testfile, testfile_path) = tempfile.mkstemp() |
||
157 | os.close(testfile) |
||
158 | file_dict = { |
||
159 | testfile_path: ["1\n", "2\n", "3\n"], |
||
160 | "f_b": ["1", "2", "3"] |
||
161 | } |
||
162 | diff = Diff(file_dict[testfile_path]) |
||
163 | diff.delete_line(2) |
||
164 | diff.change_line(3, "3\n", "3_changed\n") |
||
165 | |||
166 | with simulate_console_inputs(1), self.assertRaises(ValueError): |
||
167 | ApplyPatchAction.is_applicable = staticmethod(lambda *args: True) |
||
168 | print_result(self.console_printer, |
||
169 | self.log_printer, |
||
170 | None, |
||
171 | self.file_diff_dict, |
||
172 | Result("origin", "msg", diffs={testfile_path: diff}), |
||
173 | file_dict) |
||
174 | |||
175 | # Interaction must be closed by the user with `0` if it's not a param |
||
176 | with simulate_console_inputs("INVALID", |
||
177 | -1, |
||
178 | 1, |
||
179 | 0, |
||
180 | 3) as input_generator: |
||
181 | curr_section = Section("") |
||
182 | print_section_beginning(self.console_printer, curr_section) |
||
183 | print_result(self.console_printer, |
||
184 | self.log_printer, |
||
185 | curr_section, |
||
186 | self.file_diff_dict, |
||
187 | Result("origin", "msg", diffs={testfile_path: diff}), |
||
188 | file_dict) |
||
189 | self.assertEqual(input_generator.last_input, 3) |
||
190 | |||
191 | self.file_diff_dict.clear() |
||
192 | |||
193 | with open(testfile_path) as f: |
||
194 | self.assertEqual(f.readlines(), ["1\n", "3_changed\n"]) |
||
195 | |||
196 | os.remove(testfile_path) |
||
197 | os.remove(testfile_path + ".orig") |
||
198 | |||
199 | name, section = get_action_info(curr_section, |
||
200 | TestAction().get_metadata()) |
||
201 | self.assertEqual(input_generator.last_input, 4) |
||
202 | self.assertEqual(str(section), " {param : '3'}") |
||
203 | self.assertEqual(name, "TestAction") |
||
204 | |||
205 | # Check if the user is asked for the parameter only the first time. |
||
206 | # Use OpenEditorAction that needs this parameter (editor command). |
||
207 | with simulate_console_inputs(1, "test_editor", 0, 1, 0) as generator: |
||
208 | OpenEditorAction.is_applicable = staticmethod(lambda *args: True) |
||
209 | |||
210 | patch_result = Result("origin", "msg", diffs={testfile_path: diff}) |
||
211 | patch_result.file = "f_b" |
||
212 | |||
213 | print_result(self.console_printer, |
||
214 | self.log_printer, |
||
215 | curr_section, |
||
216 | self.file_diff_dict, |
||
217 | patch_result, |
||
218 | file_dict) |
||
219 | # choose action, choose editor, choose no action (-1 -> 2) |
||
220 | self.assertEqual(generator.last_input, 2) |
||
221 | |||
222 | # It shoudn't ask for parameter again |
||
223 | print_result(self.console_printer, |
||
224 | self.log_printer, |
||
225 | curr_section, |
||
226 | self.file_diff_dict, |
||
227 | patch_result, |
||
228 | file_dict) |
||
229 | self.assertEqual(generator.last_input, 4) |
||
230 | |||
231 | def test_print_result_auto_apply(self): |
||
232 | section = Section("X") |
||
233 | section.append(Setting("default_actions", |
||
234 | "SuperBear: InvalidACTION, XBear: ABC, " |
||
235 | "UltraBear: ApplyPatchAction")) |
||
236 | with retrieve_stdout() as stdout: |
||
237 | print_result(self.console_printer, |
||
238 | self.log_printer, |
||
239 | section, |
||
240 | self.file_diff_dict, |
||
241 | Result("origin", "msg", diffs={}), |
||
242 | {}) |
||
243 | console_content = stdout.getvalue() |
||
244 | self.assertIn("Selected default action 'InvalidACTION' for bear " |
||
245 | "'SuperBear' does not exist.", |
||
246 | console_content) |
||
247 | self.assertIn("Selected default action 'ABC' for bear 'XBear' " |
||
248 | "does not exist.", |
||
249 | console_content) |
||
250 | self.assertIn("Selected default action 'ApplyPatchAction' for " |
||
251 | "bear 'UltraBear' is not applicable.", |
||
252 | console_content) |
||
253 | |||
254 | CLI_ACTIONS.append(TestAction()) |
||
255 | |||
256 | section = Section("A") |
||
257 | section.append(Setting("default_actions", |
||
258 | "MyBear: TestAction")) |
||
259 | with retrieve_stdout() as stdout: |
||
260 | print_result(self.console_printer, |
||
261 | self.log_printer, |
||
262 | section, |
||
263 | self.file_diff_dict, |
||
264 | Result("MyBear", "msg", diffs={}), |
||
265 | {}) |
||
266 | self.assertNotIn("Selected default action 'TestAction' for bear " |
||
267 | "'MyBear' does not exist or is not " |
||
268 | "applicable.", |
||
269 | stdout.getvalue()) |
||
270 | |||
271 | CLI_ACTIONS.pop() |
||
272 | |||
273 | CLI_ACTIONS.append(RaisingAction()) |
||
274 | |||
275 | section = Section("B") |
||
276 | section.append(Setting("default_actions", |
||
277 | "MySuperBear: RaisingAction")) |
||
278 | |||
279 | with retrieve_stdout() as stdout: |
||
280 | print_result(self.console_printer, |
||
281 | self.log_printer, |
||
282 | section, |
||
283 | self.file_diff_dict, |
||
284 | Result("MySuperBear", "msg", diffs={}), |
||
285 | {}) |
||
286 | self.assertIn("Failed to execute action RaisingAction.", |
||
287 | stdout.getvalue()) |
||
288 | |||
289 | CLI_ACTIONS.pop() |
||
290 | |||
291 | def test_print_section_beginning(self): |
||
292 | with retrieve_stdout() as stdout: |
||
293 | print_section_beginning(self.console_printer, Section("name")) |
||
294 | self.assertEqual(stdout.getvalue(), "Executing section name...\n") |
||
295 | |||
296 | def test_nothing_done(self): |
||
297 | with retrieve_stdout() as stdout: |
||
298 | nothing_done(self.log_printer) |
||
299 | self.assertIn("No existent section was targeted or enabled. " |
||
300 | "Nothing to do.\n", |
||
301 | stdout.getvalue()) |
||
302 | |||
303 | def test_print_results_empty(self): |
||
304 | with retrieve_stdout() as stdout: |
||
305 | print_results(self.log_printer, Section(""), [], {}, {}) |
||
306 | self.assertEqual(stdout.getvalue(), "") |
||
307 | |||
308 | def test_print_results_project_wide(self): |
||
309 | with retrieve_stdout() as stdout: |
||
310 | print_results(self.log_printer, |
||
311 | Section(""), |
||
312 | [Result("origin", "message")], |
||
313 | {}, |
||
314 | {}, |
||
315 | color=False) |
||
316 | self.assertEqual( |
||
317 | "\n{}\n| | [NORMAL] origin:\n| | message" |
||
318 | "\n".format(STR_PROJECT_WIDE), |
||
319 | stdout.getvalue()) |
||
320 | |||
321 | def test_print_results_for_file(self): |
||
322 | with retrieve_stdout() as stdout: |
||
323 | print_results( |
||
324 | self.log_printer, |
||
325 | Section(""), |
||
326 | [Result.from_values("SpaceConsistencyBear", |
||
327 | "Trailing whitespace found", |
||
328 | file="proj/white", |
||
329 | line=2)], |
||
330 | {"proj/white": ["test line\n", "line 2\n", "line 3\n"]}, |
||
331 | {}, |
||
332 | color=False) |
||
333 | self.assertEqual("""\nproj/white |
||
334 | | 2| line 2 |
||
335 | | | [NORMAL] SpaceConsistencyBear: |
||
336 | | | Trailing whitespace found |
||
337 | """, |
||
338 | stdout.getvalue()) |
||
339 | |||
340 | with retrieve_stdout() as stdout: |
||
341 | print_results( |
||
342 | self.log_printer, |
||
343 | Section(""), |
||
344 | [Result.from_values("SpaceConsistencyBear", |
||
345 | "Trailing whitespace found", |
||
346 | file="proj/white", |
||
347 | line=5)], |
||
348 | {"proj/white": ["test line\n", |
||
349 | "line 2\n", |
||
350 | "line 3\n", |
||
351 | "line 4\n", |
||
352 | "line 5\n"]}, |
||
353 | {}, |
||
354 | color=False) |
||
355 | self.assertEqual("""\nproj/white |
||
356 | | 5| line 5 |
||
357 | | | [NORMAL] SpaceConsistencyBear: |
||
358 | | | Trailing whitespace found |
||
359 | """, |
||
360 | stdout.getvalue()) |
||
361 | |||
362 | def test_print_results_sorting(self): |
||
363 | with retrieve_stdout() as stdout: |
||
364 | print_results(self.log_printer, |
||
365 | Section(""), |
||
366 | [Result.from_values("SpaceConsistencyBear", |
||
367 | "Trailing whitespace found", |
||
368 | file="file", |
||
369 | line=5), |
||
370 | Result.from_values("SpaceConsistencyBear", |
||
371 | "Trailing whitespace found", |
||
372 | file="file", |
||
373 | line=2)], |
||
374 | {"file": ["test line\n", |
||
375 | "line 2\n", |
||
376 | "line 3\n", |
||
377 | "line 4\n", |
||
378 | "line 5\n"]}, |
||
379 | {}, |
||
380 | color=False) |
||
381 | |||
382 | self.assertEqual(""" |
||
383 | file |
||
384 | | 2| line 2 |
||
385 | | | [NORMAL] SpaceConsistencyBear: |
||
386 | | | Trailing whitespace found |
||
387 | |||
388 | file |
||
389 | | 5| line 5 |
||
390 | | | [NORMAL] SpaceConsistencyBear: |
||
391 | | | Trailing whitespace found |
||
392 | """, |
||
393 | stdout.getvalue()) |
||
394 | |||
395 | def test_print_results_multiple_ranges(self): |
||
396 | affected_code = (SourceRange.from_values("some_file", 5, end_line=7), |
||
397 | SourceRange.from_values("another_file", 1, 3, 1, 5), |
||
398 | SourceRange.from_values("another_file", 3, 3, 3, 5)) |
||
399 | with retrieve_stdout() as stdout: |
||
400 | print_results( |
||
401 | self.log_printer, |
||
402 | Section(""), |
||
403 | [Result("ClangCloneDetectionBear", |
||
404 | "Clone Found", |
||
405 | affected_code)], |
||
406 | {"some_file": ["line "+str(i+1)+"\n" for i in range(10)], |
||
407 | "another_file": ["line "+str(i+1)+"\n" for i in range(10)]}, |
||
408 | {}, |
||
409 | color=False) |
||
410 | self.assertEqual(""" |
||
411 | another_file |
||
412 | | 1| line 1 |
||
413 | |||
414 | another_file |
||
415 | | 3| line 3 |
||
416 | |||
417 | some_file |
||
418 | | 5| line 5 |
||
419 | | 6| line 6 |
||
420 | | 7| line 7 |
||
421 | | | [NORMAL] ClangCloneDetectionBear: |
||
422 | | | Clone Found |
||
423 | """, |
||
424 | stdout.getvalue()) |
||
425 | |||
426 | def test_print_results_missing_file(self): |
||
427 | self.log_printer = LogPrinter(NullPrinter()) |
||
428 | with retrieve_stdout() as stdout: |
||
429 | print_results( |
||
430 | self.log_printer, |
||
431 | Section(""), |
||
432 | [Result("t", "msg"), |
||
433 | Result.from_values("t", "msg", file="file", line=5)], |
||
434 | {}, |
||
435 | {}, |
||
436 | color=False) |
||
437 | self.assertEqual("\n" + STR_PROJECT_WIDE + "\n" |
||
438 | "| | [NORMAL] t:\n" |
||
439 | "| | msg\n" |
||
440 | # Second results file isn't there, no context is |
||
441 | # printed, only a warning log message which we |
||
442 | # don't catch |
||
443 | "| | [NORMAL] t:\n" |
||
444 | "| | msg\n", stdout.getvalue()) |
||
445 | |||
446 | def test_print_results_missing_line(self): |
||
447 | with retrieve_stdout() as stdout: |
||
448 | print_results( |
||
449 | self.log_printer, |
||
450 | Section(""), |
||
451 | [Result.from_values("t", "msg", file="file", line=5), |
||
452 | Result.from_values("t", "msg", file="file", line=6)], |
||
453 | {"file": ["line " + str(i+1) for i in range(5)]}, |
||
454 | {}, |
||
455 | color=False) |
||
456 | self.assertEqual("\n" |
||
457 | "file\n" |
||
458 | "| 5| line 5\n" |
||
459 | "| | [NORMAL] t:\n" |
||
460 | "| | msg\n" |
||
461 | "\n" |
||
462 | "file\n" |
||
463 | "| | {}\n" |
||
464 | "| | [NORMAL] t:\n" |
||
465 | "| | msg\n".format(STR_LINE_DOESNT_EXIST), |
||
466 | stdout.getvalue()) |
||
467 | |||
468 | def test_print_results_without_line(self): |
||
469 | with retrieve_stdout() as stdout: |
||
470 | print_results( |
||
471 | self.log_printer, |
||
472 | Section(""), |
||
473 | [Result.from_values("t", "msg", file="file")], |
||
474 | {"file": []}, |
||
475 | {}, |
||
476 | color=False) |
||
477 | self.assertEqual( |
||
478 | "\nfile\n" |
||
479 | "| | [NORMAL] t:\n" |
||
480 | "| | msg\n", |
||
481 | stdout.getvalue()) |
||
482 | |||
483 | def test_print_bears_empty(self): |
||
484 | with retrieve_stdout() as stdout: |
||
485 | bears = {} |
||
486 | print_bears(self.log_printer.printer, bears, True) |
||
487 | self.assertEqual("No bears to show.\n", stdout.getvalue()) |
||
488 | with retrieve_stdout() as stdout: |
||
489 | bears = {} |
||
490 | print_bears(self.log_printer.printer, bears, False) |
||
491 | self.assertEqual("No bears to show.\n", stdout.getvalue()) |
||
492 | |||
493 | def test_print_bears(self): |
||
494 | with retrieve_stdout() as stdout: |
||
495 | bears = {TestBear: ["default", "docs"]} |
||
496 | print_bears(self.log_printer.printer, bears, False) |
||
497 | expected_string = "TestBear:\n" |
||
498 | expected_string += " Test bear Description.\n\n" |
||
499 | expected_string += " Used in:\n" |
||
500 | expected_string += " * default\n" |
||
501 | expected_string += " * docs\n\n" |
||
502 | expected_string += " Needed Settings:\n" |
||
503 | expected_string += " * setting1: Required Setting.\n\n" |
||
504 | expected_string += " Optional Settings:\n" |
||
505 | expected_string += " * setting2: Optional Setting. (" |
||
506 | expected_string += "Optional, defaults to 'None'." |
||
507 | expected_string += ")\n\n" |
||
508 | |||
509 | self.assertEqual(expected_string, stdout.getvalue()) |
||
510 | |||
511 | def test_print_bears_no_settings(self): |
||
512 | with retrieve_stdout() as stdout: |
||
513 | bears = {SomeBear: ["default"]} |
||
514 | print_bears(self.log_printer.printer, bears, False) |
||
515 | expected_string = "SomeBear:\n" |
||
516 | expected_string += " Some Description.\n\n" |
||
517 | expected_string += " Used in:\n" |
||
518 | expected_string += " * default\n\n" |
||
519 | expected_string += " No needed settings.\n\n" |
||
520 | expected_string += " No optional settings.\n\n" |
||
521 | |||
522 | self.assertEqual(expected_string, stdout.getvalue()) |
||
523 | |||
524 | def test_print_bears_no_needed_settings(self): |
||
525 | with retrieve_stdout() as stdout: |
||
526 | bears = {SomeOtherBear: ["test"]} |
||
527 | print_bears(self.log_printer.printer, bears, False) |
||
528 | expected_string = "SomeOtherBear:\n" |
||
529 | expected_string += " This is a Bear.\n\n" |
||
530 | expected_string += " Used in:\n" |
||
531 | expected_string += " * test\n\n" |
||
532 | expected_string += " No needed settings.\n\n" |
||
533 | expected_string += " Optional Settings:\n" |
||
534 | expected_string += " * setting: This is an optional setting. (" |
||
535 | expected_string += "Optional, defaults to 'None'." |
||
536 | expected_string += ")\n\n" |
||
537 | |||
538 | self.assertEqual(expected_string, stdout.getvalue()) |
||
539 | |||
540 | def test_print_bears_no_optional_settings(self): |
||
541 | with retrieve_stdout() as stdout: |
||
542 | bears = {TestBear2: ["test"]} |
||
543 | print_bears(self.log_printer.printer, bears, False) |
||
544 | expected_string = "TestBear2:\n" |
||
545 | expected_string += " Test bear 2 description.\n\n" |
||
546 | expected_string += " Used in:\n" |
||
547 | expected_string += " * test\n\n" |
||
548 | expected_string += " Needed Settings:\n" |
||
549 | expected_string += " * setting1: Required Setting.\n\n" |
||
550 | expected_string += " No optional settings.\n\n" |
||
551 | |||
552 | self.assertEqual(expected_string, stdout.getvalue()) |
||
553 | |||
554 | def test_print_bears_no_sections(self): |
||
555 | with retrieve_stdout() as stdout: |
||
556 | bears = {SomeBear: []} |
||
557 | print_bears(self.log_printer.printer, bears, False) |
||
558 | expected_string = "SomeBear:\n" |
||
559 | expected_string += " Some Description.\n\n" |
||
560 | expected_string += " No sections.\n\n" |
||
561 | expected_string += " No needed settings.\n\n" |
||
562 | expected_string += " No optional settings.\n\n" |
||
563 | |||
564 | self.assertEqual(expected_string, stdout.getvalue()) |
||
565 | |||
566 | def test_show_bears(self): |
||
567 | with retrieve_stdout() as stdout: |
||
568 | bears = {KeywordBear: ['default', 'test'], |
||
569 | LineLengthBear: ['test'], |
||
570 | SomeglobalBear: ['default', 'test']} |
||
571 | print_bears(self.log_printer.printer, bears, False) |
||
572 | expected_string = stdout.getvalue() |
||
573 | self.maxDiff = None |
||
574 | with retrieve_stdout() as stdout: |
||
575 | show_bears(self.local_bears, |
||
576 | self.global_bears, |
||
577 | False, |
||
578 | self.log_printer.printer) |
||
579 | self.assertEqual(expected_string, stdout.getvalue()) |
||
580 | |||
581 | with retrieve_stdout() as stdout: |
||
582 | show_bears(self.local_bears, |
||
583 | self.global_bears, |
||
584 | True, |
||
585 | self.log_printer.printer) |
||
586 | self.assertEqual(" * KeywordBear\n" |
||
587 | " * LineLengthBear\n" |
||
588 | " * SomeglobalBear\n", stdout.getvalue()) |
||
589 | |||
661 |