mutineer 0.6.1 → 0.6.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 88e7dbea9ba80b3fed23d634e30830372c89e2f42cf7403d8fa5860d80ba17dd
4
- data.tar.gz: ac519c7e8c6e301e46242af5bd6a94672aa0a95f2d8dc46dfbd5e3b2611c366c
3
+ metadata.gz: b549b3640aa316aa715732f4e91f3be669b7ab8e7ad877b8207d0e31ac12b4aa
4
+ data.tar.gz: a626241007cf47b4fb0ef3c68dc1fba7f0c8679d0c41db516dca888893fc5f51
5
5
  SHA512:
6
- metadata.gz: 5e49d3e6fef7dddc74b93c6e1216a5740e556f0c9b1ba1d684cc28b61c3f464063669ad04468dc0d0882a1a141050d62c96e6f9995b8b0e541f38e94d9fbac7a
7
- data.tar.gz: d70b8231caef83f5b55a9ee840cb77cdf16b8c93c8f227d7f278266db44584577eb17ca589eba677d3896dceae03b8e71a43f8b7747f7046060aa659d9b55d58
6
+ metadata.gz: ba4d45a6ba52ead7da7f580452eb610bfc23b368501c496e80ffa56e2e364a62fcf896a1e9d37c50b1216727eb8a6a02386ba0917c85397ac61a3f2a9f41d694
7
+ data.tar.gz: 6be383459b367be9b72135b1672d57c63bd4e4a6c032c3301532f50a1bcb96dff2cc6ecf764979d6009fab9e4c1e4d327fbb1e81cf3652232cb38a2eb6a82558
data/CHANGELOG.md CHANGED
@@ -4,6 +4,20 @@ All notable changes to this project are documented here. The format is based on
4
4
  [Keep a Changelog](https://keepachangelog.com/), and this project adheres to
5
5
  [Semantic Versioning](https://semver.org/).
6
6
 
7
+ ## [0.6.2] - 2026-06-29
8
+
9
+ ### Fixed
10
+ - **`--rails` defaults `RAILS_ENV` to `test`** (#7) — an unset `RAILS_ENV` booted
11
+ development, where the suite isn't loaded, so every mutant was falsely reported
12
+ `no_coverage` (score N/A, exit 0). An explicit `RAILS_ENV` is respected.
13
+ - **`--rails` defaults to `--jobs 1`** (#12) — parallel mutant forks share one
14
+ database and deadlock on transactional fixtures; explicit `--jobs N` opts back
15
+ into parallelism.
16
+
17
+ ### Added
18
+ - **Tier-2 operator discoverability** (#14) — the human-format run summary now
19
+ lists the available opt-in tier-2 operators and how to enable them.
20
+
7
21
  ## [0.6.1] - 2026-06-29
8
22
 
9
23
  ### Changed
@@ -86,6 +100,7 @@ All notable changes to this project are documented here. The format is based on
86
100
  - `.mutineer.yml` configuration (CLI > config > default precedence).
87
101
  - Byte-correct source handling for multibyte (UTF-8) sources.
88
102
 
103
+ [0.6.2]: https://github.com/davidteren/mutineer/releases/tag/v0.6.2
89
104
  [0.6.1]: https://github.com/davidteren/mutineer/releases/tag/v0.6.1
90
105
  [0.6.0]: https://github.com/davidteren/mutineer/releases/tag/v0.6.0
91
106
  [0.5.0]: https://github.com/davidteren/mutineer/releases/tag/v0.5.0
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Mutineer
2
2
 
3
+ [![Socket Badge](https://badge.socket.dev/rubygems/package/mutineer/0.6.2?platform=ruby)](https://socket.dev/rubygems/package/mutineer/overview/0.6.2?platform=ruby)
4
+
3
5
  A clean-room mutation-testing tool for Ruby. Mutineer mutates your source one
4
6
  change at a time, runs your test suite (Minitest or RSpec) against each mutant, and reports the
5
7
  ones your tests failed to catch — the gaps where your suite isn't actually
data/lib/mutineer/cli.rb CHANGED
@@ -257,9 +257,27 @@ module Mutineer
257
257
  reporter = Reporter.new(aggregate, source_map)
258
258
  reporter.report(out: $stdout, err: $stderr, threshold: config.threshold,
259
259
  format: config.format, output: config.output)
260
+
261
+ # #14: nudge toward the opt-in tier-2 operators (human report only — never
262
+ # pollute JSON output).
263
+ if config.format != "json" && (hint = tier2_hint(config.operators))
264
+ puts hint
265
+ end
266
+
260
267
  exit reporter.exit_code(threshold: config.threshold)
261
268
  end
262
269
 
270
+ # The tier-2 operators not in the active set, as a one-line hint (or nil when
271
+ # they're all already enabled). `active` nil means the default (Tier-1) set.
272
+ def self.tier2_hint(active)
273
+ active ||= MutatorRegistry::DEFAULT_NAMES
274
+ unused = MutatorRegistry::TIER2_NAMES - active
275
+ return if unused.empty?
276
+
277
+ "#{unused.size} tier-2 operators available (#{unused.join(', ')}) — " \
278
+ "enable with --operators <list>."
279
+ end
280
+
263
281
  def self.dry_run(config)
264
282
  operator_classes = MutatorRegistry.resolve(config.operators || MutatorRegistry::DEFAULT_NAMES)
265
283
  sources = {}
@@ -108,6 +108,11 @@ module Mutineer
108
108
  if config.rails
109
109
  config.boot ||= "config/environment"
110
110
  config.strategy = "redefine" unless explicit.include?(:strategy)
111
+ # #12: parallel mutant forks share one database; transactional-fixture
112
+ # setup/teardown across processes contends and deadlocks. Default to
113
+ # serial under --rails; an explicit --jobs N opts back into parallelism
114
+ # (with the per-worker DB-isolation that implies).
115
+ config.jobs = 1 unless explicit.include?(:jobs)
111
116
  end
112
117
 
113
118
  # Auto-detect the framework only when neither CLI nor config file set it
@@ -40,6 +40,11 @@ module Mutineer
40
40
  # parse that needs nothing loaded. Standalone mode requires the sources as
41
41
  # before so their classes exist for the children to inherit.
42
42
  if config.boot
43
+ # #7: under --rails an unset RAILS_ENV boots development, where the test
44
+ # suite isn't loaded — coverage comes back empty and EVERY mutant is
45
+ # falsely reported no_coverage (score N/A, exit 0). Default it to test.
46
+ ensure_rails_env(config)
47
+
43
48
  # Coverage instruments only files loaded AFTER it starts. Start it BEFORE
44
49
  # the boot require so the entire app loaded during boot is instrumented;
45
50
  # forked children then measure each test's coverage delta against it.
@@ -152,6 +157,17 @@ module Mutineer
152
157
  end.uniq
153
158
  end
154
159
 
160
+ # #7: when --rails is on and RAILS_ENV is unset, default it to "test" (and
161
+ # say so) before the app boots — otherwise it boots development and nothing
162
+ # is measured. An explicitly-set RAILS_ENV is always respected.
163
+ def self.ensure_rails_env(config)
164
+ return unless config.rails
165
+ return unless ENV["RAILS_ENV"].nil? || ENV["RAILS_ENV"].empty?
166
+
167
+ ENV["RAILS_ENV"] = "test"
168
+ warn "[mutineer] RAILS_ENV was unset; defaulting to 'test' for --rails."
169
+ end
170
+
155
171
  def self.sweep_orphans(dirs)
156
172
  dirs.each do |dir|
157
173
  Dir.glob(File.join(dir, "mutineer_mutant*.rb")).each do |f|
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mutineer
4
- VERSION = "0.6.1"
4
+ VERSION = "0.6.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mutineer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Teren