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
Code coverage support for tests (scrypto coverage command) #1640
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really nice work!
I managed to run scrypto new-package hello
and scrypto coverage
, after following all the hints for dependencies.
A coverage report was successfully generated, and the total coverage percentage seems to be right on index.html
. However, the coverage report for the hello/src/lib.rs
file is completely missed. It shows zero coverage.
reason: err.to_string(), | ||
} | ||
})?; | ||
#[cfg(not(feature = "coverage"))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of curiosity, did you run into any issue with gas metering ingestion for the coverage-enabled wasm code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. When transaction fails for example due to out of gas then dump_coverage cannot be called because it will fail due to out of gas. When this is commented, the function dump_coverage is not using any build-in native functions so it's going to work even in case of transaction failure.
The other option is to disable gas/native functions only when dump_coverage
is called.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. I was hoping it wasn't an error with the instrumentation itself, otherwise we have a problem. All is good.
usd_price: USD_PRICE_IN_XRD.try_into().unwrap(), | ||
state_storage_price: Decimal::zero(), | ||
archive_storage_price: Decimal::zero(), | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to the difference in configuration, some tests may fail in coverage
mode but not in regular test mode. I guess it's not a big deal for most cases. We will need to make sure the --no-fail-fast
flag is provided when running coverage.
scrypto-unit/src/test_runner.rs
Outdated
}); | ||
let definition = manifest_decode(&definition).unwrap_or_else(|err| { | ||
panic!( | ||
"Failed to parse manifest definition from path {:?} - {:?}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: manifest definition
-> package definition
if !is_nightly { | ||
println!("Coverage tool requries nightly version of rust toolchain"); | ||
println!("You can install it by using the following commands:"); | ||
println!("rustup default nightly"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wonder if it's possible to use nightly
for coverage only?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it could use "cargo +nightly" when building package, but there may be some issues when someone is using multiple nightly versions. Anyway, I added this in the next commit.
@iamyulong This should not happened, in my case helo/src/lib.rs has correct coverage report. Did you update dependencies in cargo.toml to use version with coverage? If you did and it didn't work then please contact me to find out why it happened. |
|
||
// Build package | ||
let path = self.path.clone().unwrap_or(current_dir().unwrap()); | ||
let (wasm_path, _) = build_package(&path, false, false, true, Level::Trace, true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@iamyulong This approach, with building package before running tests and then reusing it makes tests way faster. Here's my recommendation regarding scrypto test
:
- Build all packages in advance, including dependencies (this may be hard when it comes to dependencies)
- Store information what has been build in ENV, you can also store checksum and build options
- In
test_runner.rs
try to use cached version, if it doesn't exist then build it and eventually cache it somehow (this may be hard because requires synchronization)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is generally a good idea. 👍
I believe the cargo build
automatically caches previous builds and avoids re-compiling if not updates have been made, right? However, we can potentially speed up tests by caching package publishing processing and genesis bootstrap.
This is definitely something that we need to measure and improve.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah it does, but it's slow and requires other tests to wait when using multiple workers/threads
Hi @bbarwikowski-hacken, thanks for sharing the screenshot! I actually got the same HTML report as yours. I think I was confused by it only showing the hit counts, rather than highlighting covered lines green and uncovered lines red. Any chance we can improve this a bit? Not a blocker and I think the PR is ready for merging. :) |
The problem is that hello package has 100% code coverage so there's nothing to highlight 😆 This is how it looks in case of not covered code. |
Summary
This PR adds new command
scrypto coverage
which allows to create code coverage report from tests. It was implemented based on https://github.com/hknio/code-coverage-for-webassembly findings.Please let me know what you think, in same cases I had to use ugly approach like:
If you have better idea how it could be implemented, please let me know.
In the next commit I'll add test_coverage.sh script, the only problem is I'll need to install nightly version of rust and the same version of llvm as nightly rustc is using. Should I add it in Dockerfile or somewhere else?