1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
#!/usr/bin/env python3
"""
Script add PIT mutation plugin to maven files and run mutations.
"""
import argparse
import os
import os.path
import shutil
import subprocess
import sys
import xml.etree.ElementTree as ET
PIT_GROUP_ID = 'org.pitest'
PIT_ARTIFACT_ID = 'pitest-maven'
PIT_VERSION = '1.14.4'
PIT_JUNIT5_ARTIFACT_ID = 'pitest-junit5-plugin'
PIT_JUNIT5_VERSION = '1.2.0'
NAMESPACES = {'': 'http://maven.apache.org/POM/4.0.0'}
for prefix, url in NAMESPACES.items():
ET.register_namespace(prefix, url)
MUTATORS = [
'STRONGER'
]
OPEN_COMMAND = 'x-www-browser' # or xdg-open
def create_args():
parser = argparse.ArgumentParser()
parser.add_argument('-pl', '--projects')
parser.add_argument('-pn', '--project-name')
parser.add_argument('-am', '--also-make', action='store_true')
parser.add_argument('-q', '--quiet', action='store_true')
parser.add_argument('globs', nargs='+')
return parser
def get_pom_files():
for root, dirs, files in os.walk('.'):
for file in files:
if file == 'pom.xml':
yield os.path.join(root, file)
def make_file_backup(file):
dst = '%s.bak.%d' % (file, os.getpid())
shutil.copyfile(file, dst)
return file, dst
def update_pom(file, project, globs):
tree = ET.parse(file)
root = tree.getroot()
artifact_id = root.find('./artifactId', NAMESPACES).text
build = root.find('./build', NAMESPACES)
if build is None:
build = ET.SubElement(root, 'build')
plugins = build.find('./plugins', NAMESPACES)
if plugins is None:
plugins = ET.SubElement(build, 'plugins')
plugin = ET.SubElement(plugins, 'plugin')
ET.SubElement(plugin, 'groupId').text = PIT_GROUP_ID
ET.SubElement(plugin, 'artifactId').text = PIT_ARTIFACT_ID
ET.SubElement(plugin, 'version').text = PIT_VERSION
dependencies = ET.SubElement(plugin, 'dependencies')
dependency = ET.SubElement(dependencies, 'dependency')
ET.SubElement(dependency, 'groupId').text = PIT_GROUP_ID
ET.SubElement(dependency, 'artifactId').text = PIT_JUNIT5_ARTIFACT_ID
ET.SubElement(dependency, 'version').text = PIT_JUNIT5_VERSION
configuration = ET.SubElement(plugin, 'configuration')
if artifact_id == project or project is None:
ET.SubElement(configuration, 'skip').text = 'False'
target_classes = ET.SubElement(configuration, 'targetClasses')
target_tests = ET.SubElement(configuration, 'targetTests')
for glob in globs:
ET.SubElement(target_classes, 'param').text = glob
ET.SubElement(target_tests, 'param').text = glob
mutators = ET.SubElement(configuration, 'mutators')
for mutator in MUTATORS:
ET.SubElement(mutators, 'mutator').text = mutator
formats = ET.SubElement(configuration, 'outputFormats')
ET.SubElement(formats, 'outputFormat').text = 'HTML'
ET.SubElement(formats, 'outputFormat').text = 'XML'
else:
ET.SubElement(configuration, 'skip').text = 'True'
tree.write(file)
def run_mutation_coverage(args):
command = ['mvn', '--batch-mode', 'test-compile', 'org.pitest:pitest-maven:mutationCoverage']
if args.also_make:
command.append('--also-make')
if args.projects:
command.append('--projects')
command.append(args.projects)
if args.quiet:
command.append('--quiet')
subprocess.call(' '.join(command), shell=True, stdout=sys.stdout, stderr=sys.stderr)
def print_details(filename):
subprocess.call(['pandoc', '--to', 'plain', filename], stdout=sys.stdout, stderr=sys.stderr)
def open_result(project):
target = os.path.join(project, 'target', 'pit-reports')
dirs = os.listdir(target)
if dirs:
last_dir = sorted(dirs)[-1]
index_file = os.path.join(target, last_dir, 'index.html')
if os.path.isfile(index_file):
print_details(index_file)
print('Report:', os.path.abspath(index_file))
subprocess.call([OPEN_COMMAND, os.path.abspath(index_file)])
def update_pom_files(args):
backup_files = []
try:
for file in get_pom_files():
backup_files.append(make_file_backup(file))
update_pom(file, args.project_name or args.projects, args.globs)
run_mutation_coverage(args)
open_result(args.projects)
finally:
for orig, backup in backup_files:
shutil.move(backup, orig)
def main():
args = create_args().parse_args()
update_pom_files(args)
if __name__ == '__main__':
main()
|