henitai 0.1.0 → 0.1.1

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: 586e777c1eb78b5345eedde4f010ab262fe1ced6e0ac3714e21dbd9aa7cc63d3
4
- data.tar.gz: 7d6d5d3939777b28ab127133dc4f2d9663c29c812f6f4a77af4705a3f36ef973
3
+ metadata.gz: bb30ced7751d8a102dbfe3a5eebdb33235997723d6b2f9c7f6e5c43a02eb09b6
4
+ data.tar.gz: 6386ce164d48f3527f5fa042595c4218e8b508b5d7a64a255a37e74b4696b867
5
5
  SHA512:
6
- metadata.gz: 0fd445f2506b0dec762413e3e992af6b93797728c4253a86de2e1ce0f60fcd189ac2d2f342033ac8d16653064ce3fc3cd885c69ad34026e9781c60ca88d85de4
7
- data.tar.gz: 9d00b7d9f3237b70460306aae62729d38e0142fbf7b954c2b4528feda3a4e596f08bd373c9ed448fd0ff12de7c5c1fb867c3ea9f8cf8582792a9c3a454d2bfd5
6
+ metadata.gz: 5c6463df3bd0184d655aedf48110635fa7706e161ef41c2a1305a738d2499713a4fd522e7a540f87900fac181cc10526fef4eadb541951d079a877c70762f4de
7
+ data.tar.gz: 16e16613e3c3055105685f73a0832f9aa4ce401f254710af391ef6d5c1983d3a7ecaec44ae7b5c1976bfa8a8714a7a8e1951050aa49c034d1afb817e9812817d
data/CHANGELOG.md CHANGED
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.1.1] - 2026-04-03
11
+
12
+ ### Added
13
+ - Minitest integration for Rails projects: injects SimpleCov for coverage
14
+ collection, sets `RAILS_ENV=test` and `PARALLEL_WORKERS=1` in the baseline
15
+ subprocess, preloads `config/environment.rb` before mutant activation, adds
16
+ `test/` to `$LOAD_PATH` before forking, and excludes `test/system/` by default
17
+ - `simplecov` runtime dependency (required by the Minitest integration)
18
+
19
+ ### Fixed
20
+ - `rspec/core` was unconditionally required at load time, causing a `LoadError`
21
+ in projects that do not have RSpec installed — now loaded lazily only when the
22
+ RSpec integration is used
23
+ - Coverage path normalisation now uses `File.realpath` so symlinked temp
24
+ directories on macOS no longer cause false no-coverage results
25
+
26
+ ## [0.1.0] - 2026-03-01
27
+
10
28
  ### Added
11
29
  - Initial gem scaffold with Ruby 4.0.2 support
12
30
  - Dev Container configuration (official `ruby:4.0.2-alpine` base image, Codex CLI preinstalled)
@@ -16,4 +34,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
16
34
  - CLI critical path: `henitai run` now executes the full pipeline, supports `--since`, returns CI-friendly exit codes, and `henitai version` prints `Henitai::VERSION`
17
35
  - RSpec per-test coverage output: `henitai/coverage_formatter` now writes `coverage/henitai_per_test.json`
18
36
 
19
- [Unreleased]: https://github.com/martinotten/henitai/commits/main
37
+ [Unreleased]: https://github.com/martinotten/henitai/compare/v0.1.1...HEAD
38
+ [0.1.1]: https://github.com/martinotten/henitai/compare/v0.1.0...v0.1.1
39
+ [0.1.0]: https://github.com/martinotten/henitai/releases/tag/v0.1.0
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "fileutils"
4
4
  require "minitest"
5
- require "rspec/core"
6
5
 
7
6
  module Henitai
8
7
  # Namespace for test-framework integrations.
@@ -224,6 +223,7 @@ module Henitai
224
223
  end
225
224
 
226
225
  def run_tests(test_files)
226
+ require "rspec/core"
227
227
  status = RSpec::Core::Runner.run(test_files + rspec_options)
228
228
  return status if status.is_a?(Integer)
229
229
 
@@ -391,10 +391,33 @@ module Henitai
391
391
  # runner. Minitest shares selection and execution semantics, but per-test
392
392
  # coverage collection is not yet wired into this path.
393
393
  class Minitest < Rspec
394
+ def run_mutant(mutant:, test_files:, timeout:)
395
+ setup_load_path
396
+ super
397
+ end
398
+
399
+ def run_in_child(mutant:, test_files:, log_paths:)
400
+ ENV["RAILS_ENV"] = "test" unless ENV["RAILS_ENV"] == "test"
401
+ preload_environment
402
+ super
403
+ end
404
+
405
+ def run_suite(test_files, timeout: DEFAULT_SUITE_TIMEOUT)
406
+ log_paths = scenario_log_paths("baseline")
407
+ FileUtils.mkdir_p(File.dirname(log_paths[:stdout_path]))
408
+ pid = File.open(log_paths[:stdout_path], "w") do |stdout_file|
409
+ File.open(log_paths[:stderr_path], "w") do |stderr_file|
410
+ Process.spawn(subprocess_env, *suite_command(test_files), out: stdout_file, err: stderr_file)
411
+ end
412
+ end
413
+ build_result(wait_with_timeout(pid, timeout), log_paths)
414
+ end
415
+
394
416
  private
