commit - 568de39969dba9780429ff37e612382ec145b9d6
commit + f20ac5dfb78a9af1b0691535ab6e4880c5d7ee4a
blob - 2464e4df4be4115e48c1f1f96155346ee5a64149
blob + 8ad3f666594e3a4d838684db12cd4c2ecbd3d3d6
--- generate.py
+++ generate.py
from jinja2 import Template
+STATUS_KILLED = "Killed"
+STATUS_SURVIVED = "Survived"
+STATUS_NO_COVERAGE = "NoCoverage"
+STATUS_COMPILE_ERROR = "CompileError"
+STATUS_RUNTIME_ERROR = "RuntimeError"
+STATUS_TIMEOUT = "Timeout"
+STATUS_IGNORED = "Ignored"
+
+LIST_STATUSES = [STATUS_KILLED,
+ STATUS_SURVIVED,
+ STATUS_NO_COVERAGE,
+ STATUS_COMPILE_ERROR,
+ STATUS_RUNTIME_ERROR,
+ STATUS_TIMEOUT,
+ STATUS_IGNORED]
+
SUPPORTED_SCHEMA_VERSIONS = ["1.0"]
DEFAULT_TEXT_TEMPLATE = """
{% endfor %}
{% endfor %}
-Schema version: {{ version }}
+Schema version: {{ json_data['schemaVersion'] }}
Time of generation: {{ current_time.strftime('%d-%m-%Y %H:%M') }}
"""
<div>
<div>Mutation states</div>
<div>
-<div>Killed</div>
+<div>Killed</div> - {{ killed }}
When at least one test failed while this mutant was active, the mutant is
-killed. This is what you want, good job!
+killed.
</div>
<div>
-<div>Survived</div>
+<div>Survived</div> - {{ survived }}
When all tests passed while this mutant was active, the mutant survived. You're
missing a test for it.
</div>
<div>
-<div>No coverage</div>
+<div>No coverage</div> - {{ no_coverage }}
No tests were executed for this mutant. It probably is located in a part of the
code not hit by any of your tests. This means the mutant survived and you are
missing a test case for it.
</div>
<div>
-<div>Timeout</div>
+<div>Timeout</div> - {{ timeout }}
The running of tests with this mutant active resulted in a timeout. For
example, the mutant resulted in an infinite loop in your code. Don't spend too
much attention to this mutant. It is counted as "detected". The logic here is
</div>
<div>
-<div>Runtime error</div>
+<div>Runtime error</div> - {{ runtime_error }}
The running of the tests resulted in an error (rather than a failed test). This
can happen when the testrunner fails. For example, when a testrunner throws an
OutOfMemoryError or for dynamic languages where the mutant resulted in
</div>
<div>
-<div>Compile error</div>
+<div>Compile error</div> - {{ compile_error }}
The mutant resulted in a compiler error. This can happen in compiled languages.
Don't spend too much attention looking at this mutant. It is not represented in
your mutation score.
</div>
<div>
-<div>Ignored</div>
+<div>Ignored</div> - {{ ignored }}
The mutant was not tested because the config of the user asked for it to be
ignored. This will not count against your mutation score but will show up in
reports.
{% endfor %}
{% endfor %}
-<p>Schema version: {{ version }}</p>
+Schema version: {{ json_data['schemaVersion'] }}
<p>Time of generation: {{ current_time.strftime('%d-%m-%Y %H:%M') }}</p>
</body>
</html>
def render_template(json_data, template):
+ files_mutant_statuses = []
+ for file_name, properties in json_data.get("files", None).items():
+ files_mutant_statuses.append({file_name: file_mutant_statuses(properties)})
+ report_mutant_statuses = sum_statuses(files_mutant_statuses)
+
t = Template(template)
time = datetime.datetime.now()
- schema_version = json_data.get("schemaVersion", None)
- return t.render(json_data=json_data, version=schema_version, current_time=time)
+ return t.render(json_data=json_data,
+ killed=report_mutant_statuses[STATUS_KILLED],
+ survived=report_mutant_statuses[STATUS_SURVIVED],
+ no_coverage=report_mutant_statuses[STATUS_NO_COVERAGE],
+ compile_error=report_mutant_statuses[STATUS_COMPILE_ERROR],
+ runtime_error=report_mutant_statuses[STATUS_RUNTIME_ERROR],
+ timeout=report_mutant_statuses[STATUS_TIMEOUT],
+ ignored=report_mutant_statuses[STATUS_IGNORED],
+ current_time=time)
+
+def dict_statuses():
+ statuses = {STATUS_KILLED: 0,
+ STATUS_SURVIVED: 0,
+ STATUS_NO_COVERAGE: 0,
+ STATUS_COMPILE_ERROR: 0,
+ STATUS_RUNTIME_ERROR: 0,
+ STATUS_TIMEOUT: 0,
+ STATUS_IGNORED: 0}
+
+ return statuses
+
+
+def file_mutant_statuses(json_data):
+ """
+ json_data: a dict that includes dicts "file" described in
+ 'mutation-elements' schema.
+
+ returns: statuses, dict with a name of status and
+ a number mutants with that status.
+ """
+
+ mutants = json_data.get("mutants", None)
+ statuses = dict_statuses()
+ for mutant in mutants:
+ status = mutant.get("status", None)
+ if not status:
+ raise Exception("status is None")
+
+ if status == STATUS_KILLED:
+ statuses[STATUS_KILLED] += 1
+ elif status == STATUS_SURVIVED:
+ statuses[STATUS_SURVIVED] += 1
+ elif status == STATUS_NO_COVERAGE:
+ statuses[STATUS_NO_COVERAGE] += 1
+ elif status == STATUS_COMPILE_ERROR:
+ statuses[STATUS_COMPILE_ERROR] += 1
+ elif status == STATUS_RUNTIME_ERROR:
+ statuses[STATUS_RUNTIME_ERROR] += 1
+ elif status == STATUS_TIMEOUT:
+ statuses[STATUS_TIMEOUT] += 1
+ elif status == STATUS_IGNORED:
+ statuses[STATUS_IGNORED] += 1
+
+ return statuses
+
+
+def sum_statuses(list_of_statuses_per_file):
+ """
+ list_of_statuses: list of dicts {file_name: dict with statuses}
+ """
+ total_num_statuses = dict_statuses()
+ statuses = []
+ for d in list_of_statuses_per_file:
+ statuses += list(d.values())
+ for st in LIST_STATUSES:
+ total_num_statuses[st] = sum(d[st] for d in statuses)
+
+ return total_num_statuses
+
+
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--data", dest="data_path", default="",