mutmut 3.3.1__tar.gz → 3.5.0__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.
- {mutmut-3.3.1 → mutmut-3.5.0}/HISTORY.rst +47 -1
- {mutmut-3.3.1/mutmut.egg-info → mutmut-3.5.0}/PKG-INFO +110 -37
- mutmut-3.3.1/PKG-INFO → mutmut-3.5.0/README.rst +85 -45
- mutmut-3.5.0/pyproject.toml +69 -0
- {mutmut-3.3.1 → mutmut-3.5.0/src}/mutmut/__init__.py +7 -4
- {mutmut-3.3.1 → mutmut-3.5.0/src}/mutmut/__main__.py +403 -125
- mutmut-3.5.0/src/mutmut/code_coverage.py +63 -0
- {mutmut-3.3.1 → mutmut-3.5.0/src}/mutmut/file_mutation.py +123 -17
- {mutmut-3.3.1 → mutmut-3.5.0/src}/mutmut/node_mutation.py +3 -0
- mutmut-3.5.0/src/mutmut/trampoline_templates.py +56 -0
- mutmut-3.5.0/src/mutmut/type_checking.py +98 -0
- mutmut-3.3.1/AUTHORS.rst +0 -29
- mutmut-3.3.1/MANIFEST.in +0 -6
- mutmut-3.3.1/README.rst +0 -216
- mutmut-3.3.1/mutmut/.DS_Store +0 -0
- mutmut-3.3.1/mutmut/__pycache__/__init__.cpython-311.pyc +0 -0
- mutmut-3.3.1/mutmut/__pycache__/__init__.cpython-312.pyc +0 -0
- mutmut-3.3.1/mutmut/__pycache__/__main__.cpython-311.pyc +0 -0
- mutmut-3.3.1/mutmut/__pycache__/__main__.cpython-312.pyc +0 -0
- mutmut-3.3.1/mutmut/__pycache__/file_mutation.cpython-312.pyc +0 -0
- mutmut-3.3.1/mutmut/__pycache__/node_mutation.cpython-312.pyc +0 -0
- mutmut-3.3.1/mutmut/__pycache__/trampoline_templates.cpython-312.pyc +0 -0
- mutmut-3.3.1/mutmut/trampoline_templates.py +0 -73
- mutmut-3.3.1/mutmut.egg-info/SOURCES.txt +0 -42
- mutmut-3.3.1/mutmut.egg-info/dependency_links.txt +0 -1
- mutmut-3.3.1/mutmut.egg-info/entry_points.txt +0 -2
- mutmut-3.3.1/mutmut.egg-info/not-zip-safe +0 -1
- mutmut-3.3.1/mutmut.egg-info/requires.txt +0 -8
- mutmut-3.3.1/mutmut.egg-info/top_level.txt +0 -2
- mutmut-3.3.1/requirements.txt +0 -7
- mutmut-3.3.1/setup.cfg +0 -19
- mutmut-3.3.1/setup.py +0 -112
- mutmut-3.3.1/tests/__init__.py +0 -0
- mutmut-3.3.1/tests/e2e/__init__.py +0 -0
- mutmut-3.3.1/tests/e2e/test_cli_version.py +0 -9
- mutmut-3.3.1/tests/e2e/test_e2e_result_snapshots.py +0 -80
- mutmut-3.3.1/tests/test_generation_error_handling.py +0 -35
- mutmut-3.3.1/tests/test_mutation.py +0 -710
- mutmut-3.3.1/tests/test_mutmut3.py +0 -74
- {mutmut-3.3.1 → mutmut-3.5.0}/LICENSE +0 -0
- {mutmut-3.3.1 → mutmut-3.5.0/src}/mutmut/result_browser_layout.tcss +0 -0
|
@@ -1,6 +1,52 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
---------
|
|
3
3
|
|
|
4
|
+
3.5.0
|
|
5
|
+
~~~~~
|
|
6
|
+
|
|
7
|
+
* Filter mutants based on type annotations. This feature needs to be turned on with the `type_check_command` config.
|
|
8
|
+
|
|
9
|
+
* Support running on Windows
|
|
10
|
+
|
|
11
|
+
* Save mutation stats for use with CI/CD pipeline (#460)
|
|
12
|
+
|
|
13
|
+
* Async functions fixed
|
|
14
|
+
|
|
15
|
+
* Fix for functions with positional only arguments
|
|
16
|
+
|
|
17
|
+
* Support signatures with PEP 649 deferred annotations
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
3.4.0
|
|
21
|
+
~~~~~
|
|
22
|
+
|
|
23
|
+
* Add action to view tests for mutant
|
|
24
|
+
|
|
25
|
+
* Add basic description for all results in mutmut browse
|
|
26
|
+
|
|
27
|
+
* Add description for timeout mutants
|
|
28
|
+
|
|
29
|
+
* Early exit when stats find no tests for any mutant
|
|
30
|
+
|
|
31
|
+
* Support python 3.14
|
|
32
|
+
|
|
33
|
+
* Performance improvements
|
|
34
|
+
|
|
35
|
+
* Fix `mutate_only_covered_lines` when files are excluded from test run
|
|
36
|
+
|
|
37
|
+
* Add `pytest_add_cli_args` and `pytest_add_cli_args_test_selection` configs
|
|
38
|
+
|
|
39
|
+
* `mutate_only_covered_lines` added to config to control whether coverage.py is used to filter down mutations
|
|
40
|
+
|
|
41
|
+
* Filter out identical string mutants with different values
|
|
42
|
+
|
|
43
|
+
* Handle more exit codes
|
|
44
|
+
|
|
45
|
+
* Disable common order-randomising pytest plugins, as that can seriously deteriorate mutation testing performance
|
|
46
|
+
|
|
47
|
+
* Fixed packaging issue
|
|
48
|
+
|
|
49
|
+
|
|
4
50
|
3.3.1
|
|
5
51
|
~~~~~
|
|
6
52
|
|
|
@@ -143,7 +189,7 @@ Changelog
|
|
|
143
189
|
3.0.0
|
|
144
190
|
~~~~~
|
|
145
191
|
|
|
146
|
-
* Execution model switched to mutation schemata, which enabled
|
|
192
|
+
* Execution model switched to mutation schemata, which enabled parallel execution.
|
|
147
193
|
|
|
148
194
|
* New terminal UI
|
|
149
195
|
|
|
@@ -1,26 +1,35 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: mutmut
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.5.0
|
|
4
4
|
Summary: mutation testing for Python 3
|
|
5
|
-
|
|
5
|
+
Keywords: mutmut,mutant,mutation,test,testing
|
|
6
6
|
Author: Anders Hovmöller
|
|
7
|
-
Author-email: boxed@killingar.net
|
|
8
|
-
License: BSD
|
|
9
|
-
|
|
7
|
+
Author-email: Anders Hovmöller <boxed@killingar.net>
|
|
8
|
+
License-Expression: BSD-3-Clause
|
|
9
|
+
License-File: LICENSE
|
|
10
10
|
Classifier: Development Status :: 4 - Beta
|
|
11
11
|
Classifier: Intended Audience :: Developers
|
|
12
|
-
Classifier: License :: OSI Approved :: BSD License
|
|
13
12
|
Classifier: Natural Language :: English
|
|
14
13
|
Classifier: Programming Language :: Python :: 3
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
Requires-Dist:
|
|
21
|
-
Requires-Dist:
|
|
22
|
-
Requires-Dist:
|
|
23
|
-
Requires-Dist: pytest
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Requires-Dist: click>=8.0.0
|
|
20
|
+
Requires-Dist: coverage>=7.3.0
|
|
21
|
+
Requires-Dist: libcst>=1.8.5
|
|
22
|
+
Requires-Dist: pytest>=6.2.5
|
|
23
|
+
Requires-Dist: setproctitle>=1.1.0
|
|
24
|
+
Requires-Dist: textual>=1.0.0
|
|
25
|
+
Requires-Dist: toml>=0.10.2 ; python_full_version < '3.11'
|
|
26
|
+
Requires-Python: >=3.10
|
|
27
|
+
Project-URL: Changelog, https://github.com/boxed/mutmut/blob/main/HISTORY.rst
|
|
28
|
+
Project-URL: Documentation, https://mutmut.readthedocs.io/en/latest/
|
|
29
|
+
Project-URL: Homepage, https://github.com/boxed/mutmut
|
|
30
|
+
Project-URL: Issues, https://github.com/boxed/mutmut/issues
|
|
31
|
+
Project-URL: Repository, https://github.com/boxed/mutmut
|
|
32
|
+
Description-Content-Type: text/x-rst
|
|
24
33
|
|
|
25
34
|
mutmut - python mutation tester
|
|
26
35
|
===============================
|
|
@@ -91,6 +100,20 @@ source code control and committed before you apply a mutant!
|
|
|
91
100
|
If during the installation you get an error for the `libcst` dependency mentioning the lack of a rust compiler on your system, it is because your architecture does not have a prebuilt binary for `libcst` and it requires both `rustc` and `cargo` from the [rust toolchain](https://www.rust-lang.org/tools/install) to be built. This is known for at least the `x86_64-darwin` architecture.
|
|
92
101
|
|
|
93
102
|
|
|
103
|
+
Wildcards for testing mutants
|
|
104
|
+
-----------------------------
|
|
105
|
+
|
|
106
|
+
Unix filename pattern matching style on mutants is supported. Example:
|
|
107
|
+
|
|
108
|
+
.. code-block:: console
|
|
109
|
+
|
|
110
|
+
mutmut run "my_module*"
|
|
111
|
+
mutmut run "my_module.my_function*"
|
|
112
|
+
|
|
113
|
+
In the `browse` TUI you can press `f` to retest a function, and `m` to retest
|
|
114
|
+
an entire module.
|
|
115
|
+
|
|
116
|
+
|
|
94
117
|
Configuration
|
|
95
118
|
-------------
|
|
96
119
|
|
|
@@ -100,7 +123,7 @@ In `setup.cfg` in the root of your project you can configure mutmut if you need
|
|
|
100
123
|
|
|
101
124
|
[mutmut]
|
|
102
125
|
paths_to_mutate=src/
|
|
103
|
-
|
|
126
|
+
pytest_add_cli_args_test_selection=tests/
|
|
104
127
|
|
|
105
128
|
If you use `pyproject.toml`, you must specify the paths as array in a `tool.mutmut` section:
|
|
106
129
|
|
|
@@ -108,27 +131,13 @@ If you use `pyproject.toml`, you must specify the paths as array in a `tool.mutm
|
|
|
108
131
|
|
|
109
132
|
[tool.mutmut]
|
|
110
133
|
paths_to_mutate = [ "src/" ]
|
|
111
|
-
|
|
134
|
+
pytest_add_cli_args_test_selection= [ "tests/" ]
|
|
112
135
|
|
|
113
136
|
See below for more options for configuring mutmut.
|
|
114
137
|
|
|
115
138
|
|
|
116
|
-
Wildcards for testing mutants
|
|
117
|
-
-----------------------------
|
|
118
|
-
|
|
119
|
-
Unix filename pattern matching style on mutants is supported. Example:
|
|
120
|
-
|
|
121
|
-
.. code-block:: console
|
|
122
|
-
|
|
123
|
-
mutmut run "my_module*"
|
|
124
|
-
mutmut run "my_module.my_function*"
|
|
125
|
-
|
|
126
|
-
In the `browse` TUI you can press `f` to retest a function, and `m` to retest
|
|
127
|
-
an entire module.
|
|
128
|
-
|
|
129
|
-
|
|
130
139
|
"also copy" files
|
|
131
|
-
|
|
140
|
+
~~~~~~~~~~~~~~~~~
|
|
132
141
|
|
|
133
142
|
To run the full test suite some files are often needed above the tests and the
|
|
134
143
|
source. You can configure to copy extra files that you need by adding
|
|
@@ -142,7 +151,7 @@ directories and files to `also_copy` in your `setup.cfg`:
|
|
|
142
151
|
|
|
143
152
|
|
|
144
153
|
Limit stack depth
|
|
145
|
-
|
|
154
|
+
~~~~~~~~~~~~~~~~~
|
|
146
155
|
|
|
147
156
|
In big code bases some functions are called incidentally by huge swaths of the
|
|
148
157
|
codebase, but you really don't want tests that hit those executions to count
|
|
@@ -166,7 +175,7 @@ caught.
|
|
|
166
175
|
|
|
167
176
|
|
|
168
177
|
Exclude files from mutation
|
|
169
|
-
|
|
178
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
170
179
|
|
|
171
180
|
You can exclude files from mutation in `setup.cfg`:
|
|
172
181
|
|
|
@@ -176,8 +185,51 @@ You can exclude files from mutation in `setup.cfg`:
|
|
|
176
185
|
*__tests.py
|
|
177
186
|
|
|
178
187
|
|
|
188
|
+
Enable coverage.py filtering of lines to mutate
|
|
189
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
190
|
+
|
|
191
|
+
By default, mutmut will mutate only functions that are called. But, if you would like a finer grained (line-level)
|
|
192
|
+
check for coverage, mutmut can use coverage.py to do that.
|
|
193
|
+
|
|
194
|
+
If you only want to mutate lines that are called (according to coverage.py), you can set
|
|
195
|
+
`mutate_only_covered_lines` to `true` in your configuration. The default value is `false`.
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
.. code-block::
|
|
199
|
+
|
|
200
|
+
mutate_only_covered_lines=true
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
Filter generated mutants with type checker
|
|
204
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
205
|
+
|
|
206
|
+
When your project is type checked using `mypy` or `pyrefly`, you can also use it to filter out invalid mutants.
|
|
207
|
+
For instance, mutmut mutates `x: str = 'foo'` to `x: str = None` which can easily caught by type checkers.
|
|
208
|
+
|
|
209
|
+
Using this filter can improve performance and reduce noise, however it can also hide a few relevant mutations:
|
|
210
|
+
|
|
211
|
+
1. `x: str = None` may not be valid, but if your tests do not detect such a change it indicates that
|
|
212
|
+
the value of `x` is not properly tested (even if your type checker would catch this particular modification)
|
|
213
|
+
2. In some edge cases with class properties (usually in the `__init__` method), the way `mypy` and `pyrefly` infer types does not work well
|
|
214
|
+
with the way mutmut mutates code. Some valid mutations like changing `self.x = 123` to `self.x = None` can
|
|
215
|
+
be filtered out, even though the may be valid.
|
|
216
|
+
|
|
217
|
+
To enable this filtering, configure the `type_check_command` to output json results as follows:
|
|
218
|
+
|
|
219
|
+
.. code-block::
|
|
220
|
+
|
|
221
|
+
# for pyrefly
|
|
222
|
+
type_check_command = ['pyrefly', 'check', '--output-format=json']
|
|
223
|
+
# for mypy
|
|
224
|
+
type_check_command = ['mypy', 'traces_parser', '--output', 'json']
|
|
225
|
+
|
|
226
|
+
Currently, only `pyrefly` and `mypy` are supported.
|
|
227
|
+
With `pyright` and `ty`, mutating a class method `Foo.bar()` can break the types of all methods of `Foo`,
|
|
228
|
+
and therefore mutmut cannot match the type error with the mutant that caused the type error.
|
|
229
|
+
|
|
230
|
+
|
|
179
231
|
Enable debug output (increase verbosity)
|
|
180
|
-
|
|
232
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
181
233
|
|
|
182
234
|
By default, mutmut "swallows" all the test output etc. so that you get a nice clean output.
|
|
183
235
|
|
|
@@ -191,7 +243,7 @@ to failing tests.
|
|
|
191
243
|
|
|
192
244
|
|
|
193
245
|
Whitelisting
|
|
194
|
-
|
|
246
|
+
~~~~~~~~~~~~
|
|
195
247
|
|
|
196
248
|
You can mark lines like this:
|
|
197
249
|
|
|
@@ -207,6 +259,27 @@ whitelist lines are:
|
|
|
207
259
|
to continue, but it's slower.
|
|
208
260
|
|
|
209
261
|
|
|
262
|
+
Modifying pytest arguments
|
|
263
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
264
|
+
|
|
265
|
+
You can add and override pytest arguments:
|
|
266
|
+
|
|
267
|
+
.. code-block:: python
|
|
268
|
+
|
|
269
|
+
# for CLI args that select or deselect tests, use `pytest_add_cli_args_test_selection`
|
|
270
|
+
pytest_add_cli_args_test_selection = ["-m", "not fail", "-k", "test_include"]
|
|
271
|
+
|
|
272
|
+
# for other CLI args, use `pytest_add_cli_args`
|
|
273
|
+
pytest_add_cli_args = ["-p", "no:some_plugin"] # disable a plugin
|
|
274
|
+
pytest_add_cli_args = ["-o", "xfail_strict=False"] # overrides xfail_strict from your normal config
|
|
275
|
+
|
|
276
|
+
# if you want to ignore the normal pytest configuration
|
|
277
|
+
# you can specify a diferent pytest ini file to be used
|
|
278
|
+
pytest_add_cli_args = ["-c", "mutmut_pytest.ini"]
|
|
279
|
+
also_copy = ["mutmut_pytest.ini"]
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
|
|
210
283
|
Example mutations
|
|
211
284
|
-----------------
|
|
212
285
|
|
|
@@ -1,27 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: mutmut
|
|
3
|
-
Version: 3.3.1
|
|
4
|
-
Summary: mutation testing for Python 3
|
|
5
|
-
Home-page: https://github.com/boxed/mutmut
|
|
6
|
-
Author: Anders Hovmöller
|
|
7
|
-
Author-email: boxed@killingar.net
|
|
8
|
-
License: BSD
|
|
9
|
-
Keywords: mutmut mutant mutation test testing
|
|
10
|
-
Classifier: Development Status :: 4 - Beta
|
|
11
|
-
Classifier: Intended Audience :: Developers
|
|
12
|
-
Classifier: License :: OSI Approved :: BSD License
|
|
13
|
-
Classifier: Natural Language :: English
|
|
14
|
-
Classifier: Programming Language :: Python :: 3
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
16
|
-
License-File: LICENSE
|
|
17
|
-
License-File: AUTHORS.rst
|
|
18
|
-
Requires-Dist: libcst~=1.7.0
|
|
19
|
-
Requires-Dist: click
|
|
20
|
-
Requires-Dist: setproctitle
|
|
21
|
-
Requires-Dist: textual
|
|
22
|
-
Requires-Dist: toml>=0.10.2; python_version < "3.11"
|
|
23
|
-
Requires-Dist: pytest
|
|
24
|
-
|
|
25
1
|
mutmut - python mutation tester
|
|
26
2
|
===============================
|
|
27
3
|
|
|
@@ -91,6 +67,20 @@ source code control and committed before you apply a mutant!
|
|
|
91
67
|
If during the installation you get an error for the `libcst` dependency mentioning the lack of a rust compiler on your system, it is because your architecture does not have a prebuilt binary for `libcst` and it requires both `rustc` and `cargo` from the [rust toolchain](https://www.rust-lang.org/tools/install) to be built. This is known for at least the `x86_64-darwin` architecture.
|
|
92
68
|
|
|
93
69
|
|
|
70
|
+
Wildcards for testing mutants
|
|
71
|
+
-----------------------------
|
|
72
|
+
|
|
73
|
+
Unix filename pattern matching style on mutants is supported. Example:
|
|
74
|
+
|
|
75
|
+
.. code-block:: console
|
|
76
|
+
|
|
77
|
+
mutmut run "my_module*"
|
|
78
|
+
mutmut run "my_module.my_function*"
|
|
79
|
+
|
|
80
|
+
In the `browse` TUI you can press `f` to retest a function, and `m` to retest
|
|
81
|
+
an entire module.
|
|
82
|
+
|
|
83
|
+
|
|
94
84
|
Configuration
|
|
95
85
|
-------------
|
|
96
86
|
|
|
@@ -100,7 +90,7 @@ In `setup.cfg` in the root of your project you can configure mutmut if you need
|
|
|
100
90
|
|
|
101
91
|
[mutmut]
|
|
102
92
|
paths_to_mutate=src/
|
|
103
|
-
|
|
93
|
+
pytest_add_cli_args_test_selection=tests/
|
|
104
94
|
|
|
105
95
|
If you use `pyproject.toml`, you must specify the paths as array in a `tool.mutmut` section:
|
|
106
96
|
|
|
@@ -108,27 +98,13 @@ If you use `pyproject.toml`, you must specify the paths as array in a `tool.mutm
|
|
|
108
98
|
|
|
109
99
|
[tool.mutmut]
|
|
110
100
|
paths_to_mutate = [ "src/" ]
|
|
111
|
-
|
|
101
|
+
pytest_add_cli_args_test_selection= [ "tests/" ]
|
|
112
102
|
|
|
113
103
|
See below for more options for configuring mutmut.
|
|
114
104
|
|
|
115
105
|
|
|
116
|
-
Wildcards for testing mutants
|
|
117
|
-
-----------------------------
|
|
118
|
-
|
|
119
|
-
Unix filename pattern matching style on mutants is supported. Example:
|
|
120
|
-
|
|
121
|
-
.. code-block:: console
|
|
122
|
-
|
|
123
|
-
mutmut run "my_module*"
|
|
124
|
-
mutmut run "my_module.my_function*"
|
|
125
|
-
|
|
126
|
-
In the `browse` TUI you can press `f` to retest a function, and `m` to retest
|
|
127
|
-
an entire module.
|
|
128
|
-
|
|
129
|
-
|
|
130
106
|
"also copy" files
|
|
131
|
-
|
|
107
|
+
~~~~~~~~~~~~~~~~~
|
|
132
108
|
|
|
133
109
|
To run the full test suite some files are often needed above the tests and the
|
|
134
110
|
source. You can configure to copy extra files that you need by adding
|
|
@@ -142,7 +118,7 @@ directories and files to `also_copy` in your `setup.cfg`:
|
|
|
142
118
|
|
|
143
119
|
|
|
144
120
|
Limit stack depth
|
|
145
|
-
|
|
121
|
+
~~~~~~~~~~~~~~~~~
|
|
146
122
|
|
|
147
123
|
In big code bases some functions are called incidentally by huge swaths of the
|
|
148
124
|
codebase, but you really don't want tests that hit those executions to count
|
|
@@ -166,7 +142,7 @@ caught.
|
|
|
166
142
|
|
|
167
143
|
|
|
168
144
|
Exclude files from mutation
|
|
169
|
-
|
|
145
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
170
146
|
|
|
171
147
|
You can exclude files from mutation in `setup.cfg`:
|
|
172
148
|
|
|
@@ -176,8 +152,51 @@ You can exclude files from mutation in `setup.cfg`:
|
|
|
176
152
|
*__tests.py
|
|
177
153
|
|
|
178
154
|
|
|
155
|
+
Enable coverage.py filtering of lines to mutate
|
|
156
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
157
|
+
|
|
158
|
+
By default, mutmut will mutate only functions that are called. But, if you would like a finer grained (line-level)
|
|
159
|
+
check for coverage, mutmut can use coverage.py to do that.
|
|
160
|
+
|
|
161
|
+
If you only want to mutate lines that are called (according to coverage.py), you can set
|
|
162
|
+
`mutate_only_covered_lines` to `true` in your configuration. The default value is `false`.
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
.. code-block::
|
|
166
|
+
|
|
167
|
+
mutate_only_covered_lines=true
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
Filter generated mutants with type checker
|
|
171
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
172
|
+
|
|
173
|
+
When your project is type checked using `mypy` or `pyrefly`, you can also use it to filter out invalid mutants.
|
|
174
|
+
For instance, mutmut mutates `x: str = 'foo'` to `x: str = None` which can easily caught by type checkers.
|
|
175
|
+
|
|
176
|
+
Using this filter can improve performance and reduce noise, however it can also hide a few relevant mutations:
|
|
177
|
+
|
|
178
|
+
1. `x: str = None` may not be valid, but if your tests do not detect such a change it indicates that
|
|
179
|
+
the value of `x` is not properly tested (even if your type checker would catch this particular modification)
|
|
180
|
+
2. In some edge cases with class properties (usually in the `__init__` method), the way `mypy` and `pyrefly` infer types does not work well
|
|
181
|
+
with the way mutmut mutates code. Some valid mutations like changing `self.x = 123` to `self.x = None` can
|
|
182
|
+
be filtered out, even though the may be valid.
|
|
183
|
+
|
|
184
|
+
To enable this filtering, configure the `type_check_command` to output json results as follows:
|
|
185
|
+
|
|
186
|
+
.. code-block::
|
|
187
|
+
|
|
188
|
+
# for pyrefly
|
|
189
|
+
type_check_command = ['pyrefly', 'check', '--output-format=json']
|
|
190
|
+
# for mypy
|
|
191
|
+
type_check_command = ['mypy', 'traces_parser', '--output', 'json']
|
|
192
|
+
|
|
193
|
+
Currently, only `pyrefly` and `mypy` are supported.
|
|
194
|
+
With `pyright` and `ty`, mutating a class method `Foo.bar()` can break the types of all methods of `Foo`,
|
|
195
|
+
and therefore mutmut cannot match the type error with the mutant that caused the type error.
|
|
196
|
+
|
|
197
|
+
|
|
179
198
|
Enable debug output (increase verbosity)
|
|
180
|
-
|
|
199
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
181
200
|
|
|
182
201
|
By default, mutmut "swallows" all the test output etc. so that you get a nice clean output.
|
|
183
202
|
|
|
@@ -191,7 +210,7 @@ to failing tests.
|
|
|
191
210
|
|
|
192
211
|
|
|
193
212
|
Whitelisting
|
|
194
|
-
|
|
213
|
+
~~~~~~~~~~~~
|
|
195
214
|
|
|
196
215
|
You can mark lines like this:
|
|
197
216
|
|
|
@@ -207,6 +226,27 @@ whitelist lines are:
|
|
|
207
226
|
to continue, but it's slower.
|
|
208
227
|
|
|
209
228
|
|
|
229
|
+
Modifying pytest arguments
|
|
230
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
231
|
+
|
|
232
|
+
You can add and override pytest arguments:
|
|
233
|
+
|
|
234
|
+
.. code-block:: python
|
|
235
|
+
|
|
236
|
+
# for CLI args that select or deselect tests, use `pytest_add_cli_args_test_selection`
|
|
237
|
+
pytest_add_cli_args_test_selection = ["-m", "not fail", "-k", "test_include"]
|
|
238
|
+
|
|
239
|
+
# for other CLI args, use `pytest_add_cli_args`
|
|
240
|
+
pytest_add_cli_args = ["-p", "no:some_plugin"] # disable a plugin
|
|
241
|
+
pytest_add_cli_args = ["-o", "xfail_strict=False"] # overrides xfail_strict from your normal config
|
|
242
|
+
|
|
243
|
+
# if you want to ignore the normal pytest configuration
|
|
244
|
+
# you can specify a diferent pytest ini file to be used
|
|
245
|
+
pytest_add_cli_args = ["-c", "mutmut_pytest.ini"]
|
|
246
|
+
also_copy = ["mutmut_pytest.ini"]
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
|
|
210
250
|
Example mutations
|
|
211
251
|
-----------------
|
|
212
252
|
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "mutmut"
|
|
3
|
+
version = "3.5.0"
|
|
4
|
+
description = "mutation testing for Python 3"
|
|
5
|
+
keywords = ["mutmut", "mutant", "mutation", "test", "testing"]
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "Anders Hovmöller", email = "boxed@killingar.net" },
|
|
8
|
+
]
|
|
9
|
+
requires-python = ">=3.10"
|
|
10
|
+
readme = "README.rst"
|
|
11
|
+
license = "BSD-3-Clause"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"Natural Language :: English",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Programming Language :: Python :: 3.14",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
dependencies = [
|
|
27
|
+
"click>=8.0.0",
|
|
28
|
+
"coverage>=7.3.0",
|
|
29
|
+
"libcst>=1.8.5",
|
|
30
|
+
"pytest>=6.2.5",
|
|
31
|
+
"setproctitle>=1.1.0",
|
|
32
|
+
"textual>=1.0.0",
|
|
33
|
+
"toml>=0.10.2 ; python_full_version < '3.11'",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
Homepage = "https://github.com/boxed/mutmut"
|
|
38
|
+
Documentation = "https://mutmut.readthedocs.io/en/latest/"
|
|
39
|
+
Repository = "https://github.com/boxed/mutmut"
|
|
40
|
+
Issues = "https://github.com/boxed/mutmut/issues"
|
|
41
|
+
Changelog = "https://github.com/boxed/mutmut/blob/main/HISTORY.rst"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
[project.scripts]
|
|
45
|
+
mutmut = "mutmut.__main__:cli"
|
|
46
|
+
|
|
47
|
+
[build-system]
|
|
48
|
+
requires = ["uv_build>=0.9.5,<0.10.0"]
|
|
49
|
+
build-backend = "uv_build"
|
|
50
|
+
|
|
51
|
+
[tool.uv.build-backend]
|
|
52
|
+
source-include = ["HISTORY.rst"]
|
|
53
|
+
|
|
54
|
+
[dependency-groups]
|
|
55
|
+
dev = [
|
|
56
|
+
"inline-snapshot>=0.32.0",
|
|
57
|
+
"pyrefly>=0.53.0",
|
|
58
|
+
"pytest-asyncio>=1.0.0",
|
|
59
|
+
"ruff>=0.15.1",
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
[tool.pytest.ini_options]
|
|
63
|
+
testpaths = [
|
|
64
|
+
"tests",
|
|
65
|
+
]
|
|
66
|
+
asyncio_default_fixture_loop_scope = "function"
|
|
67
|
+
|
|
68
|
+
[tool.inline-snapshot]
|
|
69
|
+
format-command="ruff format --stdin-filename {filename}"
|
|
@@ -1,21 +1,24 @@
|
|
|
1
|
+
import importlib.metadata
|
|
1
2
|
from collections import defaultdict
|
|
2
3
|
|
|
3
|
-
__version__ =
|
|
4
|
+
__version__ = importlib.metadata.version("mutmut")
|
|
4
5
|
|
|
5
6
|
|
|
6
|
-
duration_by_test =
|
|
7
|
+
duration_by_test = defaultdict(float)
|
|
7
8
|
stats_time = None
|
|
8
9
|
config = None
|
|
9
10
|
|
|
10
11
|
_stats = set()
|
|
11
12
|
tests_by_mangled_function_name = defaultdict(set)
|
|
12
|
-
|
|
13
|
+
_covered_lines = None
|
|
13
14
|
|
|
14
15
|
def _reset_globals():
|
|
15
16
|
global duration_by_test, stats_time, config, _stats, tests_by_mangled_function_name
|
|
17
|
+
global _covered_lines
|
|
16
18
|
|
|
17
|
-
duration_by_test
|
|
19
|
+
duration_by_test.clear()
|
|
18
20
|
stats_time = None
|
|
19
21
|
config = None
|
|
20
22
|
_stats = set()
|
|
21
23
|
tests_by_mangled_function_name = defaultdict(set)
|
|
24
|
+
_covered_lines = None
|