395
417
 
396
418
  def suite_command(test_files)
397
419
  ["bundle", "exec", "ruby", "-I", "test",
420
+ "-r", "henitai/minitest_simplecov",
398
421
  "-e", "ARGV.each { |f| require File.expand_path(f) }",
399
422
  *test_files]
400
423
  end
@@ -409,8 +432,26 @@ module Henitai
409
432
  status == true ? 0 : 1
410
433
  end
411
434
 
435
+ def preload_environment
436
+ env_file = File.expand_path("config/environment.rb")
437
+ require env_file if File.exist?(env_file)
438
+ end
439
+
440
+ def setup_load_path
441
+ test_dir = File.expand_path("test")
442
+ $LOAD_PATH.unshift(test_dir) unless $LOAD_PATH.include?(test_dir)
443
+ end
444
+
445
+ def subprocess_env
446
+ env = {} # : Hash[String, String]
447
+ env["RAILS_ENV"] = "test" unless ENV["RAILS_ENV"] == "test"
448
+ env["PARALLEL_WORKERS"] = "1"
449
+ env
450
+ end
451
+
412
452
  def spec_files
413
- Dir.glob("test/**/*_test.rb") + Dir.glob("test/**/*_spec.rb")
453
+ (Dir.glob("test/**/*_test.rb") + Dir.glob("test/**/*_spec.rb"))
454
+ .reject { |f| f.start_with?("test/system/") }
414
455
  end
415
456
  end
416
457
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Injected by henitai into the Minitest baseline subprocess to collect
4
+ # line coverage and write it as a SimpleCov-compatible .resultset.json.
5
+ #
6
+ # Must be required before any application code is loaded so that Coverage
7
+ # tracking is active from the first line.
8
+
9
+ require "simplecov"
10
+
11
+ SimpleCov.coverage_dir(ENV.fetch("HENITAI_COVERAGE_DIR", "coverage"))
12
+ SimpleCov.start
@@ -147,7 +147,10 @@ module Henitai
147
147
  end
148
148
 
149
149
  def normalize_path(path)
150
- File.expand_path(path)
150
+ expanded = File.expand_path(path)
151
+ File.realpath(expanded)
152
+ rescue Errno::ENOENT, Errno::ENOTDIR
153
+ expanded
151
154
  end
152
155
 
153
156
  def equivalence_detector
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Henitai
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
data/sig/henitai.rbs CHANGED
@@ -282,9 +282,17 @@ module Henitai
282
282
  end
283
283
 
284
284
  class Minitest < Rspec
285
+ def run_mutant: (mutant: Mutant, test_files: Array[String], timeout: Float) -> ScenarioExecutionResult
286
+ def run_suite: (Array[String], ?timeout: Float) -> ScenarioExecutionResult
287
+
285
288
  private
286
289
 
290
+ def run_in_child: (mutant: Mutant, test_files: Array[String], log_paths: Hash[Symbol, String]) -> Integer
291
+ def suite_command: (Array[String]) -> Array[String]
287
292
  def run_tests: (Array[String]) -> Integer
293
+ def preload_environment: () -> void
294
+ def setup_load_path: () -> void
295
+ def subprocess_env: () -> Hash[String, String]
288
296
  def spec_files: () -> Array[String]
289
297
  end
290
298
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: henitai
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Otten
@@ -23,6 +23,20 @@ dependencies:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
25
  version: '1.5'
26
+ - !ruby/object:Gem::Dependency
27
+ name: simplecov
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '0.22'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.22'
26
40
  - !ruby/object:Gem::Dependency
27
41
  name: sqlite3
28
42
  requirement: !ruby/object:Gem::Requirement
@@ -83,6 +97,7 @@ files:
83
97
  - lib/henitai/execution_engine.rb
84
98
  - lib/henitai/git_diff_analyzer.rb
85
99
  - lib/henitai/integration.rb
100
+ - lib/henitai/minitest_simplecov.rb
86
101
  - lib/henitai/mutant.rb
87
102
  - lib/henitai/mutant/activator.rb
88
103
  - lib/henitai/mutant_generator.rb
@@ -131,7 +146,7 @@ metadata:
131
146
  changelog_uri: https://github.com/martinotten/henitai/blob/main/CHANGELOG.md
132
147
  documentation_uri: https://github.com/martinotten/henitai/blob/main/README.md
133
148
  homepage_uri: https://github.com/martinotten/henitai
134
- source_code_uri: https://github.com/martinotten/henitai/tree/v0.1.0
149
+ source_code_uri: https://github.com/martinotten/henitai/tree/v0.1.1
135
150
  rubygems_mfa_required: 'true'
136
151
  rdoc_options: []
137
152
  require_paths: