Hi,
when using simplecov I get 100 % code coverage except for the version.rb which is located in lib/<namespace>/<gemname>/version.rb:
module Namespace
module Core
VERSION = "X.X.X"
end
end
My rspec test runs successful with the following but simplecov does not consider that:
module Namespace
describe Core do
it "has correct version number" do
expect(Namespace::Core::VERSION).to eq "X.X.X"
end
end
end
How can I test that so that I also get a code coverage of 100 % for the complete gem? Any idea?
Thanks in advance
Steffen
Versions:
ruby 2.3.3
rails 5.0.1 (api only)
rspec-rails 3.5.2
simplecov 0.12.0
Hi there!
Umm gotta take a look at that. I thought this works, e.g. you wouldn't even have to test it but it's just executed (the constant) and hence was covered. Need to check it out on one of my projects.
Worst case you could surround it with # :nocov: (as shown in the README).
is your lib open source to take a look?
It should indeed be covered correctly just as expected. @steffenschmidt Could you try to upgrade to the latest simplecov 0.13 to see if that possibly works? I wouldn't expect so though. Also, possibly your 'version' file is required before simplecov is required and started? That would put it out of the view of the STDLIB Coverage library simplecov uses.
I updated to simplecov 0.13 and as expected by @colszowka it was not covered. The gem is currently not open source so I could not get access to you. But I will extract the relevant things this afternoon and make a public repo so you can take a look into it.
The entirety of version.rb will be evaluated when the file is loaded. If anything requires the file, it'll be fully covered.
I made a file foo.rb containing
module Namespace
module Core
VERSION = "X.X.X"
end
end
and in irb ran
require 'coverage'
Coverage.start
load './foo.rb'
Coverage.result
and got {"foo.rb"=>[1, 1, 1, nil, nil]} which means the first three lines were hit once.
@steffenschmidt any luck with that extraction? As long as it's required it should all be coverd as ruby just executes it
Here ist a link to the extraction:
https://github.com/steffenschmidt/coverage-extraction-gem
Let me know if I can help any further.
Just for my understanding as the solution of @bf4 works for me: Why do I have to load the version.rb separate while every other file in the lib directory is considered?
@steffenschmidt when the file isn't loaded then it is not covered by the tests - there is no run time just parse code in there :) Leaving this open for now so one day when I got time could check out the test repo
This occurs when bundle exec is used to run tests, where a gemspec declaration exists in the project's Gemfile and a require 'my_gem/version' statement is in the project's my_gem.gemspec file. Since the my_gem/version file is already required before the test helper is run, simplecov never tracks it.
This is the default setup for a new gem project as created by bundle gem, so it probably affects a large number of gem projects (though most probably don't care if their gem's VERSION constant isn't covered).
I can't think of any good workaround other than removing the require from the gemspec, and just duplicating/inlining the version directly.
Just surround the VERSION with # :nocov: comments or exclude it in your config. 100% and 0% or the version.rb are both kind of meaningless. Better to ignore it.
Agreed with @bf4 - that's the best solution we'll ever get I think :)
I just had this same issue, but then realized my mistake. I was using SimpleCov.start 'rails'.... Once I removed 'rails' it got coverage for the version file.
require 'simplecov'
Coverage.start
require 'gem_name'
I ran into this problem where SimpleCov didn't report coverage on version.rb. I found that the problem was that if the gemspec was loaded prior to me calling SimpleCov.start (as I do from my spec_helper.rb), then version.rb is not included in the coverage report.
This had two negative consequences:
version.rb was included in the coverage report. Running rspec omits version.rb while running rake rspec does not.version.rb is not included in the SimpleCov coverage report, it is impossible to get 100% coverage in SonarQube.Reasonable people could say that the small discrepancy does not matter. If you care, here is why this happens and how to fix it.
SimpleCov only reports on files which were required after the call to SimpleCov.start. Most gemspecs include the line:
require_relative "lib/my_gem/version"
This is included in the gemspec that is generated when you run bundle gem my_gem.
This is the reason why SimpleCov does not show coverage on the version.rb file: the gemspec is loaded (say because you ran your test suite with rspec or bundle exec rspec) before SimpleCov.start is called in the spec_help.rb file.
Curiously, running rake spec does not load the gemspec first. This means that version.rb IS included in the coverage report when running rake spec.
The only way I have found around this is to get the version in the gemspec without requiring 'lib/my_gem/version' in the following way:
load 'lib/my_gem/version.rb'
This works because the file will be required by your test suite in the normal way after SimpleCov.start is called.
However, doing this results in the following warning when you run your test suite:
lib/my_gem/version.rb:4: warning: already initialized constant MyGem::VERSION
In order to get around this, I modified my gemspec as follows:
# Get the GEMFILE_VERSION without requiring my_gem/version
load 'lib/my_gem/version.rb'
GEMFILE_VERSION = MyGem::VERSION
MyGem.send(:remove_const, :VERSION)
Gem::Specification.new do |spec|
# ...
spec.version = GEMFILE_VERSION
# ...
end
After this, lib/my_gem/version.rb is included in the coverage report and rspec and rake rspec both show identical coverage.
Most helpful comment
This occurs when
bundle execis used to run tests, where agemspecdeclaration exists in the project'sGemfileand arequire 'my_gem/version'statement is in the project'smy_gem.gemspecfile. Since themy_gem/versionfile is alreadyrequired before the test helper is run, simplecov never tracks it.This is the default setup for a new gem project as created by
bundle gem, so it probably affects a large number of gem projects (though most probably don't care if their gem'sVERSIONconstant isn't covered).I can't think of any good workaround other than removing the
requirefrom thegemspec, and just duplicating/inlining the version directly.