Java, developed in 1995, is one of the most popular programming languages in the world. This article will walk you through an example Java project with Gradle to get up and running with testing and code coverage. You can view the entire source code of this post at our example repository.
For our project, we will be using Java 18
. You will need to create a new public repository in GitHub. You should also go ahead and create a Codecov account.
Getting started with Java
We will start with a simple calculator app that exposes two methods: add
and subtract
off of a Calculator
class. Both functions accept two doubles and return a double. We can paste the code below into the file src/main/java/calculator/Calculator.java
package calculator;
public class Calculator {
public static double add(double x, double y) {
return x + y;
}
public static double subtract(double x, double y) {
return x - y;
}
}
Now, let’s add a test for our add
function.
src/test/java/calculator/CalculatorTest.java
package calculator;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class CalculatorTest {
private static final double DELTA = 0.001;
@Test
public void testAdd() {
assertEquals(Calculator.add(1, 2), 3.0, DELTA);
}
}
To run our tests, we will be taking advantage of the junit
package. We will also need to update our build.gradle
file and build out the testing infrastructure to use junit
build.gradle
group 'io.codecov'
version '1.0'
apply plugin: 'java'
sourceCompatibility = 18
targetCompatibility = 18
repositories {
mavenCentral()
}
dependencies {
testImplementation "junit:junit:4.13"
}
Run your tests and get coverage
To run our test, in a terminal, call gradle build
This should bring the following output.
--> gradle build
Starting a Gradle Daemon (subsequent builds will be faster)
BUILD SUCCESSFUL in 6s
4 actionable tasks: 4 executed
To get coverage results, we will need to add the jacoco
plugin.
Update build.gradle
to match below
group 'io.codecov'
version '1.0'
apply plugin: 'java'
apply plugin: 'jacoco'
sourceCompatibility = 18
targetCompatibility = 18
repositories {
mavenCentral()
}
dependencies {
testImplementation "junit:junit:4.13"
}
jacocoTestReport {
reports {
xml.enabled true
html.enabled enabled
}
}
check.dependsOn jacocoTestReport
Re-run gradle build
to view coverage information.
--> bundle install && rake test
Fetching gem metadata from https://rubygems.org/..
…
--> gradle build
Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
See https://docs.gradle.org/7.5.1/userguide/command_line_interface.html#sec:command_line_warnings
BUILD SUCCESSFUL in 1s
5 actionable tasks: 5 executed
You will notice a new build
directory which holds coverage information. For the human-readable html
version, open build/reports/jacoco/test/html/index.html
in a browser.
You can view the coverage for the individual file by clicking into it.
Although coverage says 36%, this is due to total missed instructions. Our true coverage is 33.3% as there is 1 covered line return x + y;
for the 3 statements.
How to upload to Codecov
Now that we are able to collect coverage locally, let’s learn how to upload these reports to Codecov. Codecov is a code coverage tool that provides reports on how much of a project’s codebase is tested. It is often used in conjunction with continuous integration (CI) systems to ensure that new code changes are adequately covered by tests.
We will be using GitHub Actions as the Ci and the Codecov Action to upload coverage reports.
Create a file called .github/workflows/ci.yml
.
name: Workflow for Codecov example-java-gradle
on: [push, pull_request]
jobs:
run:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up JDK 18
uses: actions/setup-java@v1
with:
java-version: 18
- name: Install dependencies, run tests, and collect coverage
run: gradle build
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
It is recommended that you install the Codecov app for this repository to prevent rate-limiting issues. Save your code and push up to GitHub
.
git checkout -b 'initial-commit'
git add .
git commit -m 'Initial commit and upload coverage to Codecov'
git push origin initial-commit
In GitHub
, open the pull request and wait for CI and Codecov to finish running and analyzing. You should see the following pull request commit.
You should also see four status checks, two of which come from Codecov.
Our documentation contains more information on the meaning of each status check. When you are ready, merge the pull request.
Covering uncovered code
Now that we can get coverage data in our pull request. Let’s take a look at how to increase coverage.
Let’s take a look at the coverage report from Codecov. Navigate to your repository from the Codecov UI. You should see a dashboard like this.
Notice that there is only 1 covered line in the Code tree
. If we click on src/main/java/calculator/Calculator.java
,
From this view, we can tell that we haven’t written a test for our subtract function!
Create a new branch in your terminal
git checkout main
git pull
git checkout -b 'subtract-test'
and update the test file with the following code below the add
test.
@Test
public void testSubtract() {
assertEquals(Calculator.subtract(1, 2), -1.0, DELTA);
}
Save the code and open a new pull request.
git add .
git commit -m 'fix: add tests for subtract fn'
git push origin subtract-test
Notice the Codecov comment shows the coverage increasing from 33.33%
to 66.66%
.
Advanced Codecov configurations
Now that you have uploaded your first Java coverage reports successfully to Codecov, you can check out some of our other features including
- configuring Codecov settings
- adding Flags to isolate coverage reports
- labelling critical files