[...]
You can do that in rcov with the --test-unit-only option.
Well, one cannot have everything
. rcov is pretty useful for finding
missing tests. My only problem with it so far is its inability to test
coverage of metaprogrammed code, but I guess that can't be helped.
Are you referring to this?
$ rcov --no-html --text-coverage --no-color a.rb
================================================================================
a.rb
================================================================================
module StupidMeta
def ugly_make_meth(meth)
module_eval <<-EOF, __FILE__, __LINE__+1
def #{meth}(a,b)
a + #{meth.to_s.inspect} + b
end
EOF
end
def make_meth(meth)
define_method(meth) do |a,b|
!! a + meth.to_s + b
!! end
end
end
class X
extend StupidMeta
ugly_make_meth :foo
make_meth :bar
end
# we don't actually call them, so they should both be uncovered
#x = X.new
#x.foo("method ", " here")
#x.bar("method ", " here")
As you can see, Module#define_method will work better, if you can use it at
all (that is, if you don't need a block argument, under 1.8, and don't care
about the closure and the speed hit). Another advantage is that it will tell
you if the code is well formed (syntactically correct) much earlier.
The problem with the string forms of eval is that I've had to go to great
lengths to make sure rcov marks heredocs correctly, and the above annotation
*is* correct.
Indeed, in the above snippet the heredoc in ugly_make_meth has been
"executed", in some sense (this interpretation gains some weight due to the
interpolation going on; there's actually something being evaluated there).
But there are two interpretations for that string: as a mere heredoc, and as
executable code that defines another method. There are thus also two ways to
think about it as far as coverage is concerned.
I'm thinking that maybe some sort of pragma would make sense:
def ugly_make_meth(meth)
module_eval <<-EOF, __FILE__, __LINE+1__ # rcov:noheredoc
def #{meth}(a,b)
a + #{meth.to_s.inspect} + b
end
EOF
end
As for other limitations, I think I know how to handle generated code that
cannot be meaningfully associated to your sources, but I feel it's not worth
the effort.
Is there anything else you'd like to see addressed?