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.
Files changed (254) hide show
  1. checksums.yaml +4 -4
  2. data/bin/mutant +16 -11
  3. data/lib/mutant.rb +8 -4
  4. data/lib/mutant/bootstrap.rb +14 -1
  5. data/lib/mutant/cli.rb +9 -162
  6. data/lib/mutant/cli/command.rb +196 -0
  7. data/lib/mutant/cli/command/root.rb +13 -0
  8. data/lib/mutant/cli/command/run.rb +151 -0
  9. data/lib/mutant/cli/command/subscription.rb +54 -0
  10. data/lib/mutant/expression.rb +0 -1
  11. data/lib/mutant/isolation.rb +1 -1
  12. data/lib/mutant/isolation/fork.rb +2 -2
  13. data/lib/mutant/isolation/none.rb +1 -1
  14. data/lib/mutant/license.rb +9 -35
  15. data/lib/mutant/license/subscription.rb +31 -9
  16. data/lib/mutant/license/subscription/commercial.rb +2 -4
  17. data/lib/mutant/license/subscription/opensource.rb +7 -7
  18. data/lib/mutant/matcher/config.rb +2 -0
  19. data/lib/mutant/meta/example.rb +16 -4
  20. data/lib/mutant/meta/example/dsl.rb +33 -16
  21. data/lib/mutant/meta/example/verification.rb +70 -28
  22. data/lib/mutant/minitest/coverage.rb +53 -0
  23. data/lib/mutant/mutator/node.rb +2 -2
  24. data/lib/mutant/mutator/node/block_pass.rb +29 -0
  25. data/lib/mutant/mutator/node/{dstr.rb → dynamic_literal.rb} +7 -5
  26. data/lib/mutant/mutator/node/index.rb +4 -4
  27. data/lib/mutant/mutator/node/literal/range.rb +5 -2
  28. data/lib/mutant/mutator/node/named_value/variable_assignment.rb +1 -1
  29. data/lib/mutant/mutator/node/noop.rb +1 -1
  30. data/lib/mutant/mutator/node/op_asgn.rb +15 -1
  31. data/lib/mutant/mutator/node/send.rb +25 -1
  32. data/lib/mutant/mutator/node/send/attribute_assignment.rb +1 -0
  33. data/lib/mutant/reporter/cli/printer/isolation_result.rb +9 -3
  34. data/lib/mutant/subject/method/instance.rb +1 -1
  35. data/lib/mutant/version.rb +1 -1
  36. metadata +18 -336
  37. data/.github/workflows/ci.yml +0 -121
  38. data/.gitignore +0 -38
  39. data/.rspec +0 -5
  40. data/.rubocop.yml +0 -210
  41. data/Changelog.md +0 -87
  42. data/Gemfile +0 -7
  43. data/Gemfile.lock +0 -107
  44. data/Gemfile.shared +0 -10
  45. data/README.md +0 -199
  46. data/Rakefile +0 -5
  47. data/config/devtools.yml +0 -2
  48. data/config/reek.yml +0 -139
  49. data/config/yardstick.yml +0 -2
  50. data/docs/commercial-support.md +0 -14
  51. data/docs/concurrency.md +0 -39
  52. data/docs/incremental.md +0 -76
  53. data/docs/known-problems.md +0 -30
  54. data/docs/limitations.md +0 -50
  55. data/docs/mutant-minitest.md +0 -149
  56. data/docs/mutant-rspec.md +0 -130
  57. data/docs/nomenclature.md +0 -82
  58. data/docs/reading-reports.md +0 -74
  59. data/lib/mutant/mutator/node/dsym.rb +0 -22
  60. data/meta/and.rb +0 -13
  61. data/meta/and_asgn.rb +0 -14
  62. data/meta/array.rb +0 -27
  63. data/meta/begin.rb +0 -20
  64. data/meta/block.rb +0 -199
  65. data/meta/block_pass.rb +0 -8
  66. data/meta/blockarg.rb +0 -10
  67. data/meta/break.rb +0 -9
  68. data/meta/case.rb +0 -217
  69. data/meta/casgn.rb +0 -25
  70. data/meta/cbase.rb +0 -8
  71. data/meta/class.rb +0 -12
  72. data/meta/const.rb +0 -17
  73. data/meta/csend.rb +0 -10
  74. data/meta/cvar.rb +0 -7
  75. data/meta/cvasgn.rb +0 -9
  76. data/meta/date.rb +0 -59
  77. data/meta/def.rb +0 -196
  78. data/meta/defined.rb +0 -9
  79. data/meta/dstr.rb +0 -13
  80. data/meta/dsym.rb +0 -14
  81. data/meta/ensure.rb +0 -8
  82. data/meta/false.rb +0 -7
  83. data/meta/file.rb +0 -5
  84. data/meta/float.rb +0 -37
  85. data/meta/gvar.rb +0 -7
  86. data/meta/gvasgn.rb +0 -9
  87. data/meta/hash.rb +0 -20
  88. data/meta/if.rb +0 -72
  89. data/meta/index.rb +0 -133
  90. data/meta/indexasgn.rb +0 -31
  91. data/meta/int.rb +0 -18
  92. data/meta/ivar.rb +0 -8
  93. data/meta/ivasgn.rb +0 -22
  94. data/meta/kwarg.rb +0 -10
  95. data/meta/kwbegin.rb +0 -8
  96. data/meta/kwoptarg.rb +0 -13
  97. data/meta/lambda.rb +0 -23
  98. data/meta/line.rb +0 -5
  99. data/meta/lvar.rb +0 -16
  100. data/meta/lvasgn.rb +0 -24
  101. data/meta/masgn.rb +0 -7
  102. data/meta/match_current_line.rb +0 -14
  103. data/meta/next.rb +0 -10
  104. data/meta/nil.rb +0 -5
  105. data/meta/nthref.rb +0 -14
  106. data/meta/op_assgn.rb +0 -17
  107. data/meta/or.rb +0 -13
  108. data/meta/or_asgn.rb +0 -50
  109. data/meta/range.rb +0 -65
  110. data/meta/redo.rb +0 -5
  111. data/meta/regexp.rb +0 -80
  112. data/meta/regopt.rb +0 -10
  113. data/meta/rescue.rb +0 -84
  114. data/meta/return.rb +0 -16
  115. data/meta/sclass.rb +0 -12
  116. data/meta/self.rb +0 -7
  117. data/meta/send.rb +0 -600
  118. data/meta/str.rb +0 -7
  119. data/meta/super.rb +0 -27
  120. data/meta/sym.rb +0 -8
  121. data/meta/true.rb +0 -7
  122. data/meta/until.rb +0 -16
  123. data/meta/while.rb +0 -24
  124. data/meta/yield.rb +0 -9
  125. data/mutant-minitest.gemspec +0 -22
  126. data/mutant-rspec.gemspec +0 -22
  127. data/mutant.gemspec +0 -44
  128. data/mutant.sh +0 -12
  129. data/mutant.yml +0 -6
  130. data/spec/integration/mutant/corpus_spec.rb +0 -15
  131. data/spec/integration/mutant/isolation/fork_spec.rb +0 -28
  132. data/spec/integration/mutant/minitest_spec.rb +0 -11
  133. data/spec/integration/mutant/null_spec.rb +0 -16
  134. data/spec/integration/mutant/rspec_spec.rb +0 -15
  135. data/spec/integration/mutant/test_mutator_handles_types_spec.rb +0 -9
  136. data/spec/integrations.yml +0 -63
  137. data/spec/shared/framework_integration_behavior.rb +0 -70
  138. data/spec/shared/method_matcher_behavior.rb +0 -47
  139. data/spec/spec_helper.rb +0 -90
  140. data/spec/support/corpus.rb +0 -318
  141. data/spec/support/file_system.rb +0 -62
  142. data/spec/support/ice_nine_config.rb +0 -10
  143. data/spec/support/ruby_vm.rb +0 -84
  144. data/spec/support/shared_context.rb +0 -169
  145. data/spec/support/xspec.rb +0 -183
  146. data/spec/unit/mutant/ast/find_metaclass_containing_spec.rb +0 -64
  147. data/spec/unit/mutant/ast/meta/optarg_spec.rb +0 -24
  148. data/spec/unit/mutant/ast/meta/send/proc_predicate_spec.rb +0 -30
  149. data/spec/unit/mutant/ast/meta/send/receiver_possible_top_level_const_predicate_spec.rb +0 -39
  150. data/spec/unit/mutant/ast/meta/send_spec.rb +0 -42
  151. data/spec/unit/mutant/ast/named_children_spec.rb +0 -89
  152. data/spec/unit/mutant/ast/sexp_spec.rb +0 -38
  153. data/spec/unit/mutant/ast_spec.rb +0 -57
  154. data/spec/unit/mutant/bootstrap_spec.rb +0 -216
  155. data/spec/unit/mutant/cli_spec.rb +0 -305
  156. data/spec/unit/mutant/clock_monotonic_spec.rb +0 -52
  157. data/spec/unit/mutant/config_spec.rb +0 -126
  158. data/spec/unit/mutant/context_spec.rb +0 -111
  159. data/spec/unit/mutant/env_spec.rb +0 -229
  160. data/spec/unit/mutant/expression/method_spec.rb +0 -62
  161. data/spec/unit/mutant/expression/methods_spec.rb +0 -66
  162. data/spec/unit/mutant/expression/namespace/exact_spec.rb +0 -28
  163. data/spec/unit/mutant/expression/namespace/recursive_spec.rb +0 -66
  164. data/spec/unit/mutant/expression/parser_spec.rb +0 -65
  165. data/spec/unit/mutant/expression_spec.rb +0 -45
  166. data/spec/unit/mutant/integration/rspec_spec.rb +0 -201
  167. data/spec/unit/mutant/integration_spec.rb +0 -150
  168. data/spec/unit/mutant/isolation/fork_spec.rb +0 -309
  169. data/spec/unit/mutant/isolation/none_spec.rb +0 -23
  170. data/spec/unit/mutant/isolation/result_spec.rb +0 -73
  171. data/spec/unit/mutant/license_spec.rb +0 -305
  172. data/spec/unit/mutant/loader_spec.rb +0 -79
  173. data/spec/unit/mutant/matcher/chain_spec.rb +0 -26
  174. data/spec/unit/mutant/matcher/compiler_spec.rb +0 -0
  175. data/spec/unit/mutant/matcher/config_spec.rb +0 -47
  176. data/spec/unit/mutant/matcher/filter_spec.rb +0 -22
  177. data/spec/unit/mutant/matcher/method/instance_spec.rb +0 -164
  178. data/spec/unit/mutant/matcher/method/metaclass_spec.rb +0 -108
  179. data/spec/unit/mutant/matcher/method/singleton_spec.rb +0 -90
  180. data/spec/unit/mutant/matcher/methods/instance_spec.rb +0 -54
  181. data/spec/unit/mutant/matcher/methods/metaclass_spec.rb +0 -62
  182. data/spec/unit/mutant/matcher/methods/singleton_spec.rb +0 -51
  183. data/spec/unit/mutant/matcher/namespace_spec.rb +0 -39
  184. data/spec/unit/mutant/matcher/null_spec.rb +0 -12
  185. data/spec/unit/mutant/matcher/scope_spec.rb +0 -45
  186. data/spec/unit/mutant/matcher/static_spec.rb +0 -13
  187. data/spec/unit/mutant/matcher_spec.rb +0 -102
  188. data/spec/unit/mutant/meta/example/dsl_spec.rb +0 -108
  189. data/spec/unit/mutant/meta/example/verification_spec.rb +0 -154
  190. data/spec/unit/mutant/meta/example_spec.rb +0 -34
  191. data/spec/unit/mutant/mutation_spec.rb +0 -140
  192. data/spec/unit/mutant/mutator/node_spec.rb +0 -47
  193. data/spec/unit/mutant/mutator_spec.rb +0 -21
  194. data/spec/unit/mutant/parallel/driver_spec.rb +0 -126
  195. data/spec/unit/mutant/parallel/source/array_spec.rb +0 -57
  196. data/spec/unit/mutant/parallel/worker_spec.rb +0 -206
  197. data/spec/unit/mutant/parallel_spec.rb +0 -115
  198. data/spec/unit/mutant/parser_spec.rb +0 -26
  199. data/spec/unit/mutant/range_spec.rb +0 -141
  200. data/spec/unit/mutant/registry_spec.rb +0 -74
  201. data/spec/unit/mutant/reporter/cli/printer/config_spec.rb +0 -17
  202. data/spec/unit/mutant/reporter/cli/printer/env_progress_spec.rb +0 -85
  203. data/spec/unit/mutant/reporter/cli/printer/env_result_spec.rb +0 -45
  204. data/spec/unit/mutant/reporter/cli/printer/isolation_result_spec.rb +0 -132
  205. data/spec/unit/mutant/reporter/cli/printer/mutation_progress_result_spec.rb +0 -25
  206. data/spec/unit/mutant/reporter/cli/printer/mutation_result_spec.rb +0 -153
  207. data/spec/unit/mutant/reporter/cli/printer/status_progressive_spec.rb +0 -45
  208. data/spec/unit/mutant/reporter/cli/printer/subject_progress_spec.rb +0 -36
  209. data/spec/unit/mutant/reporter/cli/printer/subject_result_spec.rb +0 -44
  210. data/spec/unit/mutant/reporter/cli/printer/test_result_spec.rb +0 -16
  211. data/spec/unit/mutant/reporter/cli/printer_spec.rb +0 -163
  212. data/spec/unit/mutant/reporter/cli_spec.rb +0 -137
  213. data/spec/unit/mutant/reporter/null_spec.rb +0 -14
  214. data/spec/unit/mutant/reporter/sequence_spec.rb +0 -31
  215. data/spec/unit/mutant/repository/diff/ranges_spec.rb +0 -180
  216. data/spec/unit/mutant/repository/diff_spec.rb +0 -122
  217. data/spec/unit/mutant/repository/subject_filter_spec.rb +0 -30
  218. data/spec/unit/mutant/require_highjack_spec.rb +0 -73
  219. data/spec/unit/mutant/result/class_methods_spec.rb +0 -51
  220. data/spec/unit/mutant/result/env_spec.rb +0 -161
  221. data/spec/unit/mutant/result/mutation_spec.rb +0 -70
  222. data/spec/unit/mutant/result/subject_spec.rb +0 -111
  223. data/spec/unit/mutant/result/test_spec.rb +0 -14
  224. data/spec/unit/mutant/result_spec.rb +0 -33
  225. data/spec/unit/mutant/runner/sink_spec.rb +0 -174
  226. data/spec/unit/mutant/runner_spec.rb +0 -121
  227. data/spec/unit/mutant/selector/expression_spec.rb +0 -62
  228. data/spec/unit/mutant/selector/null_spec.rb +0 -17
  229. data/spec/unit/mutant/subject/method/instance_spec.rb +0 -276
  230. data/spec/unit/mutant/subject/method/metaclass_spec.rb +0 -63
  231. data/spec/unit/mutant/subject/method/singleton_spec.rb +0 -61
  232. data/spec/unit/mutant/subject_spec.rb +0 -93
  233. data/spec/unit/mutant/transform/array_spec.rb +0 -92
  234. data/spec/unit/mutant/transform/bool_spec.rb +0 -63
  235. data/spec/unit/mutant/transform/error_spec.rb +0 -132
  236. data/spec/unit/mutant/transform/exception_spec.rb +0 -44
  237. data/spec/unit/mutant/transform/hash_spec.rb +0 -236
  238. data/spec/unit/mutant/transform/index_spec.rb +0 -92
  239. data/spec/unit/mutant/transform/named_spec.rb +0 -49
  240. data/spec/unit/mutant/transform/primitive_spec.rb +0 -56
  241. data/spec/unit/mutant/transform/sequence_spec.rb +0 -98
  242. data/spec/unit/mutant/util/one_spec.rb +0 -22
  243. data/spec/unit/mutant/warnings_spec.rb +0 -89
  244. data/spec/unit/mutant/world_spec.rb +0 -63
  245. data/spec/unit/mutant/zombifier_spec.rb +0 -122
  246. data/test_app/.rspec +0 -1
  247. data/test_app/Gemfile.minitest +0 -6
  248. data/test_app/Gemfile.rspec3.8 +0 -7
  249. data/test_app/lib/test_app.rb +0 -114
  250. data/test_app/lib/test_app/literal.rb +0 -35
  251. data/test_app/lib/test_app/metaclasses.rb +0 -108
  252. data/test_app/spec/spec_helper.rb +0 -9
  253. data/test_app/spec/unit/test_app/literal_spec.rb +0 -20
  254. data/test_app/test/unit/test_app/literal_test.rb +0 -16
@@ -1,2 +0,0 @@
1
- ---
2
- threshold: 100
@@ -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.
@@ -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.
@@ -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.
@@ -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)
@@ -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
- ```
@@ -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.
@@ -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
- ```