simplecov-ruby / simplecov

Code coverage for Ruby with a powerful configuration library and automatic merging of coverage across test suites
MIT License
4.77k stars 552 forks source link

Subprocess at_fork doesn't seem to work #984

Open artagnon opened 3 years ago

artagnon commented 3 years ago

I'm using simplecov with minitest to generate coverage reports. I have the following code I want subprocess coverage for:

  def test_httpd
    Dir.mktmpdir do |dir|
      Clayoven::Init.init dir
      Dir.chdir dir do
        pid = fork { Clayoven::Httpd.start }
        sleep 1
        out, = capture_subprocess_io { system 'curl http://localhost:8000/index.html' }
        Process.kill 'INT', pid
        Process.waitall
        assert_equal out.include?('Enjoy using clayoven!'), true
      end
    end
  end

Unfortunately, even with enable_for_subprocess and at_fork configured as follows in my .simplecov:

SimpleCov.start do
  enable_coverage :branch
  primary_coverage :branch
  add_filter %r{^/test/}
  enable_for_subprocesses true
  at_fork do |pid|
    start do
      command_name "#{command_name} (subprocess: #{pid})"
      print_error_status false
      formatter SimpleCov::Formatter::SimpleFormatter
      minimum_coverage 0
    end
  end
end

I don't get subprocess coverage. Is this because I'm killing the subprocess instead of waiting for it to finish (it never finishes)? Is there a way around this?

EDIT: It's not because of Process.kill. It doesn't seem to work for a fork-wait either:

  def test_noinit
    Dir.mktmpdir do |dir|
      Dir.chdir dir do
        pid = fork { Clayoven::Toplevel.main }
        Process.wait pid
        assert_equal $?.success?, false, 'clayoven did not abort with non-zero exit status'
      end
    end
  end
HoneyryderChuck commented 2 years ago

I'm also experiencing the same issue.

alec-c4 commented 1 year ago

Any updates? I met the same problem :(

dcunning commented 1 year ago

I ran into the same issue. The heart of my issue was the Dir.chdir, simplecov generates the coverage report within that directory so it's never merged into the full coverage report.

The fix was using #root and #coverage_dir to point simplecov to back the right spot:

# Within my tests
pwd = Dir.pwd
Dir.chdir "somedir" do
  Open3.capture3({ "SIMPLECOV_ROOT" => pwd }, "bin/my-command")
end

# .simplecov
SimpleCov.start do
  root ENV["SIMPLECOV_ROOT"] || Dir.pwd
  coverage_dir File.join(root, "coverage")
end