-
-
Notifications
You must be signed in to change notification settings - Fork 181
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Misses in coverage #351
Comments
It looks like my coverage report is counting the lines in tests as part of coverage (including one miss, somehow). See e.g. here if you scroll down to the lines 500+. Not sure whether that's intentional or not but seems a bit odd (and the miss is a false negative I guess) |
There's some weirdness with macros, I need to figure out the best way to handle them. Also if you want to exclude test code you can use |
Just curious, why is |
Honestly just because as a feature it came later and no ones asked for the default to be switched around, I've got no opposition to switching the default behaviour. I also definitely don't think people are writing tests for their tests (or at least I hope not...) The main use I can see is for integration tests that involve things like file or network IO some people might want to make sure their tests are actually executing the code as thoroughly as they expect |
I think this is another instance of the "split logical lines", but the attached report for |
A variable declaration with the left-hand expression on a different line is counted as untested, see this report and this one. Additionally, conditionally compiled code that is not part of the current feature set seems to flag a false negative as well, as shown here |
oh the feature flag is something I've definitely missed! Although I suppose I wonder if that should be filtered out by default, as ideally you should test all your features thoroughly and it is possible to organise different runs in a batch with different feature settings... Maybe I'll add a flag to add/remove them. Also for the assign expressions thinking of something that maps to logical lines of code for solving that class of issues once and for all |
It looks like the inline, associated functions returning Also, thanks for tarpaulin, it's really handy and easy to set up :) |
I can think of two examples:
But I don't care much about coverage in both cases, |
Here's another coverage result that seems to have some odd lines marked as not covered: The repository is over here: https://github.com/jonhoo/openssh-rs/ |
I believe all of the misses here are erroneous: |
😞 |
^ I think that's just GitHub having issues today |
I have 2 covered lines containing doc comments using tarpaulin 0.11.1: |
False negatives here. I have setup tarpaulin recently and tested it on my code and uploaded test coverage to Codecov. This is the actual report on Codecov (no custom formatting). I have found that:
Here's my travis-ci build configuration, if needed: configuration
|
I have a whole bunch of |
In a It seems to be any trailing expression that is just a borrow from |
The item headers for |
@CAD97 That link is behind a login wall. Not everyone has already given access to codecov.io. |
@mathstuf ah, sorry, I was unaware that that link required a login. (It should be public, the repository in question is public.) (If it was just that the second link was blank, it's because I had forgotten to pin it to a specific commit, which is fixed now.) Here's the linked snippets inline: + pub fn builder(&mut self) -> &mut Builder {
- &mut self.cache
}
+ pub fn add(&mut self, element: impl Into<NodeOrToken<Arc<Node>, Arc<Token>>) -> &mut Self {
+ self.children.push(element.into());
- self
} + fn visit_seq<Seq>(self, mut seq: Seq) -> Result<Self::Value, Seq::Error>
where
Seq: SeqAccess<'de>,
{
+ if seq.size_hint().is_some() {
struct SeqAccessExactSizeIterator<'a, 'de, Seq: SeqAccess<'de>>(
&'a mut Builder,
Seq,
PhantomData<&'de ()>,
);
- impl<'de, Seq: SeqAccess<'de>> Iterator for SeqAccessExactSizeIterator<'_, 'de, Seq> {
- type Item = Result<NodeOrToken<Arc<Node>, Arc<Token>>, Seq::Error>;
+ fn next(&mut self) -> Option<Self::Item> {
+ self.1.next_element_seed(ElementSeed(self.0)).transpose()
} |
Found this yesterday, not sure it has already been reported, but I couldn't find any reference to it: Resulting coverage: This is inside a It also comes up when invoking the macro, because the macro forwards the attributes: Resulting coverage: Seems like EDIT: I tried adding a test that actually uses the implementation of |
Fails to record coverage properly when functions are annotated with and |
For tracing, we found that it helps a lot to set |
@eloff It might be a bit late, but was this in generic code by any chance? I have both break statements and match cases not covered in generic code. @jplatte Is your example from generic code? I concur with @tokcum and @blacktemplar and I think that all these might have the same root cause. Maybe discussion about this case should be regrouped in #1078. |
I included a link with my example. It's in an impl block with lifetime generics, no type generics are involved. |
Sorry, I had missed that. It seems like lifetime generics are enough to trigger the behavior I have observed: struct S1 { v: Option<i32>, }
fn f1<'a>() {
let s = S1 { v: Some(0) };
Box::new(S1 {
v: s
.v
.map(|v| 42),
});
}
#[test]
fn test1() { f1(); }
struct S2 { u: i32, }
fn f2<'a>() {
Box::new(S2 {
u: 0,
});
}
#[test]
fn test2() { f2(); }
fn f3<'a>() {
Some(0)
.map(
|
v
|
42
);
}
#[test]
fn test3() { f3(); } gets me |
One silly, yet super important gotcha regarding accuracy: make sure you have not added:
In your |
@xd009642 I use Also when I have declared my own macros often |
seem to get missing coverage when a chain of methods is called: may be because they're being optimised out before the final code? https://app.codecov.io/gh/KGrewal1/optimisers/blob/master/src%2Flbfgs.rs missing coverage on struct field instantiation on lines 146 definitely doesnt seem correct however? Also some issues where every line is covered bar a final call to collect https://app.codecov.io/gh/KGrewal1/optimisers/blob/master/src%2Fadam.rs |
Hi 👋 , nice work with this project! 😸 I believe there's missing coverage when using Edit: resolved #1503. tyty! 😸 |
I went through the codebase and it looks like this line https://github.com/xd009642/tarpaulin/blob/develop/src/source_analysis/items.rs#L106 doesn't return true for Edit: resolved #1503. tyty! 😸 |
I'm getting a lot of seemingly random misses in match statements: CodeCov Link: https://app.codecov.io/gh/AnthonyMichaelTDM/mecomp/commit/0ce9868c0a0eae2458b5202e506c1250e32956b8/blob/one-or-many/src/lib.rs Screenshot of (some of the) coverage results of interest: the test(s) that should be resulting in those lines being covered: #[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::{assert_eq, assert_ne};
use rstest::rstest;
...
#[rstest]
#[case::none(OneOrMany::<usize>::None, OneOrMany::<usize>::None, Some(std::cmp::Ordering::Equal))]
#[case::none(OneOrMany::<usize>::None, OneOrMany::One(1), Some(std::cmp::Ordering::Less))]
#[case::none(OneOrMany::<usize>::None, OneOrMany::Many(vec![1, 2, 3]), Some(std::cmp::Ordering::Less))]
#[case::one(OneOrMany::One(1), OneOrMany::<usize>::None, Some(std::cmp::Ordering::Greater))]
#[case::one(OneOrMany::One(1), OneOrMany::One(1), Some(std::cmp::Ordering::Equal))]
#[case::one(OneOrMany::One(1), OneOrMany::One(2), Some(std::cmp::Ordering::Less))]
#[case::one(
OneOrMany::One(1),
OneOrMany::One(0),
Some(std::cmp::Ordering::Greater)
)]
#[case::one(OneOrMany::One(1), OneOrMany::Many(vec![1, 2, 3]), Some(std::cmp::Ordering::Less))]
#[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::<usize>::None, Some(std::cmp::Ordering::Greater))]
#[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::One(1), Some(std::cmp::Ordering::Greater))]
#[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::Many(vec![1, 2, 3]), Some(std::cmp::Ordering::Equal))]
#[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::Many(vec![2, 3]), Some(std::cmp::Ordering::Less))]
#[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::Many(vec![1, 2, 3, 4]), Some(std::cmp::Ordering::Less))]
fn test_partial_cmp<T>(
#[case] input: OneOrMany<T>,
#[case] other: OneOrMany<T>,
#[case] expected: Option<std::cmp::Ordering>,
) where
T: std::fmt::Debug + PartialOrd,
{
let actual = input.partial_cmp(&other);
assert_eq!(actual, expected);
}
#[rstest]
#[case::none(OneOrMany::<usize>::None, OneOrMany::<usize>::None, std::cmp::Ordering::Equal)]
#[case::none(OneOrMany::<usize>::None, OneOrMany::One(1), std::cmp::Ordering::Less)]
#[case::none(OneOrMany::<usize>::None, OneOrMany::Many(vec![1, 2, 3]), std::cmp::Ordering::Less)]
#[case::one(OneOrMany::One(1), OneOrMany::<usize>::None, std::cmp::Ordering::Greater)]
#[case::one(OneOrMany::One(1), OneOrMany::One(1), std::cmp::Ordering::Equal)]
#[case::one(OneOrMany::One(1), OneOrMany::One(2), std::cmp::Ordering::Less)]
#[case::one(OneOrMany::One(1), OneOrMany::One(0), std::cmp::Ordering::Greater)]
#[case::one(OneOrMany::One(1), OneOrMany::Many(vec![1, 2, 3]), std::cmp::Ordering::Less)]
#[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::<usize>::None, std::cmp::Ordering::Greater)]
#[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::One(1), std::cmp::Ordering::Greater)]
#[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::Many(vec![1, 2, 3]), std::cmp::Ordering::Equal)]
#[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::Many(vec![2, 3]), std::cmp::Ordering::Less)]
#[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::Many(vec![1, 2, 3, 4]), std::cmp::Ordering::Less)]
fn test_cmp<T>(
#[case] input: OneOrMany<T>,
#[case] other: OneOrMany<T>,
#[case] expected: std::cmp::Ordering,
) where
T: std::fmt::Debug + Ord,
{
let actual = input.cmp(&other);
assert_eq!(actual, expected);
}
...
} some additional context: #[derive(Clone, Debug, PartialEq, Eq, Default)]
pub enum OneOrMany<T> {
One(T),
Many(Vec<T>),
#[default]
None,
} |
huh, changing my compilation profile to use opt-level 0 instead of opt-level 1 seems to have fixed it. nevermind i guess? |
Is there more to getting the tracing event! macro to be covered than setting RUST_LOG=trace? I have done that and I am not getting the event! macro lines covered. |
You need an actual tracing subscriber registered, I typically use the |
I think I was confusing logging and tracing - I switched to a simpler logging interface using env_logger and I achieved all of the coverage that I required. Thanks for the help. |
It seems that static GLOBAL_ONE_PLUS_ONE_STATIC: u64 = add(1, 1);
const GLOBAL_ONE_PLUS_ONE_CONST: u64 = add(1, 1);
pub const fn add(left: u64, right: u64) -> u64 {
const _UNUSED: u64 = 70;
left + right
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
assert_eq!(GLOBAL_ONE_PLUS_ONE_STATIC, 2);
assert_eq!(GLOBAL_ONE_PLUS_ONE_CONST, 2);
static ONE_PLUS_ONE_STATIC: u64 = add(1, 1);
assert_eq!(ONE_PLUS_ONE_STATIC, 2);
const ONE_PLUS_ONE_CONST: u64 = add(1, 1);
assert_eq!(ONE_PLUS_ONE_CONST, 2);
}
}
appending |
that's probably because the values would be computed at compile time |
Yeah, values at compile time aren't evaluated at test time so not covered. const fn's can be runtime or compile time so I can't just filter them out |
hmmm, I'd imagine the way it ideally work then is to have the compiler increment the counters. |
|
False negative on desugared statement. Https://github.com/xd009642/tarpaulin/issues/1675 |
Mention any false positives or false negatives in code coverage in this issue with an example where it occurred and it will be added to the list!
else
only line https://codecov.io/gh/Smithay/wayland-rs/src/master/wayland-commons/src/socket.rs#L33*self
false positive when matching enum #258const
initialisations aren't covered.PhantomData
assert_eq!
asm!
worksFoo::X{ref bar} => {}
bar can register as uncoveredThe text was updated successfully, but these errors were encountered: