mutant 0.9.10 → 0.10.0
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.
- checksums.yaml +4 -4
- data/bin/mutant +16 -11
- data/lib/mutant.rb +8 -4
- data/lib/mutant/bootstrap.rb +14 -1
- data/lib/mutant/cli.rb +9 -162
- data/lib/mutant/cli/command.rb +196 -0
- data/lib/mutant/cli/command/root.rb +13 -0
- data/lib/mutant/cli/command/run.rb +151 -0
- data/lib/mutant/cli/command/subscription.rb +54 -0
- data/lib/mutant/expression.rb +0 -1
- data/lib/mutant/isolation.rb +1 -1
- data/lib/mutant/isolation/fork.rb +2 -2
- data/lib/mutant/isolation/none.rb +1 -1
- data/lib/mutant/license.rb +9 -35
- data/lib/mutant/license/subscription.rb +31 -9
- data/lib/mutant/license/subscription/commercial.rb +2 -4
- data/lib/mutant/license/subscription/opensource.rb +7 -7
- data/lib/mutant/matcher/config.rb +2 -0
- data/lib/mutant/meta/example.rb +16 -4
- data/lib/mutant/meta/example/dsl.rb +33 -16
- data/lib/mutant/meta/example/verification.rb +70 -28
- data/lib/mutant/minitest/coverage.rb +53 -0
- data/lib/mutant/mutator/node.rb +2 -2
- data/lib/mutant/mutator/node/block_pass.rb +29 -0
- data/lib/mutant/mutator/node/{dstr.rb → dynamic_literal.rb} +7 -5
- data/lib/mutant/mutator/node/index.rb +4 -4
- data/lib/mutant/mutator/node/literal/range.rb +5 -2
- data/lib/mutant/mutator/node/named_value/variable_assignment.rb +1 -1
- data/lib/mutant/mutator/node/noop.rb +1 -1
- data/lib/mutant/mutator/node/op_asgn.rb +15 -1
- data/lib/mutant/mutator/node/send.rb +25 -1
- data/lib/mutant/mutator/node/send/attribute_assignment.rb +1 -0
- data/lib/mutant/reporter/cli/printer/isolation_result.rb +9 -3
- data/lib/mutant/subject/method/instance.rb +1 -1
- data/lib/mutant/version.rb +1 -1
- metadata +18 -336
- data/.github/workflows/ci.yml +0 -121
- data/.gitignore +0 -38
- data/.rspec +0 -5
- data/.rubocop.yml +0 -210
- data/Changelog.md +0 -87
- data/Gemfile +0 -7
- data/Gemfile.lock +0 -107
- data/Gemfile.shared +0 -10
- data/README.md +0 -199
- data/Rakefile +0 -5
- data/config/devtools.yml +0 -2
- data/config/reek.yml +0 -139
- data/config/yardstick.yml +0 -2
- data/docs/commercial-support.md +0 -14
- data/docs/concurrency.md +0 -39
- data/docs/incremental.md +0 -76
- data/docs/known-problems.md +0 -30
- data/docs/limitations.md +0 -50
- data/docs/mutant-minitest.md +0 -149
- data/docs/mutant-rspec.md +0 -130
- data/docs/nomenclature.md +0 -82
- data/docs/reading-reports.md +0 -74
- data/lib/mutant/mutator/node/dsym.rb +0 -22
- data/meta/and.rb +0 -13
- data/meta/and_asgn.rb +0 -14
- data/meta/array.rb +0 -27
- data/meta/begin.rb +0 -20
- data/meta/block.rb +0 -199
- data/meta/block_pass.rb +0 -8
- data/meta/blockarg.rb +0 -10
- data/meta/break.rb +0 -9
- data/meta/case.rb +0 -217
- data/meta/casgn.rb +0 -25
- data/meta/cbase.rb +0 -8
- data/meta/class.rb +0 -12
- data/meta/const.rb +0 -17
- data/meta/csend.rb +0 -10
- data/meta/cvar.rb +0 -7
- data/meta/cvasgn.rb +0 -9
- data/meta/date.rb +0 -59
- data/meta/def.rb +0 -196
- data/meta/defined.rb +0 -9
- data/meta/dstr.rb +0 -13
- data/meta/dsym.rb +0 -14
- data/meta/ensure.rb +0 -8
- data/meta/false.rb +0 -7
- data/meta/file.rb +0 -5
- data/meta/float.rb +0 -37
- data/meta/gvar.rb +0 -7
- data/meta/gvasgn.rb +0 -9
- data/meta/hash.rb +0 -20
- data/meta/if.rb +0 -72
- data/meta/index.rb +0 -133
- data/meta/indexasgn.rb +0 -31
- data/meta/int.rb +0 -18
- data/meta/ivar.rb +0 -8
- data/meta/ivasgn.rb +0 -22
- data/meta/kwarg.rb +0 -10
- data/meta/kwbegin.rb +0 -8
- data/meta/kwoptarg.rb +0 -13
- data/meta/lambda.rb +0 -23
- data/meta/line.rb +0 -5
- data/meta/lvar.rb +0 -16
- data/meta/lvasgn.rb +0 -24
- data/meta/masgn.rb +0 -7
- data/meta/match_current_line.rb +0 -14
- data/meta/next.rb +0 -10
- data/meta/nil.rb +0 -5
- data/meta/nthref.rb +0 -14
- data/meta/op_assgn.rb +0 -17
- data/meta/or.rb +0 -13
- data/meta/or_asgn.rb +0 -50
- data/meta/range.rb +0 -65
- data/meta/redo.rb +0 -5
- data/meta/regexp.rb +0 -80
- data/meta/regopt.rb +0 -10
- data/meta/rescue.rb +0 -84
- data/meta/return.rb +0 -16
- data/meta/sclass.rb +0 -12
- data/meta/self.rb +0 -7
- data/meta/send.rb +0 -600
- data/meta/str.rb +0 -7
- data/meta/super.rb +0 -27
- data/meta/sym.rb +0 -8
- data/meta/true.rb +0 -7
- data/meta/until.rb +0 -16
- data/meta/while.rb +0 -24
- data/meta/yield.rb +0 -9
- data/mutant-minitest.gemspec +0 -22
- data/mutant-rspec.gemspec +0 -22
- data/mutant.gemspec +0 -44
- data/mutant.sh +0 -12
- data/mutant.yml +0 -6
- data/spec/integration/mutant/corpus_spec.rb +0 -15
- data/spec/integration/mutant/isolation/fork_spec.rb +0 -28
- data/spec/integration/mutant/minitest_spec.rb +0 -11
- data/spec/integration/mutant/null_spec.rb +0 -16
- data/spec/integration/mutant/rspec_spec.rb +0 -15
- data/spec/integration/mutant/test_mutator_handles_types_spec.rb +0 -9
- data/spec/integrations.yml +0 -63
- data/spec/shared/framework_integration_behavior.rb +0 -70
- data/spec/shared/method_matcher_behavior.rb +0 -47
- data/spec/spec_helper.rb +0 -90
- data/spec/support/corpus.rb +0 -318
- data/spec/support/file_system.rb +0 -62
- data/spec/support/ice_nine_config.rb +0 -10
- data/spec/support/ruby_vm.rb +0 -84
- data/spec/support/shared_context.rb +0 -169
- data/spec/support/xspec.rb +0 -183
- data/spec/unit/mutant/ast/find_metaclass_containing_spec.rb +0 -64
- data/spec/unit/mutant/ast/meta/optarg_spec.rb +0 -24
- data/spec/unit/mutant/ast/meta/send/proc_predicate_spec.rb +0 -30
- data/spec/unit/mutant/ast/meta/send/receiver_possible_top_level_const_predicate_spec.rb +0 -39
- data/spec/unit/mutant/ast/meta/send_spec.rb +0 -42
- data/spec/unit/mutant/ast/named_children_spec.rb +0 -89
- data/spec/unit/mutant/ast/sexp_spec.rb +0 -38
- data/spec/unit/mutant/ast_spec.rb +0 -57
- data/spec/unit/mutant/bootstrap_spec.rb +0 -216
- data/spec/unit/mutant/cli_spec.rb +0 -305
- data/spec/unit/mutant/clock_monotonic_spec.rb +0 -52
- data/spec/unit/mutant/config_spec.rb +0 -126
- data/spec/unit/mutant/context_spec.rb +0 -111
- data/spec/unit/mutant/env_spec.rb +0 -229
- data/spec/unit/mutant/expression/method_spec.rb +0 -62
- data/spec/unit/mutant/expression/methods_spec.rb +0 -66
- data/spec/unit/mutant/expression/namespace/exact_spec.rb +0 -28
- data/spec/unit/mutant/expression/namespace/recursive_spec.rb +0 -66
- data/spec/unit/mutant/expression/parser_spec.rb +0 -65
- data/spec/unit/mutant/expression_spec.rb +0 -45
- data/spec/unit/mutant/integration/rspec_spec.rb +0 -201
- data/spec/unit/mutant/integration_spec.rb +0 -150
- data/spec/unit/mutant/isolation/fork_spec.rb +0 -309
- data/spec/unit/mutant/isolation/none_spec.rb +0 -23
- data/spec/unit/mutant/isolation/result_spec.rb +0 -73
- data/spec/unit/mutant/license_spec.rb +0 -305
- data/spec/unit/mutant/loader_spec.rb +0 -79
- data/spec/unit/mutant/matcher/chain_spec.rb +0 -26
- data/spec/unit/mutant/matcher/compiler_spec.rb +0 -0
- data/spec/unit/mutant/matcher/config_spec.rb +0 -47
- data/spec/unit/mutant/matcher/filter_spec.rb +0 -22
- data/spec/unit/mutant/matcher/method/instance_spec.rb +0 -164
- data/spec/unit/mutant/matcher/method/metaclass_spec.rb +0 -108
- data/spec/unit/mutant/matcher/method/singleton_spec.rb +0 -90
- data/spec/unit/mutant/matcher/methods/instance_spec.rb +0 -54
- data/spec/unit/mutant/matcher/methods/metaclass_spec.rb +0 -62
- data/spec/unit/mutant/matcher/methods/singleton_spec.rb +0 -51
- data/spec/unit/mutant/matcher/namespace_spec.rb +0 -39
- data/spec/unit/mutant/matcher/null_spec.rb +0 -12
- data/spec/unit/mutant/matcher/scope_spec.rb +0 -45
- data/spec/unit/mutant/matcher/static_spec.rb +0 -13
- data/spec/unit/mutant/matcher_spec.rb +0 -102
- data/spec/unit/mutant/meta/example/dsl_spec.rb +0 -108
- data/spec/unit/mutant/meta/example/verification_spec.rb +0 -154
- data/spec/unit/mutant/meta/example_spec.rb +0 -34
- data/spec/unit/mutant/mutation_spec.rb +0 -140
- data/spec/unit/mutant/mutator/node_spec.rb +0 -47
- data/spec/unit/mutant/mutator_spec.rb +0 -21
- data/spec/unit/mutant/parallel/driver_spec.rb +0 -126
- data/spec/unit/mutant/parallel/source/array_spec.rb +0 -57
- data/spec/unit/mutant/parallel/worker_spec.rb +0 -206
- data/spec/unit/mutant/parallel_spec.rb +0 -115
- data/spec/unit/mutant/parser_spec.rb +0 -26
- data/spec/unit/mutant/range_spec.rb +0 -141
- data/spec/unit/mutant/registry_spec.rb +0 -74
- data/spec/unit/mutant/reporter/cli/printer/config_spec.rb +0 -17
- data/spec/unit/mutant/reporter/cli/printer/env_progress_spec.rb +0 -85
- data/spec/unit/mutant/reporter/cli/printer/env_result_spec.rb +0 -45
- data/spec/unit/mutant/reporter/cli/printer/isolation_result_spec.rb +0 -132
- data/spec/unit/mutant/reporter/cli/printer/mutation_progress_result_spec.rb +0 -25
- data/spec/unit/mutant/reporter/cli/printer/mutation_result_spec.rb +0 -153
- data/spec/unit/mutant/reporter/cli/printer/status_progressive_spec.rb +0 -45
- data/spec/unit/mutant/reporter/cli/printer/subject_progress_spec.rb +0 -36
- data/spec/unit/mutant/reporter/cli/printer/subject_result_spec.rb +0 -44
- data/spec/unit/mutant/reporter/cli/printer/test_result_spec.rb +0 -16
- data/spec/unit/mutant/reporter/cli/printer_spec.rb +0 -163
- data/spec/unit/mutant/reporter/cli_spec.rb +0 -137
- data/spec/unit/mutant/reporter/null_spec.rb +0 -14
- data/spec/unit/mutant/reporter/sequence_spec.rb +0 -31
- data/spec/unit/mutant/repository/diff/ranges_spec.rb +0 -180
- data/spec/unit/mutant/repository/diff_spec.rb +0 -122
- data/spec/unit/mutant/repository/subject_filter_spec.rb +0 -30
- data/spec/unit/mutant/require_highjack_spec.rb +0 -73
- data/spec/unit/mutant/result/class_methods_spec.rb +0 -51
- data/spec/unit/mutant/result/env_spec.rb +0 -161
- data/spec/unit/mutant/result/mutation_spec.rb +0 -70
- data/spec/unit/mutant/result/subject_spec.rb +0 -111
- data/spec/unit/mutant/result/test_spec.rb +0 -14
- data/spec/unit/mutant/result_spec.rb +0 -33
- data/spec/unit/mutant/runner/sink_spec.rb +0 -174
- data/spec/unit/mutant/runner_spec.rb +0 -121
- data/spec/unit/mutant/selector/expression_spec.rb +0 -62
- data/spec/unit/mutant/selector/null_spec.rb +0 -17
- data/spec/unit/mutant/subject/method/instance_spec.rb +0 -276
- data/spec/unit/mutant/subject/method/metaclass_spec.rb +0 -63
- data/spec/unit/mutant/subject/method/singleton_spec.rb +0 -61
- data/spec/unit/mutant/subject_spec.rb +0 -93
- data/spec/unit/mutant/transform/array_spec.rb +0 -92
- data/spec/unit/mutant/transform/bool_spec.rb +0 -63
- data/spec/unit/mutant/transform/error_spec.rb +0 -132
- data/spec/unit/mutant/transform/exception_spec.rb +0 -44
- data/spec/unit/mutant/transform/hash_spec.rb +0 -236
- data/spec/unit/mutant/transform/index_spec.rb +0 -92
- data/spec/unit/mutant/transform/named_spec.rb +0 -49
- data/spec/unit/mutant/transform/primitive_spec.rb +0 -56
- data/spec/unit/mutant/transform/sequence_spec.rb +0 -98
- data/spec/unit/mutant/util/one_spec.rb +0 -22
- data/spec/unit/mutant/warnings_spec.rb +0 -89
- data/spec/unit/mutant/world_spec.rb +0 -63
- data/spec/unit/mutant/zombifier_spec.rb +0 -122
- data/test_app/.rspec +0 -1
- data/test_app/Gemfile.minitest +0 -6
- data/test_app/Gemfile.rspec3.8 +0 -7
- data/test_app/lib/test_app.rb +0 -114
- data/test_app/lib/test_app/literal.rb +0 -35
- data/test_app/lib/test_app/metaclasses.rb +0 -108
- data/test_app/spec/spec_helper.rb +0 -9
- data/test_app/spec/unit/test_app/literal_spec.rb +0 -20
- data/test_app/test/unit/test_app/literal_test.rb +0 -16
data/config/yardstick.yml
DELETED
data/docs/commercial-support.md
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
# Commercial Support
|
2
|
-
|
3
|
-
Mutant offers only community support.
|
4
|
-
|
5
|
-
Commercial license customers are entited to priority support via email.
|
6
|
-
|
7
|
-
## Priority Support
|
8
|
-
|
9
|
-
Covers 1 incident per quarter, with a max response time of 7 days.
|
10
|
-
Scope is limited to mutant not the application or infrastructure.
|
11
|
-
|
12
|
-
For support email [Markus Schirp](mailto:mbj@schirp-dso.com?subject=Mutant%20Support).
|
13
|
-
Please email using the same domain as the roiginal license email or explain
|
14
|
-
your connection to the license.
|
data/docs/concurrency.md
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
Concurrency
|
2
|
-
===========
|
3
|
-
|
4
|
-
By default, mutant will test mutations in parallel by running up
|
5
|
-
to one process for each core on your system. You can control the
|
6
|
-
number of processes created using the `-j/--jobs` argument.
|
7
|
-
|
8
|
-
Mutant forks a new process for each mutation to be tested to prevent side
|
9
|
-
affects in your specs and the lack of thread safety in integrations from
|
10
|
-
impacting the results.
|
11
|
-
|
12
|
-
Database
|
13
|
-
--------
|
14
|
-
|
15
|
-
If the code under test relies on a database, you may experience problems
|
16
|
-
when running mutant because of conflicting data in the database. For
|
17
|
-
example, if you have a test like this:
|
18
|
-
|
19
|
-
```ruby
|
20
|
-
resource = MyModel.create!(...)
|
21
|
-
expect(MyModel.first.name).to eql(resource.name)
|
22
|
-
```
|
23
|
-
|
24
|
-
It might fail if some other test wrote a record to the `MyModel` table
|
25
|
-
at the same time as this test was executed. (It would find the MyModel
|
26
|
-
record created by the other test.) Most of these issues can be fixed
|
27
|
-
by writing more specific tests. Here is a concurrent safe version of
|
28
|
-
the same test:
|
29
|
-
|
30
|
-
```
|
31
|
-
resource = MyModel.create!(...)
|
32
|
-
expect(MyModel.find_by_id(m.id).name).to eql(resource.name)
|
33
|
-
```
|
34
|
-
|
35
|
-
An alternative is to try wrapping each test into an enclosing transaction.
|
36
|
-
|
37
|
-
Note that some databases, SQLite in particular, are not designed for
|
38
|
-
concurrent access and will fail if used in this manner. If you are
|
39
|
-
using SQLite, you should set the `--jobs` to 1.
|
data/docs/incremental.md
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
# Incremental mutation testing
|
2
|
-
|
3
|
-
Incremental mutation testing allows you to significantly speed up mutation
|
4
|
-
analysis, via skipping over subjects that are not changed.
|
5
|
-
|
6
|
-
This is an explicit trade off, often worth the downsides.
|
7
|
-
|
8
|
-
## Motivation
|
9
|
-
|
10
|
-
Despite all efforts in setting up a project for maximum mutation testing
|
11
|
-
efficiency, running a full pass over all available subjects is not always
|
12
|
-
desired. On building your branches on CI, and during local commit stage, its
|
13
|
-
instead more efficient to scope the Mutant run to everything that was
|
14
|
-
touched in the current branch / commit. The working set of subjects.
|
15
|
-
|
16
|
-
For not having to manually keep track of the working set, the `--since` option
|
17
|
-
allows you to specify a git reference point. Mutant will automatically subset all
|
18
|
-
available subjects to the ones that where touched since the reference point.
|
19
|
-
|
20
|
-
## Usage
|
21
|
-
|
22
|
-
Use the `--since git-reference` flag to enable automatic filtering of the
|
23
|
-
matched subjects to the ones that have a line changed since the reference
|
24
|
-
point.
|
25
|
-
|
26
|
-
Internally mutant will use the semantics of `git diff git-reference` to
|
27
|
-
determine which subjects have changes. A subject is selected by this mechanism
|
28
|
-
when `git diff` reports a hunk that overlaps with the current subjects line
|
29
|
-
range.
|
30
|
-
|
31
|
-
## Example
|
32
|
-
|
33
|
-
On a branch, executing:
|
34
|
-
|
35
|
-
```
|
36
|
-
mutant --since master 'ProjectNamespace*'
|
37
|
-
```
|
38
|
-
|
39
|
-
Will run mutation testing against all subjects that have a direct source code
|
40
|
-
since the `master` branch. Assuming your project has 100 subjects, and you
|
41
|
-
touched 2 of them in your branch: Mutant will only select these 2 subjects for
|
42
|
-
mutation testing.
|
43
|
-
|
44
|
-
## Recommended use
|
45
|
-
|
46
|
-
Use incremental for any project where a full pass does not fit within acceptable
|
47
|
-
round trip times for the human mind.
|
48
|
-
|
49
|
-
A small 200 loc gem, should probably never use it. Typically its the local per
|
50
|
-
developer environment that should use incremental first. On CI its recommended
|
51
|
-
to stay with the full pass as long as possible and switch to incremental mode
|
52
|
-
when the CI cycle time gets too annoying.
|
53
|
-
|
54
|
-
In addition, once using incremental its recommended to run a full pass as a
|
55
|
-
nightly job.
|
56
|
-
|
57
|
-
Incremental is also a good mode to retrofit mutation testing into a legacy
|
58
|
-
project.
|
59
|
-
|
60
|
-
Good selectors for reference points are `HEAD~1` (the previous commit) or
|
61
|
-
`master` (the integration branch).
|
62
|
-
|
63
|
-
## Limitations
|
64
|
-
|
65
|
-
Mutant only triggers incremental subject selection for *direct* code changes.
|
66
|
-
It'll currently not select subjects that where indirectly changed.
|
67
|
-
|
68
|
-
Counter examples:
|
69
|
-
|
70
|
-
* A change to a constant that results in a behavior change of a subject will
|
71
|
-
not trigger that subject to be selected.
|
72
|
-
* A change to a subject A that causes another subject B to change in behavior,
|
73
|
-
will not select subject B.
|
74
|
-
|
75
|
-
These limitations may be removed in future versions of mutant, work on more
|
76
|
-
fine grained tracing is underway.
|
data/docs/known-problems.md
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
Known Problems
|
2
|
-
==============
|
3
|
-
|
4
|
-
The Crash / Stuck Problem (MRI)
|
5
|
-
-------------------------------
|
6
|
-
|
7
|
-
Mutations generated by mutant can cause MRI to enter VM states its not prepared for.
|
8
|
-
All MRI versions > 1.9 and < 2.2.1 are affected by this depending on your compiler flags,
|
9
|
-
compiler version, and OS scheduling behavior.
|
10
|
-
|
11
|
-
This can have the following unintended effects:
|
12
|
-
|
13
|
-
* MRI crashes with a segfault. Mutant kills each mutation in a dedicated fork to isolate
|
14
|
-
the mutations side effects when this fork terminates abnormally (segfault) mutant
|
15
|
-
counts the mutation as killed.
|
16
|
-
|
17
|
-
* MRI crashes with a segfault and gets stuck when handling the segfault.
|
18
|
-
Depending on the number of active kill jobs mutant might appear to continue normally until
|
19
|
-
all workers are stuck into this state when it begins to hang.
|
20
|
-
Currently mutant must assume that your test suite simply not terminated yet as from the outside
|
21
|
-
(parent process) the difference between a long running test and a stuck MRI is not observable.
|
22
|
-
Its planned to implement a timeout enforced from the parent process, but ideally MRI simply gets fixed.
|
23
|
-
|
24
|
-
References:
|
25
|
-
|
26
|
-
* [MRI fix](https://github.com/ruby/ruby/commit/8fe95fea9d238a6deb70c8953ceb3a28a67f4636)
|
27
|
-
* [MRI backport to 2.2.1](https://github.com/ruby/ruby/commit/8fe95fea9d238a6deb70c8953ceb3a28a67f4636)
|
28
|
-
* [Mutant issue](https://github.com/mbj/mutant/issues/265)
|
29
|
-
* [Upstream bug redmine](https://bugs.ruby-lang.org/issues/10460)
|
30
|
-
* [Upstream bug github](https://github.com/ruby/ruby/pull/822)
|
data/docs/limitations.md
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
Limitations
|
2
|
-
===========
|
3
|
-
|
4
|
-
Subject
|
5
|
-
-------
|
6
|
-
|
7
|
-
Mutant cannot emit mutations for some subjects.
|
8
|
-
|
9
|
-
* methods defined within a closure. For example, methods defined using `module_eval`, `class_eval`,
|
10
|
-
`define_method`, or `define_singleton_method`:
|
11
|
-
|
12
|
-
```ruby
|
13
|
-
class Example
|
14
|
-
class_eval do
|
15
|
-
def example1
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
module_eval do
|
20
|
-
def example2
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
define_method(:example3) do
|
25
|
-
end
|
26
|
-
|
27
|
-
define_singleton_method(:example4) do
|
28
|
-
end
|
29
|
-
end
|
30
|
-
```
|
31
|
-
|
32
|
-
* singleton methods not defined on a constant or `self`
|
33
|
-
|
34
|
-
```ruby
|
35
|
-
class Foo
|
36
|
-
def self.bar; end # ok
|
37
|
-
def Foo.baz; end # ok
|
38
|
-
|
39
|
-
myself = self
|
40
|
-
def myself.qux; end # cannot mutate
|
41
|
-
end
|
42
|
-
```
|
43
|
-
|
44
|
-
* methods defined with eval:
|
45
|
-
|
46
|
-
```ruby
|
47
|
-
class Foo
|
48
|
-
class_eval('def bar; end') # cannot mutate
|
49
|
-
end
|
50
|
-
```
|
data/docs/mutant-minitest.md
DELETED
@@ -1,149 +0,0 @@
|
|
1
|
-
mutant-minitest
|
2
|
-
===============
|
3
|
-
|
4
|
-
Before starting with mutant its recommended to understand the
|
5
|
-
[nomenclature](/docs/nomenclature.md).
|
6
|
-
|
7
|
-
## Setup
|
8
|
-
|
9
|
-
To add mutant to your minitest code base you need to:
|
10
|
-
|
11
|
-
1. Add `mutant-minitest` as development dependency to your `Gemfile` or `.gemspec`
|
12
|
-
|
13
|
-
This may look like:
|
14
|
-
|
15
|
-
```ruby
|
16
|
-
# A gemfile
|
17
|
-
gem 'mutant-minitest'
|
18
|
-
```
|
19
|
-
|
20
|
-
2. Add `require 'mutant/minitest/coverage'` to your test environment (example to your `test/test_helper.rb`)
|
21
|
-
|
22
|
-
Example:
|
23
|
-
|
24
|
-
```ruby
|
25
|
-
require 'minitest/autorun'
|
26
|
-
require 'mutant/minitest/coverage'
|
27
|
-
|
28
|
-
class YourTestBaseClass < MiniTest::Test
|
29
|
-
# ...
|
30
|
-
```
|
31
|
-
|
32
|
-
3. Add `.cover` call sides to your test suite to mark them as eligible for killing mutations in subjects.
|
33
|
-
|
34
|
-
Example:
|
35
|
-
|
36
|
-
```ruby
|
37
|
-
class YourLibrarySomeClassTest < YourTestBaseClass
|
38
|
-
cover 'YourLibrary::SomeClass*' # tells mutant which subjects this tests should cover
|
39
|
-
# ...
|
40
|
-
```
|
41
|
-
|
42
|
-
4. Run mutant against the minitest integration
|
43
|
-
|
44
|
-
```sh
|
45
|
-
bundle exec mutant --include lib --require 'your_library.rb' --use minitest -- 'YourLibrary*'
|
46
|
-
```
|
47
|
-
|
48
|
-
## Run through example
|
49
|
-
|
50
|
-
This uses [mbj/auom](https://github.com/mbj/auom) a small library that
|
51
|
-
has 100% mutation coverage. Its tests execute very fast and do not have any IO
|
52
|
-
so its a good playground example to interact with.
|
53
|
-
|
54
|
-
All the setup described above is already done.
|
55
|
-
|
56
|
-
```sh
|
57
|
-
git clone https://github.com/mbj/auom
|
58
|
-
cd auom
|
59
|
-
bundle install # gemfile references mutant-minitest already
|
60
|
-
bundle exec mutant --include lib --require auom --use minitest -- 'AUOM*'
|
61
|
-
```
|
62
|
-
|
63
|
-
This prints a report like:
|
64
|
-
|
65
|
-
```sh
|
66
|
-
Mutant environment:
|
67
|
-
Matcher: #<Mutant::Matcher::Config match_expressions: [AUOM*]>
|
68
|
-
Integration: Mutant::Integration::Minitest
|
69
|
-
Jobs: 8
|
70
|
-
Includes: ["lib"]
|
71
|
-
Requires: ["auom"]
|
72
|
-
Subjects: 23
|
73
|
-
Mutations: 1003
|
74
|
-
Results: 1003
|
75
|
-
Kills: 1003
|
76
|
-
Alive: 0
|
77
|
-
Runtime: 9.68s
|
78
|
-
Killtime: 3.80s
|
79
|
-
Overhead: 154.30%
|
80
|
-
Mutations/s: 103.67
|
81
|
-
Coverage: 100.00%
|
82
|
-
```
|
83
|
-
|
84
|
-
Now lets try adding some redundant (or unspecified) code:
|
85
|
-
|
86
|
-
```sh
|
87
|
-
patch -p1 <<'PATCH'
|
88
|
-
--- a/lib/auom/unit.rb
|
89
|
-
+++ b/lib/auom/unit.rb
|
90
|
-
@@ -170,7 +170,7 @@ module AUOM
|
91
|
-
# TODO: Move defaults coercions etc to .build method
|
92
|
-
#
|
93
|
-
def self.new(scalar, numerators = nil, denominators = nil)
|
94
|
-
- scalar = rational(scalar)
|
95
|
-
+ scalar = rational(scalar) if true
|
96
|
-
|
97
|
-
scalar, numerators = resolve([*numerators], scalar, :*)
|
98
|
-
scalar, denominators = resolve([*denominators], scalar, :/)
|
99
|
-
PATCH
|
100
|
-
```
|
101
|
-
|
102
|
-
Running mutant again prints the following:
|
103
|
-
|
104
|
-
```
|
105
|
-
AUOM::Unit.new:/home/mrh-dev/auom/lib/auom/unit.rb:172
|
106
|
-
- minitest:AUOMTest::ClassMethods::New#test_reduced_unit
|
107
|
-
- minitest:AUOMTest::ClassMethods::New#test_normalized_denominator_scalar
|
108
|
-
- minitest:AUOMTest::ClassMethods::New#test_normalized_numerator_unit
|
109
|
-
- minitest:AUOMTest::ClassMethods::New#test_incompatible_scalar
|
110
|
-
- minitest:AUOMTest::ClassMethods::New#test_integer
|
111
|
-
- minitest:AUOMTest::ClassMethods::New#test_sorted_numerator
|
112
|
-
- minitest:AUOMTest::ClassMethods::New#test_unknown_unit
|
113
|
-
- minitest:AUOMTest::ClassMethods::New#test_rational
|
114
|
-
- minitest:AUOMTest::ClassMethods::New#test_normalized_numerator_scalar
|
115
|
-
- minitest:AUOMTest::ClassMethods::New#test_sorted_denominator
|
116
|
-
- minitest:AUOMTest::ClassMethods::New#test_normalized_denominator_unit
|
117
|
-
evil:AUOM::Unit.new:/home/mrh-dev/auom/lib/auom/unit.rb:172:cd9ee
|
118
|
-
@@ -1,9 +1,7 @@
|
119
|
-
def self.new(scalar, numerators = nil, denominators = nil)
|
120
|
-
- if true
|
121
|
-
- scalar = rational(scalar)
|
122
|
-
- end
|
123
|
-
+ scalar = rational(scalar)
|
124
|
-
scalar, numerators = resolve([*numerators], scalar, :*)
|
125
|
-
scalar, denominators = resolve([*denominators], scalar, :/)
|
126
|
-
super(scalar, *[numerators, denominators].map(&:sort)).freeze
|
127
|
-
end
|
128
|
-
-----------------------
|
129
|
-
Mutant configuration:
|
130
|
-
Matcher: #<Mutant::Matcher::Config match_expressions: [AUOM*]>
|
131
|
-
Integration: Mutant::Integration::Minitest
|
132
|
-
Jobs: 8
|
133
|
-
Includes: ["lib"]
|
134
|
-
Requires: ["auom"]
|
135
|
-
Subjects: 23
|
136
|
-
Mutations: 1009
|
137
|
-
Results: 1009
|
138
|
-
Kills: 1008
|
139
|
-
Alive: 1
|
140
|
-
Runtime: 9.38s
|
141
|
-
Killtime: 3.47s
|
142
|
-
Overhead: 170.06%
|
143
|
-
Mutations/s: 107.60
|
144
|
-
Coverage: 99.90%
|
145
|
-
```
|
146
|
-
|
147
|
-
This shows mutant detected the alive mutation. Which shows the conditional we deliberately added above is redundant.
|
148
|
-
|
149
|
-
Feel free to also remove some tests. Or do other modifications to either test or code.
|
data/docs/mutant-rspec.md
DELETED
@@ -1,130 +0,0 @@
|
|
1
|
-
mutant-rspec
|
2
|
-
============
|
3
|
-
|
4
|
-
Before starting with mutant its recommended to understand the
|
5
|
-
[nomenclature](/docs/nomenclature.md).
|
6
|
-
|
7
|
-
## Setup
|
8
|
-
|
9
|
-
To add mutant to your rspec code base you need to:
|
10
|
-
|
11
|
-
1. Add `mutant-rspec` as development dependency to your `Gemfile` or `.gemspec`
|
12
|
-
|
13
|
-
This may look like:
|
14
|
-
|
15
|
-
```ruby
|
16
|
-
# A gemfile
|
17
|
-
gem 'mutant-rspec'
|
18
|
-
```
|
19
|
-
|
20
|
-
2. Run mutant against the rspec integration via the `--use rspec` flag.
|
21
|
-
|
22
|
-
## Run through example
|
23
|
-
|
24
|
-
This uses [mbj/auom](https://github.com/mbj/auom) a small library that
|
25
|
-
has 100% mutation coverage. Its tests execute very fast and do not have any IO
|
26
|
-
so its a good playground example to interact with.
|
27
|
-
|
28
|
-
All the setup described above is already done.
|
29
|
-
|
30
|
-
```sh
|
31
|
-
git clone https://github.com/mbj/auom
|
32
|
-
cd auom
|
33
|
-
bundle install # gemfile references mutant-rspec already
|
34
|
-
bundle exec mutant --include lib --require auom --use rspec -- 'AUOM*'
|
35
|
-
```
|
36
|
-
|
37
|
-
This prints a report like:
|
38
|
-
|
39
|
-
```sh
|
40
|
-
Mutant environment:
|
41
|
-
Matcher: #<Mutant::Matcher::Config match_expressions: [AUOM*]>
|
42
|
-
Integration: Mutant::Integration::Rspec
|
43
|
-
Jobs: 8
|
44
|
-
Includes: ["lib"]
|
45
|
-
Requires: ["auom"]
|
46
|
-
Subjects: 23
|
47
|
-
Mutations: 1003
|
48
|
-
Results: 1003
|
49
|
-
Kills: 1003
|
50
|
-
Alive: 0
|
51
|
-
Runtime: 51.52s
|
52
|
-
Killtime: 200.13s
|
53
|
-
Overhead: -74.26%
|
54
|
-
Mutations/s: 19.47
|
55
|
-
Coverage: 100.00%
|
56
|
-
```
|
57
|
-
|
58
|
-
Now lets try adding some redundant (or unspecified) code:
|
59
|
-
|
60
|
-
```sh
|
61
|
-
patch -p1 <<'PATCH'
|
62
|
-
--- a/lib/auom/unit.rb
|
63
|
-
+++ b/lib/auom/unit.rb
|
64
|
-
@@ -170,7 +170,7 @@ module AUOM
|
65
|
-
# TODO: Move defaults coercions etc to .build method
|
66
|
-
#
|
67
|
-
def self.new(scalar, numerators = nil, denominators = nil)
|
68
|
-
- scalar = rational(scalar)
|
69
|
-
+ scalar = rational(scalar) if true
|
70
|
-
|
71
|
-
scalar, numerators = resolve([*numerators], scalar, :*)
|
72
|
-
scalar, denominators = resolve([*denominators], scalar, :/)
|
73
|
-
PATCH
|
74
|
-
```
|
75
|
-
|
76
|
-
Running mutant again prints the following:
|
77
|
-
|
78
|
-
```sh
|
79
|
-
evil:AUOM::Unit.new:/home/mrh-dev/example/auom/lib/auom/unit.rb:172:45e17
|
80
|
-
@@ -1,9 +1,7 @@
|
81
|
-
def self.new(scalar, numerators = nil, denominators = nil)
|
82
|
-
- if true
|
83
|
-
- scalar = rational(scalar)
|
84
|
-
- end
|
85
|
-
+ scalar = rational(scalar)
|
86
|
-
scalar, numerators = resolve([*numerators], scalar, :*)
|
87
|
-
scalar, denominators = resolve([*denominators], scalar, :/)
|
88
|
-
super(scalar, *[numerators, denominators].map(&:sort)).freeze
|
89
|
-
end
|
90
|
-
-----------------------
|
91
|
-
Mutant configuration:
|
92
|
-
Matcher: #<Mutant::Matcher::Config match_expressions: [AUOM*]>
|
93
|
-
Integration: Mutant::Integration::Rspec
|
94
|
-
Jobs: 8
|
95
|
-
Includes: ["lib"]
|
96
|
-
Requires: ["auom"]
|
97
|
-
Subjects: 23
|
98
|
-
Mutations: 1009
|
99
|
-
Results: 1009
|
100
|
-
Kills: 1008
|
101
|
-
Alive: 1
|
102
|
-
Runtime: 50.93s
|
103
|
-
Killtime: 190.09s
|
104
|
-
Overhead: -73.21%
|
105
|
-
Mutations/s: 19.81
|
106
|
-
Coverage: 99.90%
|
107
|
-
```
|
108
|
-
|
109
|
-
This shows mutant detected the alive mutation. Which shows the conditional we deliberately added above is redundant.
|
110
|
-
|
111
|
-
Feel free to also remove some tests. Or do other modifications to either test or code.
|
112
|
-
|
113
|
-
Test-Selection
|
114
|
-
--------------
|
115
|
-
|
116
|
-
Mutation testing is slow. The key to making it fast is selecting the correct
|
117
|
-
set of tests to run. Mutant currently supports the following built-in
|
118
|
-
strategy for selecting tests/specs:
|
119
|
-
|
120
|
-
Mutant uses the "longest rspec example group descriptions prefix match" to
|
121
|
-
select the tests to run.
|
122
|
-
|
123
|
-
Example for a subject like `Foo::Bar#baz` it will run all example groups with
|
124
|
-
description prefixes in `Foo::Bar#baz`, `Foo::Bar` and `Foo`. The order is
|
125
|
-
important, so if mutant finds example groups in the current prefix level,
|
126
|
-
these example groups *must* kill the mutation.
|
127
|
-
|
128
|
-
```sh
|
129
|
-
RAILS_ENV=test bundle exec mutant -r ./config/environment --use rspec User
|
130
|
-
```
|