mutant 0.8.10 → 0.8.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -4
- data/Changelog.md +8 -0
- data/README.md +112 -43
- data/Rakefile +2 -16
- data/circle.yml +1 -1
- data/config/flay.yml +2 -2
- data/config/flog.yml +1 -1
- data/config/reek.yml +3 -4
- data/config/rubocop.yml +53 -16
- data/lib/mutant.rb +27 -6
- data/lib/mutant/ast/meta/const.rb +2 -0
- data/lib/mutant/ast/meta/optarg.rb +2 -0
- data/lib/mutant/ast/meta/resbody.rb +2 -0
- data/lib/mutant/ast/meta/restarg.rb +2 -0
- data/lib/mutant/ast/meta/send.rb +4 -0
- data/lib/mutant/ast/meta/symbol.rb +2 -0
- data/lib/mutant/ast/named_children.rb +14 -4
- data/lib/mutant/ast/nodes.rb +3 -1
- data/lib/mutant/ast/regexp.rb +53 -0
- data/lib/mutant/ast/regexp/transformer.rb +185 -0
- data/lib/mutant/ast/regexp/transformer/alternative.rb +39 -0
- data/lib/mutant/ast/regexp/transformer/character_set.rb +46 -0
- data/lib/mutant/ast/regexp/transformer/direct.rb +99 -0
- data/lib/mutant/ast/regexp/transformer/options_group.rb +66 -0
- data/lib/mutant/ast/regexp/transformer/quantifier.rb +112 -0
- data/lib/mutant/ast/regexp/transformer/recursive.rb +50 -0
- data/lib/mutant/ast/regexp/transformer/root.rb +29 -0
- data/lib/mutant/ast/regexp/transformer/text.rb +55 -0
- data/lib/mutant/ast/types.rb +92 -5
- data/lib/mutant/cli.rb +2 -14
- data/lib/mutant/color.rb +1 -1
- data/lib/mutant/config.rb +1 -3
- data/lib/mutant/expression/methods.rb +1 -1
- data/lib/mutant/expression/namespace.rb +2 -2
- data/lib/mutant/expression/parser.rb +1 -1
- data/lib/mutant/integration.rb +10 -28
- data/lib/mutant/isolation.rb +9 -60
- data/lib/mutant/isolation/fork.rb +72 -0
- data/lib/mutant/isolation/none.rb +25 -0
- data/lib/mutant/matcher/config.rb +2 -0
- data/lib/mutant/matcher/method/singleton.rb +5 -4
- data/lib/mutant/meta.rb +11 -4
- data/lib/mutant/meta/example.rb +2 -116
- data/lib/mutant/meta/example/dsl.rb +22 -19
- data/lib/mutant/meta/example/verification.rb +86 -0
- data/lib/mutant/mutator.rb +22 -49
- data/lib/mutant/mutator/node.rb +15 -19
- data/lib/mutant/mutator/node/and_asgn.rb +1 -1
- data/lib/mutant/mutator/node/argument.rb +10 -5
- data/lib/mutant/mutator/node/arguments.rb +5 -9
- data/lib/mutant/mutator/node/begin.rb +4 -17
- data/lib/mutant/mutator/node/block.rb +1 -1
- data/lib/mutant/mutator/node/break.rb +1 -1
- data/lib/mutant/mutator/node/class.rb +21 -0
- data/lib/mutant/mutator/node/conditional_loop.rb +1 -1
- data/lib/mutant/mutator/node/define.rb +1 -1
- data/lib/mutant/mutator/node/defined.rb +1 -1
- data/lib/mutant/mutator/node/dstr.rb +1 -1
- data/lib/mutant/mutator/node/dsym.rb +1 -1
- data/lib/mutant/mutator/node/generic.rb +3 -3
- data/lib/mutant/mutator/node/kwbegin.rb +1 -1
- data/lib/mutant/mutator/node/literal.rb +9 -0
- data/lib/mutant/mutator/node/literal/boolean.rb +1 -1
- data/lib/mutant/mutator/node/literal/fixnum.rb +2 -2
- data/lib/mutant/mutator/node/literal/float.rb +4 -6
- data/lib/mutant/mutator/node/literal/hash.rb +1 -1
- data/lib/mutant/mutator/node/literal/nil.rb +1 -1
- data/lib/mutant/mutator/node/literal/range.rb +2 -19
- data/lib/mutant/mutator/node/literal/regex.rb +43 -3
- data/lib/mutant/mutator/node/literal/string.rb +1 -1
- data/lib/mutant/mutator/node/literal/symbol.rb +2 -4
- data/lib/mutant/mutator/node/masgn.rb +1 -1
- data/lib/mutant/mutator/node/match_current_line.rb +1 -1
- data/lib/mutant/mutator/node/mlhs.rb +2 -3
- data/lib/mutant/mutator/node/named_value/access.rb +2 -2
- data/lib/mutant/mutator/node/named_value/constant_assignment.rb +4 -3
- data/lib/mutant/mutator/node/named_value/variable_assignment.rb +4 -4
- data/lib/mutant/mutator/node/next.rb +1 -1
- data/lib/mutant/mutator/node/nthref.rb +1 -1
- data/lib/mutant/mutator/node/or_asgn.rb +1 -1
- data/lib/mutant/mutator/node/regexp.rb +44 -0
- data/lib/mutant/mutator/node/regopt.rb +31 -0
- data/lib/mutant/mutator/node/resbody.rb +1 -1
- data/lib/mutant/mutator/node/rescue.rb +1 -3
- data/lib/mutant/mutator/node/return.rb +1 -1
- data/lib/mutant/mutator/node/send.rb +43 -3
- data/lib/mutant/mutator/node/send/attribute_assignment.rb +4 -1
- data/lib/mutant/mutator/node/send/conditional.rb +23 -0
- data/lib/mutant/mutator/node/send/index.rb +1 -1
- data/lib/mutant/mutator/node/splat.rb +1 -1
- data/lib/mutant/mutator/node/when.rb +1 -1
- data/lib/mutant/mutator/node/yield.rb +1 -1
- data/lib/mutant/mutator/util.rb +0 -30
- data/lib/mutant/mutator/util/array.rb +4 -16
- data/lib/mutant/parallel.rb +1 -1
- data/lib/mutant/parallel/worker.rb +1 -1
- data/lib/mutant/registry.rb +44 -0
- data/lib/mutant/reporter/cli/format.rb +2 -0
- data/lib/mutant/reporter/cli/printer.rb +2 -2
- data/lib/mutant/reporter/cli/printer/config.rb +0 -1
- data/lib/mutant/reporter/cli/printer/env_progress.rb +1 -11
- data/lib/mutant/reporter/cli/printer/mutation_progress_result.rb +1 -1
- data/lib/mutant/reporter/cli/printer/mutation_result.rb +2 -0
- data/lib/mutant/reporter/cli/tput.rb +1 -1
- data/lib/mutant/reporter/sequence.rb +3 -0
- data/lib/mutant/require_highjack.rb +6 -2
- data/lib/mutant/result.rb +1 -1
- data/lib/mutant/subject.rb +5 -5
- data/lib/mutant/subject/method/instance.rb +1 -2
- data/lib/mutant/util.rb +18 -0
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/zombifier.rb +5 -3
- data/meta/and.rb +1 -1
- data/meta/and_asgn.rb +1 -1
- data/meta/array.rb +2 -2
- data/meta/begin.rb +2 -2
- data/meta/block.rb +7 -7
- data/meta/block_pass.rb +1 -1
- data/meta/blockarg.rb +1 -1
- data/meta/break.rb +1 -1
- data/meta/case.rb +2 -2
- data/meta/casgn.rb +11 -2
- data/meta/cbase.rb +1 -1
- data/meta/class.rb +10 -0
- data/meta/const.rb +9 -1
- data/meta/csend.rb +8 -0
- data/meta/cvar.rb +1 -1
- data/meta/cvasgn.rb +1 -1
- data/meta/date.rb +4 -4
- data/meta/def.rb +14 -14
- data/meta/defined.rb +1 -1
- data/meta/dstr.rb +1 -1
- data/meta/dsym.rb +1 -1
- data/meta/ensure.rb +1 -1
- data/meta/false.rb +1 -1
- data/meta/float.rb +3 -3
- data/meta/gvar.rb +1 -1
- data/meta/gvasgn.rb +1 -1
- data/meta/hash.rb +1 -1
- data/meta/if.rb +17 -3
- data/meta/int.rb +1 -1
- data/meta/ivar.rb +1 -1
- data/meta/ivasgn.rb +14 -1
- data/meta/kwarg.rb +8 -0
- data/meta/kwbegin.rb +1 -1
- data/meta/kwoptarg.rb +11 -0
- data/meta/lvar.rb +1 -1
- data/meta/lvasgn.rb +1 -1
- data/meta/masgn.rb +1 -1
- data/meta/match_current_line.rb +2 -2
- data/meta/next.rb +1 -1
- data/meta/nil.rb +1 -1
- data/meta/nthref.rb +5 -5
- data/meta/op_assgn.rb +1 -1
- data/meta/or.rb +1 -1
- data/meta/or_asgn.rb +5 -5
- data/meta/range.rb +2 -8
- data/meta/redo.rb +1 -1
- data/meta/regexp.rb +106 -0
- data/meta/regexp/regexp_bol_anchor.rb +13 -0
- data/meta/regexp/regexp_bos_anchor.rb +26 -0
- data/meta/regexp/regexp_root_expression.rb +13 -0
- data/meta/regopt.rb +8 -0
- data/meta/rescue.rb +49 -4
- data/meta/restarg.rb +6 -9
- data/meta/return.rb +2 -2
- data/meta/self.rb +1 -1
- data/meta/send.rb +228 -55
- data/meta/str.rb +1 -1
- data/meta/super.rb +3 -3
- data/meta/{symbol.rb → sym.rb} +1 -1
- data/meta/true.rb +1 -1
- data/meta/until.rb +1 -1
- data/meta/while.rb +2 -2
- data/meta/yield.rb +1 -1
- data/mutant-rspec.gemspec +2 -2
- data/mutant.gemspec +6 -5
- data/spec/integration/mutant/isolation/fork_spec.rb +8 -0
- data/spec/integration/mutant/rspec_spec.rb +1 -1
- data/spec/integration/mutant/test_mutator_handles_types_spec.rb +1 -2
- data/spec/integrations.yml +93 -24
- data/spec/spec_helper.rb +12 -7
- data/spec/support/compress_helper.rb +1 -1
- data/spec/support/corpus.rb +115 -50
- data/spec/support/fake_actor.rb +5 -5
- data/spec/support/file_system.rb +1 -1
- data/spec/support/ice_nine_config.rb +3 -3
- data/spec/support/ruby_vm.rb +11 -12
- data/spec/support/shared_context.rb +22 -13
- data/spec/support/test_app.rb +1 -1
- data/spec/support/warning.rb +64 -0
- data/spec/support/warnings.yml +4 -0
- data/spec/support/xspec.rb +177 -0
- data/spec/unit/mutant/actor/env_spec.rb +2 -2
- data/spec/unit/mutant/actor/sender_spec.rb +1 -1
- data/spec/unit/mutant/ast/meta/send_spec.rb +1 -1
- data/spec/unit/mutant/ast/named_children_spec.rb +26 -0
- data/spec/unit/mutant/ast/regexp/parse_spec.rb +7 -0
- data/spec/unit/mutant/ast/regexp/supported_predicate_spec.rb +14 -0
- data/spec/unit/mutant/ast/regexp/transformer/lookup_table/table_spec.rb +19 -0
- data/spec/unit/mutant/ast/regexp/transformer/lookup_table_spec.rb +33 -0
- data/spec/unit/mutant/ast/regexp/transformer_spec.rb +19 -0
- data/spec/unit/mutant/ast/regexp_spec.rb +617 -0
- data/spec/unit/mutant/cli_spec.rb +7 -45
- data/spec/unit/mutant/context_spec.rb +4 -7
- data/spec/unit/mutant/env/{boostrap_spec.rb → bootstrap_spec.rb} +2 -2
- data/spec/unit/mutant/env_spec.rb +13 -16
- data/spec/unit/mutant/expression/namespace/{flat_spec.rb → exact_spec.rb} +0 -0
- data/spec/unit/mutant/integration/rspec_spec.rb +2 -2
- data/spec/unit/mutant/integration_spec.rb +14 -0
- data/spec/unit/mutant/isolation/fork_spec.rb +155 -0
- data/spec/unit/mutant/isolation/none_spec.rb +16 -0
- data/spec/unit/mutant/loader_spec.rb +1 -1
- data/spec/unit/mutant/matcher/methods/instance_spec.rb +2 -4
- data/spec/unit/mutant/meta/example/dsl_spec.rb +106 -0
- data/spec/unit/mutant/meta/example/verification_spec.rb +120 -0
- data/spec/unit/mutant/meta/example_spec.rb +32 -0
- data/spec/unit/mutant/mutator/node_spec.rb +37 -4
- data/spec/unit/mutant/mutator_spec.rb +21 -0
- data/spec/unit/mutant/{runner → parallel}/driver_spec.rb +0 -0
- data/spec/unit/mutant/parallel/master_spec.rb +13 -13
- data/spec/unit/mutant/registry_spec.rb +47 -0
- data/spec/unit/mutant/reporter/cli/printer/config_spec.rb +0 -4
- data/spec/unit/mutant/reporter/cli/printer/env_progress_spec.rb +0 -8
- data/spec/unit/mutant/reporter/cli/printer/env_result_spec.rb +0 -2
- data/spec/unit/mutant/reporter/cli/printer/status_progressive_spec.rb +0 -8
- data/spec/unit/mutant/reporter/cli/printer/status_spec.rb +0 -34
- data/spec/unit/mutant/reporter/cli_spec.rb +0 -22
- data/spec/unit/mutant/repository/diff_spec.rb +6 -6
- data/spec/unit/mutant/require_highjack_spec.rb +38 -14
- data/spec/unit/mutant/result/env_spec.rb +1 -4
- data/spec/unit/mutant/runner_spec.rb +1 -1
- data/spec/unit/mutant/subject/method/instance_spec.rb +1 -1
- data/spec/unit/mutant/subject_spec.rb +3 -3
- data/spec/unit/mutant/util/one_spec.rb +20 -0
- data/spec/unit/mutant/zombifier_spec.rb +18 -18
- data/test_app/{Gemfile.rspec3.3 → Gemfile.rspec3.5} +2 -2
- metadata +94 -24
- data/TODO +0 -21
- data/lib/mutant/mutator/node/blockarg.rb +0 -13
- data/lib/mutant/mutator/node/restarg.rb +0 -13
- data/lib/mutant/mutator/registry.rb +0 -49
- data/meta/boolean.rb +0 -13
- data/meta/regex.rb +0 -19
- data/spec/unit/mutant/isolation_spec.rb +0 -104
- data/spec/unit/mutant/mutator/registry_spec.rb +0 -57
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b6726d9cc7696a22bc3de412e2aec93c6098212
|
4
|
+
data.tar.gz: 1c68cebbe3bd9faf603b604621a5af7cfb6402d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9a1dd4866a3264565adccb269d212b0609bdd806fc94e9f42b3366deb951967c48d0595f6044158a1719155557af450fb949821eadb7699432aa73262e7e1cf
|
7
|
+
data.tar.gz: 2cb50707ab5a178bb9eb8d1288251e978db32fbd92efddc1a4417e772df2ec4f2cefa86fceaeeb2dc5a7b7a654afe9c9182d548183a733497d17fdc9459515ea
|
data/.rubocop.yml
CHANGED
data/Changelog.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
# v0.8.11 2016-01-xx
|
2
|
+
|
3
|
+
* Add support for rspec-3.5
|
4
|
+
* Remove misleading --debug option
|
5
|
+
* Remove misleading --expect-coverage option
|
6
|
+
* Add basic support for regexp mutations (machinery and simple anchor mutations)
|
7
|
+
* Add support for mutating csend (duck tape operator) into regular sends
|
8
|
+
|
1
9
|
# v0.8.10 2016-01-24
|
2
10
|
|
3
11
|
* Add support for parser 2.3 (via unparser 0.2.5)
|
data/README.md
CHANGED
@@ -7,10 +7,11 @@ mutant
|
|
7
7
|
[![Inline docs](http://inch-ci.org/github/mbj/mutant.png)](http://inch-ci.org/github/mbj/mutant)
|
8
8
|
[![Gem Version](https://img.shields.io/gem/v/mutant.svg)](https://rubygems.org/gems/mutant)
|
9
9
|
[![Flattr](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/thing/1823010/mbjmutant-on-GitHub)
|
10
|
+
[![Slack Status](https://mutation-testing-slack.herokuapp.com/badge.svg)](https://mutation-testing.slack.com/messages/mutant)
|
10
11
|
|
11
12
|
Mutant is a mutation testing tool for Ruby.
|
12
13
|
|
13
|
-
The idea is that if code can be changed and your tests do not notice, either that code isn't being covered
|
14
|
+
The idea is that if code can be changed and your tests do not notice, then either that code isn't being covered
|
14
15
|
or it does not have a speced side effect.
|
15
16
|
|
16
17
|
Mutant supports ruby >= 2.1, while support for JRuby is planned.
|
@@ -25,7 +26,7 @@ Installation
|
|
25
26
|
------------
|
26
27
|
|
27
28
|
As mutant right now only supports rspec, install the gem `mutant-rspec` via your preferred method.
|
28
|
-
It'll pull the `mutant` gem (in correct version), that contains the main engine.
|
29
|
+
It'll pull the `mutant` gem (in the correct version), that contains the main engine.
|
29
30
|
|
30
31
|
```ruby
|
31
32
|
gem install mutant-rspec
|
@@ -48,29 +49,24 @@ mutant --include lib --require virtus --use rspec Virtus::Attribute.build
|
|
48
49
|
mutant --include lib --require virtus --use rspec Virtus::Attribute#type
|
49
50
|
```
|
50
51
|
|
51
|
-
|
52
|
-
|
52
|
+
Rails
|
53
|
+
-------
|
53
54
|
|
54
|
-
|
55
|
-
mutant will look like it is running indefinitely without killing a remaining mutation. To
|
56
|
-
avoid mutations like this, consider adding a timeout around your tests. For example, in
|
57
|
-
RSpec you can add the following to your `spec_helper`:
|
55
|
+
To mutation test Rails models with rspec, comment out ```require 'rspec/autorun'``` from your spec_helper.rb file. Having done so you should be able to use commands like the following:
|
58
56
|
|
59
|
-
```
|
60
|
-
config
|
61
|
-
Timeout.timeout(5_000, &example)
|
62
|
-
end
|
57
|
+
```sh
|
58
|
+
RAILS_ENV=test bundle exec mutant -r ./config/environment --use rspec User
|
63
59
|
```
|
64
60
|
|
65
|
-
|
61
|
+
Passing in RSpec Options
|
62
|
+
------------------------
|
66
63
|
|
67
|
-
|
68
|
-
-------
|
64
|
+
**NOTE: Experimental**
|
69
65
|
|
70
|
-
|
66
|
+
You can control some aspects of RSpec using the `SPEC_OPTS` environment variable as usual. If you want mutant to only pay attention to specs in a certain directory, you can run
|
71
67
|
|
72
68
|
```sh
|
73
|
-
|
69
|
+
SPEC_OPTS="--pattern spec/subdir_only/**/*_spec.rb" mutant --use rspec SomeClass
|
74
70
|
```
|
75
71
|
|
76
72
|
Limitations
|
@@ -121,8 +117,8 @@ Mutant cannot emit mutations for...
|
|
121
117
|
end
|
122
118
|
```
|
123
119
|
|
124
|
-
Mutation-Operators
|
125
|
-
|
120
|
+
Mutation-Operators
|
121
|
+
------------------
|
126
122
|
|
127
123
|
Mutant supports a wide range of mutation operators. An exhaustive list can be found in the [mutant-meta](https://github.com/mbj/mutant/tree/master/meta).
|
128
124
|
The `mutant-meta` is arranged to the AST-Node-Types of parser. Refer to parsers [AST documentation](https://github.com/whitequark/parser/blob/master/doc/AST_FORMAT.md) in doubt.
|
@@ -220,34 +216,66 @@ Mutation output is grouped by selection groups. Each group contains three sectio
|
|
220
216
|
-----------------------
|
221
217
|
```
|
222
218
|
|
223
|
-
|
224
|
-
|
219
|
+
Concurrency
|
220
|
+
-----------
|
225
221
|
|
226
|
-
|
222
|
+
By default, mutant will test mutations in parallel by running up to one process for each core on your system. You can control the number of processes created using the `--jobs` argument.
|
227
223
|
|
228
|
-
|
229
|
-
* [Wrocloverb 2014](http://wrocloverb.com/) / https://www.youtube.com/watch?v=rz-lFKEioLk
|
230
|
-
* [eurucamp 2013](http://2013.eurucamp.org/) / FrOSCon-2013 http://slid.es/markusschirp/mutation-testing
|
231
|
-
* [Cologne.rb](http://www.colognerb.de/topics/mutation-testing-mit-mutant) / https://github.com/DonSchado/colognerb-on-mutant/blob/master/mutation_testing_slides.pdf
|
224
|
+
Mutant forks a new process for each mutation to be tested to prevent side affects in your specs and the lack of thread safety in rspec from impacting the results.
|
232
225
|
|
233
|
-
|
234
|
-
|
226
|
+
If the code under test relies on a database, you may experience problems when running mutant because of conflicting data in the database. For example, if you have a test like this:
|
227
|
+
```
|
228
|
+
m = MyModel.create!(...)
|
229
|
+
expect(MyModel.first.name).to eql(m.name)
|
230
|
+
```
|
231
|
+
It might fail if some other test wrote a record to the MyModel table at the same time as this test was executed. (It would find the MyModel record created by the other test.) Most of these issues can be fixed by writing more specific tests. Here is a concurrent safe version of the same test:
|
232
|
+
```
|
233
|
+
m = MyModel.create!(...)
|
234
|
+
expect(MyModel.find_by_id(m.id).name).to eql(m.name)
|
235
|
+
```
|
236
|
+
You may also try wrapping your test runs in transactions.
|
235
237
|
|
236
|
-
|
238
|
+
Note that some databases, SQLite in particular, are not designed for concurrent access and will fail if used in this manner. If you are using SQLite, you should set the `--jobs` to 1.
|
237
239
|
|
238
|
-
|
239
|
-
|
240
|
-
* [Mutation testing and continuous integration (May 2015)][arkency2]
|
241
|
-
* [Why I want to introduce mutation testing to the `rails_event_store` gem (April 2015)][arkency3]
|
242
|
-
* [Mutation testing with mutant (April 2014)][sitepoint]
|
243
|
-
* [Mutation testing with mutant (January 2013)][solnic]
|
240
|
+
Neutral (noop) Tests
|
241
|
+
--------------------
|
244
242
|
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
243
|
+
Mutant will also test the original, unmutated, version your code. This ensures that mutant is able to properly setup and run your tests.
|
244
|
+
If an error occurs while mutant/rspec is running testing the original code, you will receive an error like the following:
|
245
|
+
```
|
246
|
+
--- Neutral failure ---
|
247
|
+
Original code was inserted unmutated. And the test did NOT PASS.
|
248
|
+
Your tests do not pass initially or you found a bug in mutant / unparser.
|
249
|
+
...
|
250
|
+
Test Output:
|
251
|
+
marshal data too short
|
252
|
+
```
|
253
|
+
Currently, troubleshooting these errors requires using a debugger and/or modyifying mutant to print out the error. You will want to rescue and inspect exceptions raised in this method: lib/mutant/integration/rspec.rb:call
|
254
|
+
|
255
|
+
Only Mutating Changed Code
|
256
|
+
--------------------------
|
257
|
+
|
258
|
+
Running mutant for the first time on an existing codebase can be a rather disheartening experience due to the large number of alive mutations found! Mutant has a setting that can help. Using the `--since` argument, mutant will only mutate code that has been modified. This allows you to introduce mutant into an existing code base without drowning in errors. Example usage that will mutate all code changed between master and the current branch:
|
259
|
+
```
|
260
|
+
mutant --include lib --require virtus --since master --use rspec Virtus::Attribute#type
|
261
|
+
```
|
262
|
+
|
263
|
+
Known Problems
|
264
|
+
==============
|
265
|
+
|
266
|
+
Mutations with Infinite Runtimes
|
267
|
+
---------------------------------
|
268
|
+
|
269
|
+
Occasionally mutant will produce a mutation with an infinite runtime. When this happens
|
270
|
+
mutant will look like it is running indefinitely without killing a remaining mutation. To
|
271
|
+
avoid mutations like this, consider adding a timeout around your tests. For example, in
|
272
|
+
RSpec you can add the following to your `spec_helper`:
|
273
|
+
```ruby
|
274
|
+
config.around(:each) do |example|
|
275
|
+
Timeout.timeout(5, &example)
|
276
|
+
end
|
277
|
+
```
|
278
|
+
which will fail specs which run for longer than 5 seconds.
|
251
279
|
|
252
280
|
The Crash / Stuck Problem (MRI)
|
253
281
|
-------------------------------
|
@@ -277,6 +305,17 @@ References:
|
|
277
305
|
* [Upstream bug redmine](https://bugs.ruby-lang.org/issues/10460)
|
278
306
|
* [Upstream bug github](https://github.com/ruby/ruby/pull/822)
|
279
307
|
|
308
|
+
Presentations
|
309
|
+
-------------
|
310
|
+
|
311
|
+
There are some presentations about mutant in the wild:
|
312
|
+
|
313
|
+
* [RailsConf 2014](http://railsconf.com/) / http://confreaks.com/videos/3333-railsconf-mutation-testing-with-mutant
|
314
|
+
* [Wrocloverb 2014](http://wrocloverb.com/) / https://www.youtube.com/watch?v=rz-lFKEioLk
|
315
|
+
* [eurucamp 2013](http://2013.eurucamp.org/) / FrOSCon-2013 http://slid.es/markusschirp/mutation-testing
|
316
|
+
* [Cologne.rb](http://www.colognerb.de/topics/mutation-testing-mit-mutant) / https://github.com/DonSchado/colognerb-on-mutant/blob/master/mutation_testing_slides.pdf
|
317
|
+
|
318
|
+
|
280
319
|
Planning a presentation?
|
281
320
|
------------------------
|
282
321
|
|
@@ -296,6 +335,25 @@ assumptions based on the absence of docs, use the tool authors brain to fill the
|
|
296
335
|
|
297
336
|
Hint, same applies to papers.
|
298
337
|
|
338
|
+
Blog posts
|
339
|
+
----------
|
340
|
+
|
341
|
+
Sorted by recency:
|
342
|
+
|
343
|
+
* [How to write better code using mutation testing (November 2015)][blockscore]
|
344
|
+
* [How good are your Ruby tests? Testing your tests with mutant (June 2015)][arkency1]
|
345
|
+
* [Mutation testing and continuous integration (May 2015)][arkency2]
|
346
|
+
* [Why I want to introduce mutation testing to the `rails_event_store` gem (April 2015)][arkency3]
|
347
|
+
* [Mutation testing with mutant (April 2014)][sitepoint]
|
348
|
+
* [Mutation testing with mutant (January 2013)][solnic]
|
349
|
+
|
350
|
+
[blockscore]: https://blog.blockscore.com/how-to-write-better-code-using-mutation-testing/
|
351
|
+
[sitepoint]: http://www.sitepoint.com/mutation-testing-mutant/
|
352
|
+
[arkency1]: http://blog.arkency.com/2015/06/how-good-are-your-ruby-tests-testing-your-tests-with-mutant/
|
353
|
+
[arkency2]: http://blog.arkency.com/2015/05/mutation-testing-and-continuous-integration/
|
354
|
+
[arkency3]: http://blog.arkency.com/2015/04/why-i-want-to-introduce-mutation-testing-to-the-rails-event-store-gem/
|
355
|
+
[solnic]: http://solnic.eu/2013/01/23/mutation-testing-with-mutant.html
|
356
|
+
|
299
357
|
Support
|
300
358
|
-------
|
301
359
|
|
@@ -306,8 +364,19 @@ Your options:
|
|
306
364
|
* [GitHub Issues](https://github.com/mbj/mutant/issues)
|
307
365
|
* Ping me on [twitter](https://twitter.com/_m_b_j_)
|
308
366
|
|
309
|
-
There is also a
|
310
|
-
|
367
|
+
There is also a mutation testing slack chat. Get an invite [here](https://mutation-testing-slack.herokuapp.com).
|
368
|
+
For discussing this project, join [#mutant](https://mutation-testing.slack.com/messages/#mutant).
|
369
|
+
|
370
|
+
Other Channels:
|
371
|
+
|
372
|
+
- [#cosmic-ray](https://mutation-testing.slack.com/messages/cosmic-ray): for discussing `cosmic-ray`, the python mutation testing tool.
|
373
|
+
- [#devtools](https://mutation-testing.slack.com/messages/devtools): for discussing the `devtools` metagem.
|
374
|
+
- [#general](https://mutation-testing.slack.com/messages/general): for general discussions about mutation testing.
|
375
|
+
- [#mutagen](https://mutation-testing.slack.com/messages/mutagen): for discussing `mutagen`, the javascript mutation testing tool.
|
376
|
+
- [#random](https://mutation-testing.slack.com/messages/random): for misc. off topic discussion.
|
377
|
+
- [#stryker](https://mutation-testing.slack.com/messages/stryker): for discussing `stryker`, the javascript mutation testing tool.
|
378
|
+
- [#wtf-dev](https://mutation-testing.slack.com/messages/wtf-dev): for sharing software development wtfs.
|
379
|
+
|
311
380
|
|
312
381
|
Credits
|
313
382
|
-------
|
data/Rakefile
CHANGED
@@ -9,30 +9,16 @@ namespace :metrics do
|
|
9
9
|
task mutant: :coverage do
|
10
10
|
arguments = %w[
|
11
11
|
bundle exec mutant
|
12
|
-
--ignore-subject Mutant::Meta*
|
13
12
|
--include lib
|
14
13
|
--since HEAD~1
|
15
14
|
--require mutant
|
16
15
|
--use rspec
|
17
16
|
--zombie
|
18
17
|
]
|
19
|
-
arguments.concat(%
|
18
|
+
arguments.concat(%w[--jobs 4]) if ENV.key?('CIRCLECI')
|
20
19
|
|
21
20
|
arguments.concat(%w[-- Mutant*])
|
22
21
|
|
23
|
-
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
desc 'Generate mutation operator listing'
|
28
|
-
task :list do
|
29
|
-
require 'mutant'
|
30
|
-
# TODO: Add a nice public interface
|
31
|
-
registry = Mutant::Mutator::Registry.send(:registry)
|
32
|
-
registry.keys.select do |key|
|
33
|
-
key.is_a?(Symbol)
|
34
|
-
end.sort.each do |type|
|
35
|
-
mutator = registry.fetch(type)
|
36
|
-
puts '%-18s: %s' % [type, mutator.name.sub(/\AMutant::Mutator::Node::/, '')]
|
22
|
+
Kernel.system(*arguments) or fail 'Mutant task is not successful'
|
37
23
|
end
|
38
24
|
end
|
data/circle.yml
CHANGED
data/config/flay.yml
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
---
|
2
|
-
threshold:
|
3
|
-
total_score:
|
2
|
+
threshold: 16
|
3
|
+
total_score: 1284
|
data/config/flog.yml
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
---
|
2
|
-
threshold:
|
2
|
+
threshold: 27.7
|
data/config/reek.yml
CHANGED
@@ -32,6 +32,7 @@ LongParameterList:
|
|
32
32
|
enabled: true
|
33
33
|
exclude:
|
34
34
|
- Mutant::Matcher::Method::Instance#self.build
|
35
|
+
- Mutant::Meta::Example::DSL # 3 vars
|
35
36
|
max_params: 2
|
36
37
|
LongYieldList:
|
37
38
|
enabled: true
|
@@ -42,7 +43,6 @@ NestedIterators:
|
|
42
43
|
exclude:
|
43
44
|
- Mutant#self.singleton_subclass_instance
|
44
45
|
- Mutant::CLI#parse
|
45
|
-
- Mutant::Isolation::Fork#self.call
|
46
46
|
- Mutant::Mutator::Node::Arguments#emit_argument_mutations
|
47
47
|
- Mutant::Mutator::Node::Resbody#mutate_captures
|
48
48
|
- Mutant::Mutator::Util::Array::Element#dispatch
|
@@ -65,12 +65,12 @@ TooManyInstanceVariables:
|
|
65
65
|
exclude:
|
66
66
|
- Mutant::Mutator # 4 vars
|
67
67
|
- Mutant::Parallel::Master # 4 vars
|
68
|
+
- Mutant::Meta::Example::DSL # 4 vars
|
68
69
|
max_instance_variables: 3
|
69
70
|
TooManyMethods:
|
70
71
|
enabled: true
|
71
72
|
exclude:
|
72
73
|
- Mutant::CLI
|
73
|
-
- Mutant::Meta::Example::Verification
|
74
74
|
- Mutant::Mutator::Node
|
75
75
|
- Mutant::Parallel::Master
|
76
76
|
max_methods: 10
|
@@ -79,7 +79,6 @@ TooManyStatements:
|
|
79
79
|
exclude:
|
80
80
|
- Mutant::CLI#add_debug_options
|
81
81
|
- Mutant::CLI#add_environment_options
|
82
|
-
- Mutant::Isolation::Fork#self.call
|
83
82
|
- Mutant::Reporter::CLI::Printer::Config#run
|
84
83
|
- Mutant::Reporter::CLI::Printer::EnvProgress#run
|
85
84
|
- Mutant::Runner#run_driver
|
@@ -130,7 +129,7 @@ UtilityFunction:
|
|
130
129
|
- Mutant::Integration::Null#call
|
131
130
|
- Mutant::Integration::Rspec#parse_example
|
132
131
|
- Mutant::Integration::Rspec#parse_expression # intentional, private
|
133
|
-
- Mutant::Meta::Example::Verification#
|
132
|
+
- Mutant::Meta::Example::Verification#format_mutations # intentional, private
|
134
133
|
- Mutant::Reporter::CLI::Format::Progressive#new_buffer
|
135
134
|
- Mutant::Reporter::CLI::Printer::StatusProgressive#object # False positive calls super
|
136
135
|
- Mutant::Repository::Diff#tracks? # intentional, private
|
data/config/rubocop.yml
CHANGED
@@ -11,20 +11,15 @@ BlockNesting:
|
|
11
11
|
|
12
12
|
# Align with the style guide.
|
13
13
|
CollectionMethods:
|
14
|
+
Enabled: true
|
14
15
|
PreferredMethods:
|
15
16
|
collect: 'map'
|
16
17
|
inject: 'reduce'
|
17
18
|
find: 'detect'
|
18
19
|
find_all: 'select'
|
19
20
|
|
20
|
-
# Do not force public/protected/private keyword to be indented at the same
|
21
|
-
# level as the def keyword. My personal preference is to outdent these keywords
|
22
|
-
# because I think when scanning code it makes it easier to identify the
|
23
|
-
# sections of code and visually separate them. When the keyword is at the same
|
24
|
-
# level I think it sort of blends in with the def keywords and makes it harder
|
25
|
-
# to scan the code and see where the sections are.
|
26
21
|
AccessModifierIndentation:
|
27
|
-
|
22
|
+
EnforcedStyle: outdent
|
28
23
|
|
29
24
|
# Limit line length
|
30
25
|
LineLength:
|
@@ -34,9 +29,17 @@ LineLength:
|
|
34
29
|
Documentation:
|
35
30
|
Enabled: false
|
36
31
|
|
37
|
-
#
|
32
|
+
# Permit
|
33
|
+
#
|
34
|
+
# boolean_check? or fail
|
35
|
+
#
|
36
|
+
# Reject
|
37
|
+
#
|
38
|
+
# if foo or bar
|
39
|
+
# ...
|
40
|
+
# end
|
38
41
|
AndOr:
|
39
|
-
|
42
|
+
EnforcedStyle: conditionals
|
40
43
|
|
41
44
|
# Do not favor modifier if/unless usage when you have a single-line body
|
42
45
|
IfUnlessModifier:
|
@@ -72,7 +75,7 @@ MultilineOperationIndentation:
|
|
72
75
|
|
73
76
|
# Prefer String#% over Kernel#sprintf
|
74
77
|
FormatString:
|
75
|
-
|
78
|
+
EnforcedStyle: percent
|
76
79
|
|
77
80
|
# Use square brackets for literal Array objects
|
78
81
|
PercentLiteralDelimiters:
|
@@ -95,11 +98,6 @@ SymbolArray:
|
|
95
98
|
EndAlignment:
|
96
99
|
AlignWith: variable
|
97
100
|
|
98
|
-
# Do not always align parameters when it is easier to read
|
99
|
-
AlignParameters:
|
100
|
-
Exclude:
|
101
|
-
- spec/**/*_spec.rb
|
102
|
-
|
103
101
|
# Prefer #kind_of? over #is_a?
|
104
102
|
ClassCheck:
|
105
103
|
EnforcedStyle: kind_of?
|
@@ -135,8 +133,47 @@ ParallelAssignment:
|
|
135
133
|
|
136
134
|
# Allow additional specs
|
137
135
|
ExtraSpacing:
|
138
|
-
|
136
|
+
AllowForAlignment: true
|
139
137
|
|
140
138
|
# Buggy
|
141
139
|
FormatParameterMismatch:
|
142
140
|
Enabled: false
|
141
|
+
|
142
|
+
# Different preference
|
143
|
+
SignalException:
|
144
|
+
EnforcedStyle: semantic
|
145
|
+
|
146
|
+
# Do not use `alias`
|
147
|
+
Alias:
|
148
|
+
EnforcedStyle: prefer_alias_method
|
149
|
+
|
150
|
+
# Teaching people to ignore singleton class is pointless
|
151
|
+
RedundantFreeze:
|
152
|
+
Enabled: false
|
153
|
+
|
154
|
+
# Do not waste my horizontal or vertical space
|
155
|
+
IndentArray:
|
156
|
+
Enabled: false
|
157
|
+
|
158
|
+
# Prefer
|
159
|
+
#
|
160
|
+
# some_receiver
|
161
|
+
# .foo
|
162
|
+
# .bar
|
163
|
+
# .baz
|
164
|
+
#
|
165
|
+
# Over
|
166
|
+
#
|
167
|
+
# some_receiver.foo
|
168
|
+
# .bar
|
169
|
+
# .baz
|
170
|
+
MultilineMethodCallIndentation:
|
171
|
+
EnforcedStyle: indented
|
172
|
+
|
173
|
+
# Align keys and values in a multiline hash
|
174
|
+
AlignHash:
|
175
|
+
EnforcedColonStyle: table
|
176
|
+
|
177
|
+
# Prefer `public_send` and `__send__` over `send`
|
178
|
+
Send:
|
179
|
+
Enabled: true
|