Once upon a time, I was a junior dev working alongside the QA team at an image search company. It was a small team, mostly responsible for the user-facing website. Thankless work. One of the things it instilled in me, though, was a healthy dose of respect for proper testing of code. How do you know that the code you’ve just written is going to perform the way you intended it to? Repeatable, easy-to-run testing.
There are a lot of different ways to test software, but I want to focus on Unit Testing. Simply put, Unit Testing is the process where you test the smallest units of code.
In Unit Testing, your focus is on testing how individual units of code, like a function or macro, operate. You may use use or create “mock” objects, such as an HTTP client that simulates operations against a pretend web server. What you’re doing is making sure that the function you’ve written performs the way you expect it to when given valid and invalid input.
When you do this, you’re creating test coverage in your code base. Code coverage is a metric that states what percentage of your code has a unit test that exercises it. It tells you how much of your code you’ve written tests for.
Please note, though, that it doesn’t mean you’ve written good tests. More on that another time.
So the goal for this post is to show you how to see your test coverage, and make it an integral part of your testing strategy. Perhaps more importantly, I’ll show you how to see where you lack test coverage.
The testing frameworks I’ve used in Go/Rust typically show you the number of tests run, pass or fail, but require a bit more work to visualize your test coverage.
For convenience, I’ve written shell functions for each language that will generate a coverage report. I’ve stuck these in my ~/.aliases
, making them available at the command line.
Go
Go has built-in support for collecting coverage profiles. That means that this will just work, out of the box. What I’ve created here is a function, go-coverage
, that I can pass a package path to and it will generate and open a coverage map.
|
|
To use it, simply pass it the path to the module you want to test.
|
|
Rust
There are multiple options to generating a coverage profile in Rust. I’ve tested llvm-conv and tarpaulin. They’re both similiar, but I prefer the output of llvm-conv for navigating the data. tarpaulin displays the same data, but doesn’t allow you to link to a specific line of code or jump ahead to the first block of missing coverage.
You’ll need to install llvm-conv:
|
|
Then, add this function to your aliases:
|
|
Now you can run it from any Rust project:
|
|