pyproteum 0.2__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyproteum-0.2/pyproteum.egg-info → pyproteum-0.2.2}/PKG-INFO +10 -1
- {pyproteum-0.2 → pyproteum-0.2.2}/README.md +9 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproject.toml +1 -1
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/moperators/cccr.py +2 -2
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/moperators/ccsr.py +6 -4
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/moperators/crcr.py +2 -2
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/moperators/myoperator.py +7 -1
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/moperators/oaaa.py +2 -2
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/moperators/oaan.py +2 -2
- pyproteum-0.2.2/pyproteum/moperators/oeap.py +107 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/moperators/oodl.py +2 -3
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/moperators/oplist.py +0 -1
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/moperators/orrn.py +2 -3
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/moperators/ssdl.py +10 -9
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/mutagen.py +9 -5
- {pyproteum-0.2 → pyproteum-0.2.2/pyproteum.egg-info}/PKG-INFO +10 -1
- pyproteum-0.2/pyproteum/moperators/oeap.py +0 -107
- {pyproteum-0.2 → pyproteum-0.2.2}/LICENSE +0 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/__init__.py +0 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/__main__.py +0 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/execution_reg.py +0 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/exemuta.py +0 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/models/models.py +0 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/moperators/sbrc.py +0 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/moperators/scrb.py +0 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/mutaview.py +0 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/mutaviewgui.py +0 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/print_visit.py +0 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/tcase.py +0 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/testnew.py +0 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum/utiles.py +0 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum.egg-info/SOURCES.txt +0 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum.egg-info/dependency_links.txt +0 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum.egg-info/entry_points.txt +0 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum.egg-info/requires.txt +0 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/pyproteum.egg-info/top_level.txt +0 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/setup.cfg +0 -0
- {pyproteum-0.2 → pyproteum-0.2.2}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyproteum
|
|
3
|
-
Version: 0.2
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: A tool for mutation testing in Python. Implemented as a Python module.
|
|
5
5
|
Author: Delamaro
|
|
6
6
|
Author-email: Delamaro <delamaro@icmc.usp.br>
|
|
@@ -49,6 +49,10 @@ Dynamic: requires-python
|
|
|
49
49
|
|
|
50
50
|
> - Introduces the second argument for `mutagen` selection of mutant operatos.
|
|
51
51
|
|
|
52
|
+
> **V0.2.2**
|
|
53
|
+
|
|
54
|
+
> - Introduces argument `--assert` to enable mutation on assert statements.
|
|
55
|
+
|
|
52
56
|
---
|
|
53
57
|
|
|
54
58
|
## Features
|
|
@@ -170,6 +174,11 @@ Generate mutants for all operators:
|
|
|
170
174
|
python -m pyproteum mutagen --create --D /home/user/proteum foo_session
|
|
171
175
|
```
|
|
172
176
|
|
|
177
|
+
By default `assert` statements are not considered to generate mutants. This can be changed with `--assert` argument.
|
|
178
|
+
```bash
|
|
179
|
+
python -m pyproteum mutagen --create --D /home/user/proteum --assert foo_session
|
|
180
|
+
```
|
|
181
|
+
|
|
173
182
|
Generate only `orrn` mutants, with 50% random sampling:
|
|
174
183
|
```bash
|
|
175
184
|
python -m pyproteum mutagen --create --D /home/user/proteum --orrn 50 0 foo_session
|
|
@@ -34,6 +34,10 @@
|
|
|
34
34
|
|
|
35
35
|
> - Introduces the second argument for `mutagen` selection of mutant operatos.
|
|
36
36
|
|
|
37
|
+
> **V0.2.2**
|
|
38
|
+
|
|
39
|
+
> - Introduces argument `--assert` to enable mutation on assert statements.
|
|
40
|
+
|
|
37
41
|
---
|
|
38
42
|
|
|
39
43
|
## Features
|
|
@@ -155,6 +159,11 @@ Generate mutants for all operators:
|
|
|
155
159
|
python -m pyproteum mutagen --create --D /home/user/proteum foo_session
|
|
156
160
|
```
|
|
157
161
|
|
|
162
|
+
By default `assert` statements are not considered to generate mutants. This can be changed with `--assert` argument.
|
|
163
|
+
```bash
|
|
164
|
+
python -m pyproteum mutagen --create --D /home/user/proteum --assert foo_session
|
|
165
|
+
```
|
|
166
|
+
|
|
158
167
|
Generate only `orrn` mutants, with 50% random sampling:
|
|
159
168
|
```bash
|
|
160
169
|
python -m pyproteum mutagen --create --D /home/user/proteum --orrn 50 0 foo_session
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pyproteum"
|
|
7
|
-
version = "0.2"
|
|
7
|
+
version = "0.2.2"
|
|
8
8
|
description = "A tool for mutation testing in Python. Implemented as a Python module."
|
|
9
9
|
authors = [
|
|
10
10
|
{name = "Delamaro", email = "delamaro@icmc.usp.br"}
|
|
@@ -4,8 +4,8 @@ from pyproteum.moperators.myoperator import *
|
|
|
4
4
|
|
|
5
5
|
class Cccr(MyOperator):
|
|
6
6
|
|
|
7
|
-
def __init__(self, original,filename,max):
|
|
8
|
-
super().__init__(original, filename, max)
|
|
7
|
+
def __init__(self, original,filename,max, **kwargs):
|
|
8
|
+
super().__init__(original, filename, max, **kwargs)
|
|
9
9
|
self.seq = 1
|
|
10
10
|
self.const_set = list()
|
|
11
11
|
|
|
@@ -5,8 +5,8 @@ import copy
|
|
|
5
5
|
|
|
6
6
|
class Ccsr(MyOperator):
|
|
7
7
|
|
|
8
|
-
def __init__(self, original,filename,max):
|
|
9
|
-
super().__init__(original, filename, max)
|
|
8
|
+
def __init__(self, original,filename,max, **kwargs):
|
|
9
|
+
super().__init__(original, filename, max, **kwargs)
|
|
10
10
|
self.seq = 1
|
|
11
11
|
self.scalar_set = set()
|
|
12
12
|
ParentSetter().visit(self.original)
|
|
@@ -21,13 +21,15 @@ class Ccsr(MyOperator):
|
|
|
21
21
|
|
|
22
22
|
def visit_Name(self, node):
|
|
23
23
|
if isinstance(node.ctx, ast.Store) :
|
|
24
|
-
self.scalar_set
|
|
24
|
+
if not node.id in self.scalar_set:
|
|
25
|
+
self.scalar_set.add(node.id)
|
|
25
26
|
self.generic_visit(node)
|
|
26
27
|
return node
|
|
27
28
|
|
|
28
29
|
def visit_arg(self, node):
|
|
29
30
|
if node.arg != 'self':
|
|
30
|
-
self.scalar_set
|
|
31
|
+
if not node.arg in self.scalar_set:
|
|
32
|
+
self.scalar_set.add(node.arg)
|
|
31
33
|
self.generic_visit(node)
|
|
32
34
|
return node
|
|
33
35
|
|
|
@@ -5,8 +5,8 @@ from pyproteum.moperators.myoperator import *
|
|
|
5
5
|
|
|
6
6
|
class Crcr(MyOperator):
|
|
7
7
|
|
|
8
|
-
def __init__(self, original,filename,max):
|
|
9
|
-
super().__init__(original, filename, max)
|
|
8
|
+
def __init__(self, original,filename,max, **kwargs):
|
|
9
|
+
super().__init__(original, filename, max, **kwargs)
|
|
10
10
|
self.seq = 1
|
|
11
11
|
|
|
12
12
|
def visit_Constant(self, node):
|
|
@@ -6,7 +6,7 @@ from pyproteum.utiles import red,green
|
|
|
6
6
|
|
|
7
7
|
class MyOperator(ast.NodeTransformer):
|
|
8
8
|
|
|
9
|
-
def __init__(self, original,filename, max):
|
|
9
|
+
def __init__(self, original,filename, max, **kwargs):
|
|
10
10
|
self.original = copy.deepcopy(original)
|
|
11
11
|
self.not_changr_original = original
|
|
12
12
|
self.mutants = []
|
|
@@ -18,6 +18,7 @@ class MyOperator(ast.NodeTransformer):
|
|
|
18
18
|
self.filename = filename
|
|
19
19
|
self.max_muta_per_local = max
|
|
20
20
|
self.last_local = (-1,-1)
|
|
21
|
+
self.asserti = kwargs.get('doassert',False)
|
|
21
22
|
|
|
22
23
|
def pre_visit(self, tree):
|
|
23
24
|
for node in ast.walk(tree):
|
|
@@ -95,6 +96,11 @@ class MyOperator(ast.NodeTransformer):
|
|
|
95
96
|
self.func_lineno = old_l
|
|
96
97
|
return r
|
|
97
98
|
|
|
99
|
+
def visit_Assert(self, node):
|
|
100
|
+
if not self.asserti:
|
|
101
|
+
return node
|
|
102
|
+
return self.generic_visit(node)
|
|
103
|
+
|
|
98
104
|
def visit_Expr(self, node):
|
|
99
105
|
if id(node) in self.docstrings:
|
|
100
106
|
return node
|
|
@@ -21,8 +21,8 @@ ast.BitAnd(),
|
|
|
21
21
|
|
|
22
22
|
class Oaaa(MyOperator):
|
|
23
23
|
|
|
24
|
-
def __init__(self, original,filename,max):
|
|
25
|
-
super().__init__(original, filename, max)
|
|
24
|
+
def __init__(self, original,filename,max, **kwargs):
|
|
25
|
+
super().__init__(original, filename, max, **kwargs)
|
|
26
26
|
self.use = sorted(use, key=f)
|
|
27
27
|
self.seq = 1
|
|
28
28
|
|
|
@@ -21,8 +21,8 @@ ast.BitAnd(),
|
|
|
21
21
|
|
|
22
22
|
class Oaan(MyOperator):
|
|
23
23
|
|
|
24
|
-
def __init__(self, original,filename,max):
|
|
25
|
-
super().__init__(original, filename, max)
|
|
24
|
+
def __init__(self, original,filename,max, **kwargs):
|
|
25
|
+
super().__init__(original, filename, max, **kwargs)
|
|
26
26
|
self.use = sorted(use, key=f)
|
|
27
27
|
self.seq = 1
|
|
28
28
|
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
from pyproteum.moperators.myoperator import *
|
|
3
|
+
import copy
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Oeap(MyOperator):
|
|
7
|
+
|
|
8
|
+
def __init__(self, original,filename,max, **kwargs):
|
|
9
|
+
super().__init__(original, filename, max, **kwargs)
|
|
10
|
+
self.seq = 1
|
|
11
|
+
ParentSetter().visit(self.original)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def clone_node(self, new, old):
|
|
15
|
+
new.targets = [old.target]
|
|
16
|
+
new.value = old.value
|
|
17
|
+
ast.copy_location(new,old)
|
|
18
|
+
|
|
19
|
+
def visit_AugAssign(self, node):
|
|
20
|
+
p, fld, idx = node.parent, node.parent_field, node.parent_index
|
|
21
|
+
|
|
22
|
+
new_node = ast.Assign()
|
|
23
|
+
self.clone_node(new_node, node)
|
|
24
|
+
if idx is not None:
|
|
25
|
+
lst = getattr(p, fld)
|
|
26
|
+
lst[idx] = new_node
|
|
27
|
+
else:
|
|
28
|
+
setattr(p,fld, new_node)
|
|
29
|
+
self.salva_muta(new_node, self.function, self.func_lineno, self.func_end_lineno,seq=self.seq)
|
|
30
|
+
self.seq += 1
|
|
31
|
+
|
|
32
|
+
if idx is not None:
|
|
33
|
+
lst = getattr(p, fld)
|
|
34
|
+
lst[idx] = node
|
|
35
|
+
else:
|
|
36
|
+
setattr(p,fld, node)
|
|
37
|
+
|
|
38
|
+
self.generic_visit(node)
|
|
39
|
+
return node
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# use = [ast.Add(),
|
|
43
|
+
# ast.Sub(),
|
|
44
|
+
# ast.Mult(),
|
|
45
|
+
# ast.Div(),
|
|
46
|
+
# ast.FloorDiv(),
|
|
47
|
+
# ast.Mod(),
|
|
48
|
+
# ast.Pow(),
|
|
49
|
+
# ast.LShift(),
|
|
50
|
+
# ast.RShift(),
|
|
51
|
+
# ast.BitOr(),
|
|
52
|
+
# ast.BitXor(),
|
|
53
|
+
# ast.BitAnd(),
|
|
54
|
+
# ]
|
|
55
|
+
|
|
56
|
+
# class Oepa(MyOperator):
|
|
57
|
+
|
|
58
|
+
# def __init__(self, original,filename,max):
|
|
59
|
+
# super().__init__(original, filename, max)
|
|
60
|
+
# self.seq = 1
|
|
61
|
+
# self.scalar_set = set()
|
|
62
|
+
# ParentSetter().visit(self.original)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# def clone_node(self, new, old, op):
|
|
66
|
+
# new.target = old.targets[0]
|
|
67
|
+
# new.value = old.value
|
|
68
|
+
# new.op = op
|
|
69
|
+
# ast.copy_location(new,old)
|
|
70
|
+
|
|
71
|
+
# def visit_FunctionDef(self, node):
|
|
72
|
+
# old_set = set(self.scalar_set)
|
|
73
|
+
# super().visit_FunctionDef(node)
|
|
74
|
+
# self.scalar_set = old_set
|
|
75
|
+
# return node
|
|
76
|
+
|
|
77
|
+
# def visit_Name(self, node):
|
|
78
|
+
# if isinstance(node.ctx, ast.Store) :
|
|
79
|
+
# self.scalar_set.add(node.id)
|
|
80
|
+
# self.generic_visit(node)
|
|
81
|
+
# return node
|
|
82
|
+
|
|
83
|
+
# def visit_Assign(self, node):
|
|
84
|
+
# p, fld, idx = node.parent, node.parent_field, node.parent_index
|
|
85
|
+
|
|
86
|
+
# # não é possível mudar a = b = 10
|
|
87
|
+
# if len(node.targets) == 1 and isinstance(node.targets[0], (ast.Attribute,ast.Name) ):
|
|
88
|
+
# # só faz a mutação se a variável já foi definida
|
|
89
|
+
# for op in use:
|
|
90
|
+
# new_node = ast.AugAssign()
|
|
91
|
+
# self.clone_node(new_node, node, op)
|
|
92
|
+
# if idx is not None:
|
|
93
|
+
# lst = getattr(p, fld)
|
|
94
|
+
# lst[idx] = new_node
|
|
95
|
+
# else:
|
|
96
|
+
# setattr(p,fld, new_node)
|
|
97
|
+
# self.salva_muta(new_node, self.function, self.func_lineno, self.func_end_lineno,seq=self.seq)
|
|
98
|
+
# self.seq += 1
|
|
99
|
+
|
|
100
|
+
# if idx is not None:
|
|
101
|
+
# lst = getattr(p, fld)
|
|
102
|
+
# lst[idx] = node
|
|
103
|
+
# else:
|
|
104
|
+
# setattr(p,fld, node)
|
|
105
|
+
|
|
106
|
+
# self.generic_visit(node)
|
|
107
|
+
# return node
|
|
@@ -5,10 +5,9 @@ import copy
|
|
|
5
5
|
|
|
6
6
|
class Oodl(MyOperator):
|
|
7
7
|
|
|
8
|
-
def __init__(self, original,filename,max):
|
|
9
|
-
super().__init__(original, filename, max)
|
|
8
|
+
def __init__(self, original,filename,max, **kwargs):
|
|
9
|
+
super().__init__(original, filename, max, **kwargs)
|
|
10
10
|
self.seq = 1
|
|
11
|
-
self.scalar_set = set()
|
|
12
11
|
ParentSetter().visit(self.original)
|
|
13
12
|
|
|
14
13
|
|
|
@@ -9,8 +9,8 @@ use = [ast.Eq(), ast.NotEq(), ast.Lt(), ast.LtE(), ast.Gt(), ast.GtE()]
|
|
|
9
9
|
|
|
10
10
|
class Orrn(MyOperator):
|
|
11
11
|
|
|
12
|
-
def __init__(self, original,filename,max):
|
|
13
|
-
super().__init__(original, filename, max)
|
|
12
|
+
def __init__(self, original,filename,max, **kwargs):
|
|
13
|
+
super().__init__(original, filename, max, **kwargs)
|
|
14
14
|
self.use = sorted(use, key=f)
|
|
15
15
|
self.seq = 1
|
|
16
16
|
|
|
@@ -24,7 +24,6 @@ class Orrn(MyOperator):
|
|
|
24
24
|
|
|
25
25
|
for new_op in self.use:
|
|
26
26
|
node.ops[i] = new_op
|
|
27
|
-
#desloc = self.compute_len(op, new_op)
|
|
28
27
|
self.salva_muta(node, self.function, self.func_lineno, self.func_end_lineno,seq=self.seq)
|
|
29
28
|
self.seq += 1
|
|
30
29
|
self.use = sorted(use, key=f)
|
|
@@ -6,8 +6,8 @@ from pyproteum.moperators.myoperator import *
|
|
|
6
6
|
class Ssdl(MyOperator):
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
def __init__(self, original,filename,max):
|
|
10
|
-
super().__init__(original, filename, max)
|
|
9
|
+
def __init__(self, original,filename,max, **kwargs):
|
|
10
|
+
super().__init__(original, filename, max, **kwargs)
|
|
11
11
|
self.seq = 1
|
|
12
12
|
|
|
13
13
|
def generic_visit(self, node):
|
|
@@ -29,13 +29,14 @@ class Ssdl(MyOperator):
|
|
|
29
29
|
self.salva_muta(pass_node, self.function, self.func_lineno, self.func_end_lineno, self.seq)
|
|
30
30
|
value[k] = item
|
|
31
31
|
elif self._is_command(item):
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
if not (isinstance(item, ast.Assert) and not self.asserti):
|
|
33
|
+
pass_node = ast.Pass()
|
|
34
|
+
ast.copy_location(pass_node, item)
|
|
35
|
+
value[k] = pass_node
|
|
36
|
+
# self.show_node(pass_node)
|
|
37
|
+
# self.show_node(item)
|
|
38
|
+
self.salva_muta(pass_node, self.function, self.func_lineno, self.func_end_lineno, self.seq)
|
|
39
|
+
value[k] = item
|
|
39
40
|
self.seq += 1
|
|
40
41
|
self.visit(item)
|
|
41
42
|
|
|
@@ -38,6 +38,8 @@ def __create():
|
|
|
38
38
|
i = 2
|
|
39
39
|
ops = {}
|
|
40
40
|
percent = 100
|
|
41
|
+
|
|
42
|
+
assert_flag = False
|
|
41
43
|
while i < len(sys.argv[:-2]):
|
|
42
44
|
s = sys.argv[i]
|
|
43
45
|
match s:
|
|
@@ -74,6 +76,8 @@ def __create():
|
|
|
74
76
|
except:
|
|
75
77
|
usage()
|
|
76
78
|
return
|
|
79
|
+
case '--assert':
|
|
80
|
+
assert_flag = True
|
|
77
81
|
case _:
|
|
78
82
|
try:
|
|
79
83
|
i += 1
|
|
@@ -100,7 +104,7 @@ def __create():
|
|
|
100
104
|
for r in find_op(''):
|
|
101
105
|
ops[r['class']] = (100, r['max'])
|
|
102
106
|
|
|
103
|
-
muta_create(directory, session_name, ops)
|
|
107
|
+
muta_create(directory, session_name, ops,assert_flag)
|
|
104
108
|
|
|
105
109
|
|
|
106
110
|
def usage():
|
|
@@ -112,12 +116,12 @@ def usage():
|
|
|
112
116
|
print('\t--seed stablishes the seed for mutant sampling. Using the same seed generates the same mutants.')
|
|
113
117
|
sys.exit()
|
|
114
118
|
|
|
115
|
-
def muta_create(d, session_name, ops):
|
|
119
|
+
def muta_create(d, session_name, ops,assert_flag):
|
|
116
120
|
change_dir_connect(d, session_name)
|
|
117
121
|
|
|
118
122
|
ttotal = 0
|
|
119
123
|
for reg_session in Session:
|
|
120
|
-
mutants = apply_mutations(reg_session.filename, ops)
|
|
124
|
+
mutants = apply_mutations(reg_session.filename, ops,assert_flag)
|
|
121
125
|
print(green(f'Generated {len(mutants)} total mutants for file {reg_session.filename}'))
|
|
122
126
|
ttotal += len(mutants)
|
|
123
127
|
# print(mutants[-1])
|
|
@@ -159,7 +163,7 @@ def insert_db(muta, reg_session):
|
|
|
159
163
|
return
|
|
160
164
|
|
|
161
165
|
|
|
162
|
-
def apply_mutations(filename, oper_list):
|
|
166
|
+
def apply_mutations(filename, oper_list,assert_flag):
|
|
163
167
|
|
|
164
168
|
try:
|
|
165
169
|
with open(filename) as f:
|
|
@@ -178,7 +182,7 @@ def apply_mutations(filename, oper_list):
|
|
|
178
182
|
|
|
179
183
|
mutants = []
|
|
180
184
|
for op_class,(percentage,max) in oper_list.items():
|
|
181
|
-
op = op_class(tree, filename,max)
|
|
185
|
+
op = op_class(tree, filename,max,doassert=assert_flag)
|
|
182
186
|
print(f'Applying {str(op)}')
|
|
183
187
|
op.go_visit()
|
|
184
188
|
sampled = selecionar_percentual(op.mutants, percentage)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyproteum
|
|
3
|
-
Version: 0.2
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: A tool for mutation testing in Python. Implemented as a Python module.
|
|
5
5
|
Author: Delamaro
|
|
6
6
|
Author-email: Delamaro <delamaro@icmc.usp.br>
|
|
@@ -49,6 +49,10 @@ Dynamic: requires-python
|
|
|
49
49
|
|
|
50
50
|
> - Introduces the second argument for `mutagen` selection of mutant operatos.
|
|
51
51
|
|
|
52
|
+
> **V0.2.2**
|
|
53
|
+
|
|
54
|
+
> - Introduces argument `--assert` to enable mutation on assert statements.
|
|
55
|
+
|
|
52
56
|
---
|
|
53
57
|
|
|
54
58
|
## Features
|
|
@@ -170,6 +174,11 @@ Generate mutants for all operators:
|
|
|
170
174
|
python -m pyproteum mutagen --create --D /home/user/proteum foo_session
|
|
171
175
|
```
|
|
172
176
|
|
|
177
|
+
By default `assert` statements are not considered to generate mutants. This can be changed with `--assert` argument.
|
|
178
|
+
```bash
|
|
179
|
+
python -m pyproteum mutagen --create --D /home/user/proteum --assert foo_session
|
|
180
|
+
```
|
|
181
|
+
|
|
173
182
|
Generate only `orrn` mutants, with 50% random sampling:
|
|
174
183
|
```bash
|
|
175
184
|
python -m pyproteum mutagen --create --D /home/user/proteum --orrn 50 0 foo_session
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import ast
|
|
2
|
-
from pyproteum.moperators.myoperator import *
|
|
3
|
-
import copy
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class Oeap(MyOperator):
|
|
7
|
-
|
|
8
|
-
def __init__(self, original,filename,max):
|
|
9
|
-
super().__init__(original, filename, max)
|
|
10
|
-
self.seq = 1
|
|
11
|
-
ParentSetter().visit(self.original)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def clone_node(self, new, old):
|
|
15
|
-
new.targets = [old.target]
|
|
16
|
-
new.value = old.value
|
|
17
|
-
ast.copy_location(new,old)
|
|
18
|
-
|
|
19
|
-
def visit_AugAssign(self, node):
|
|
20
|
-
p, fld, idx = node.parent, node.parent_field, node.parent_index
|
|
21
|
-
|
|
22
|
-
new_node = ast.Assign()
|
|
23
|
-
self.clone_node(new_node, node)
|
|
24
|
-
if idx is not None:
|
|
25
|
-
lst = getattr(p, fld)
|
|
26
|
-
lst[idx] = new_node
|
|
27
|
-
else:
|
|
28
|
-
setattr(p,fld, new_node)
|
|
29
|
-
self.salva_muta(new_node, self.function, self.func_lineno, self.func_end_lineno,seq=self.seq)
|
|
30
|
-
self.seq += 1
|
|
31
|
-
|
|
32
|
-
if idx is not None:
|
|
33
|
-
lst = getattr(p, fld)
|
|
34
|
-
lst[idx] = node
|
|
35
|
-
else:
|
|
36
|
-
setattr(p,fld, node)
|
|
37
|
-
|
|
38
|
-
self.generic_visit(node)
|
|
39
|
-
return node
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
use = [ast.Add(),
|
|
43
|
-
ast.Sub(),
|
|
44
|
-
ast.Mult(),
|
|
45
|
-
ast.Div(),
|
|
46
|
-
ast.FloorDiv(),
|
|
47
|
-
ast.Mod(),
|
|
48
|
-
ast.Pow(),
|
|
49
|
-
ast.LShift(),
|
|
50
|
-
ast.RShift(),
|
|
51
|
-
ast.BitOr(),
|
|
52
|
-
ast.BitXor(),
|
|
53
|
-
ast.BitAnd(),
|
|
54
|
-
]
|
|
55
|
-
|
|
56
|
-
class Oepa(MyOperator):
|
|
57
|
-
|
|
58
|
-
def __init__(self, original,filename,max):
|
|
59
|
-
super().__init__(original, filename, max)
|
|
60
|
-
self.seq = 1
|
|
61
|
-
self.scalar_set = set()
|
|
62
|
-
ParentSetter().visit(self.original)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def clone_node(self, new, old, op):
|
|
66
|
-
new.target = old.targets[0]
|
|
67
|
-
new.value = old.value
|
|
68
|
-
new.op = op
|
|
69
|
-
ast.copy_location(new,old)
|
|
70
|
-
|
|
71
|
-
def visit_FunctionDef(self, node):
|
|
72
|
-
old_set = set(self.scalar_set)
|
|
73
|
-
super().visit_FunctionDef(node)
|
|
74
|
-
self.scalar_set = old_set
|
|
75
|
-
return node
|
|
76
|
-
|
|
77
|
-
def visit_Name(self, node):
|
|
78
|
-
if isinstance(node.ctx, ast.Store) :
|
|
79
|
-
self.scalar_set.add(node.id)
|
|
80
|
-
self.generic_visit(node)
|
|
81
|
-
return node
|
|
82
|
-
|
|
83
|
-
def visit_Assign(self, node):
|
|
84
|
-
p, fld, idx = node.parent, node.parent_field, node.parent_index
|
|
85
|
-
|
|
86
|
-
# não é possível mudar a = b = 10
|
|
87
|
-
if len(node.targets) == 1 and isinstance(node.targets[0], (ast.Attribute,ast.Name) ):
|
|
88
|
-
# só faz a mutação se a variável já foi definida
|
|
89
|
-
for op in use:
|
|
90
|
-
new_node = ast.AugAssign()
|
|
91
|
-
self.clone_node(new_node, node, op)
|
|
92
|
-
if idx is not None:
|
|
93
|
-
lst = getattr(p, fld)
|
|
94
|
-
lst[idx] = new_node
|
|
95
|
-
else:
|
|
96
|
-
setattr(p,fld, new_node)
|
|
97
|
-
self.salva_muta(new_node, self.function, self.func_lineno, self.func_end_lineno,seq=self.seq)
|
|
98
|
-
self.seq += 1
|
|
99
|
-
|
|
100
|
-
if idx is not None:
|
|
101
|
-
lst = getattr(p, fld)
|
|
102
|
-
lst[idx] = node
|
|
103
|
-
else:
|
|
104
|
-
setattr(p,fld, node)
|
|
105
|
-
|
|
106
|
-
self.generic_visit(node)
|
|
107
|
-
return node
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|