Skip to content

Commit

Permalink
Merge d92b334 into b37a361
Browse files Browse the repository at this point in the history
  • Loading branch information
phihos committed Nov 23, 2018
2 parents b37a361 + d92b334 commit 7576b63
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 12 deletions.
2 changes: 1 addition & 1 deletion mutpy/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def mutate_module(self, target_module, to_mutate, total_duration):
if self.mutation_number and self.mutation_number != mutation_number:
self.score.inc_incompetent()
continue
self.notify_mutation(mutation_number, mutations, target_module.__name__, mutant_ast)
self.notify_mutation(mutation_number, mutations, target_module, mutant_ast)
mutant_module = self.create_mutant_module(target_module, mutant_ast)
if mutant_module:
self.run_tests_with_mutant(total_duration, mutant_module, mutations, coverage_result)
Expand Down
41 changes: 40 additions & 1 deletion mutpy/test/test_views.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
import sys
import unittest
from contextlib import contextmanager
from io import StringIO

from mutpy.views import QuietTextView
from mutpy import utils
from mutpy.views import QuietTextView, TextView

COLOR_RED = 'red'


@contextmanager
def captured_output():
new_out, new_err = StringIO(), StringIO()
old_out, old_err = sys.stdout, sys.stderr
try:
sys.stdout, sys.stderr = new_out, new_err
yield sys.stdout, sys.stderr
finally:
sys.stdout, sys.stderr = old_out, old_err


class QuietTextViewTest(unittest.TestCase):
@staticmethod
def get_quiet_text_view(colored_output=False):
Expand All @@ -19,3 +34,27 @@ def test_decorate_with_color(self):
colored_text = text_view.decorate(text, color=COLOR_RED)
# then
self.assertEqual(expected_colored_text, colored_text)


class TextViewTest(unittest.TestCase):
SEPARATOR = '--------------------------------------------------------------------------------'
EOL = "\n"

@staticmethod
def get_text_view(colored_output=False, show_mutants=False):
return TextView(colored_output=colored_output, show_mutants=show_mutants)

def test_print_code(self):
# given
text_view = self.get_text_view(show_mutants=True)
original = utils.create_ast('x = x + 1')
mutant = utils.create_ast('x = x - 1')
# when
with captured_output() as (out, err):
text_view.print_code(mutant, original)
# then
output = out.getvalue().strip()
self.assertEqual(
self.SEPARATOR + self.EOL + '- 1: x = x + 1' + self.EOL + '+ 1: x = x - 1' + self.EOL + self.SEPARATOR,
output
)
34 changes: 24 additions & 10 deletions mutpy/views.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import ast
import datetime
import inspect
import os
import traceback
import datetime
import yaml
from difflib import unified_diff

import jinja2
import yaml

from mutpy import codegen, termcolor, utils


Expand Down Expand Up @@ -121,27 +126,36 @@ def original_tests_fail(self, result):
def mutation(self, number, mutations, module, mutant):
for mutation in mutations:
self.level_print(
'[#{:>4}] {:<3} {}:{:<3}: '.format(number, mutation.operator.name(), module, mutation.node.lineno),
'[#{:>4}] {:<3} {}: '.format(number, mutation.operator.name(), module.__name__),
ended=False,
level=2,
)
if mutation != mutations[-1]:
print()
if self.show_mutants:
self.print_code(mutant, mutation.node.lineno)
self.print_code(mutant, ast.parse(inspect.getsource(module)))

def cant_load(self, name, exception):
self.level_print(self.decorate('Can\'t load module: ', 'red', attrs=['bold']) + '{} ({}: {})'.format(name,
exception.__class__.__name__, exception))

def print_code(self, mutant, lineno):
def print_code(self, mutant, original):
mutant_src = codegen.to_source(mutant)
mutant_src = codegen.add_line_numbers(mutant_src)
src_lines = mutant_src.split("\n")
lineno = min(lineno, len(src_lines))
src_lines[lineno - 1] = self.decorate('~' + src_lines[lineno - 1][1:], 'yellow')
snippet = src_lines[max(0, lineno - 5):min(len(src_lines), lineno + 5)]
print("\n{}\n".format('-'*80) + "\n".join(snippet) + "\n{}".format('-'*80))
original_src = codegen.to_source(original)
original_src = codegen.add_line_numbers(original_src)
self._print_diff(mutant_src, original_src)

def _print_diff(self, mutant_src, original_src):
diff = self._create_diff(mutant_src, original_src)
diff = [line for line in diff if not line.startswith(('---', '+++', '@@'))]
diff = [self.decorate(line, 'blue') if line.startswith('- ') else line for line in diff]
diff = [self.decorate(line, 'green') if line.startswith('+ ') else line for line in diff]
print("\n{}\n".format('-' * 80) + "\n".join(diff) + "\n{}".format('-' * 80))

@staticmethod
def _create_diff(mutant_src, original_src):
return list(unified_diff(original_src.split('\n'), mutant_src.split('\n'), n=4, lineterm=''))

def killed(self, time, killer, *args, **kwargs):
self.level_print(self.time_format(time) + ' ' + self.decorate('killed', 'green') + ' by ' + str(killer),
Expand Down

0 comments on commit 7576b63

Please sign in to comment.