Even with all this testing, how can you be sure you’re building quality software?
You do TDD, right?
Nice! Can you think of anything else you’d want to be sure of before claiming to have written high-quality code?
How about that other developers don’t have trouble reading your code? Or that you haven’t let a bug creep in between your tests? What about being sure that you haven’t chosen to use a dependency with known security issues? Do you want to be sure that you’ve tested enough to be true to the testing pyramid?
I’m sure that you answered "yes" to all of these questions. 😉 Fortunately, Java has been around for a while and has a bunch of tools that let you automate solutions for these issues. You can run automatic checks as part of the build. This goes beyond just automating your tests: you can add checks on the quality of your code and your tests!
With each small change you push out, the software then gets built automatically in a continuous integration environment, and checked!
![Diagram showing the dynamics of a Test Driven Team.](https://user.oc-static.com/upload/2019/06/05/15596992502473_TEST%20DRIVEN%20TEAM.png)
This environment is usually, in some form or another, another computer dedicated to proving that all the tests and quality checks pass somewhere other than on local desktops (3). When things don’t work out, it helps to have reports to look at (5) - and we'll show you a few good tools for doing that in the sections below. You can use these to communicate with other experts and make your whole team aware of what has broken. We’re all responsible for the quality, right?
If things don’t work out, it is called breaking the build. A crime punishable by having to buy doughnuts! 🍩 Remember that you’re always working in a shared codebase, so breaking something in your codebase, breaks it for everyone. You should only release your code into the world when everything runs without breaking the build (6).
So, ready to check out some build tools and report generating tools? Or do you really want to be the one bringing in doughnuts to the office? 😉
Build tools
When you create a new class in Java, you’re just editing a regular text file with a .java
at the end, and writing inside. IDEs are very good at telling you if there’s anything wrong with your use of the Java language, but they don’t really run that .java
file. Java is a compiled language and needs the JDK‘s compiler to build the .java
files into .class
files, with instructions the JVM can efficiently run. In other words, since the build is done on your computer, you can only be sure that it works on your computer.
How can I be sure that it can be built by any other developer on my team? Or on any other computer?
You use build tools like Maven or Gradle that let you list which dependencies your code needs (E.g., JUnit v4 or Spring v5). It then compiles your code and runs your tests. Finally, it can package .class
files so your working app can get shipped.
Any developer with access to your project and the same build tools can then build, test, and package your code. So the build tool runs your unit, integration, and E2E tests for you! 😀Wouldn’t it be great if it also ran those other quality checks we talked about? Stuff to make sure that your tests and code are well written? You guessed it. Both Maven and Gradle can do this, via some seriously cool plugins.
Configuring Maven can be an art in itself and there is a lot of fine documentation out there; however, that shouldn't stop you having a look at a project and some of the plugins you can use to report on the overall quality of your software.
Let's check it out:
It gets even better. Many of these tools come with useful reports and dashboards. This helps your whole team measure and understand the overall quality of your software. Many of my teams have even had large screens in our work area, displaying the health of our build.
Let's continue with that example code and see what the reports look like and where they live:
As you saw, we used a range of plugins to create a variety of reports. Let's look at them and why they are useful.
Surefire
If you’re using Gradle, just running Gradle test is enough to generate an HTML report. With Maven, you use the Surefire plugin to report on your tests and make an HTML report. This is great because you could put it on display for your whole team, and if something breaks, everyone will know about it!
Maven creates an XML report when your tests fail, but can be made to create an HTML report when you run:
mvn site
Maven places your reports in the target/site/surefire-report.html
. It’s not the most stylish thing, but tells you how your tests did. See if you can figure out what failed:
Checkstyle
When you have lint on a jacket, you might use some tape to remove unwanted fibers which stand out. Checkstyle is a Java linting tool, which means that it looks at your source code and points out undesirable coding styles which stand out.
Who gets to pick what is desirable though? 🤔
It's a common practice for teams to have coding standards. This ensures that the code is consistent regarding important things like tabs versus spaces. This may seem silly, but without it, developers will spend half their time fighting their IDEs, and your code.
Checkstyle goes beyond tabs and spaces. It is highly customizable, and enforces styles of variable naming, class naming, indentation, bracketing, and much more. There are many preset configurations. You can even start by using the Java styles of Google and Oracle.
It’s also great at picking out gotchas. Take the following example on the left:
It looks harmless to follow your if
by the thing it should execute when userValid
is true. But imagine what would happen if I decided to log the transfer right before transferring the money? You can see that it might be easy to forget the brackets. This would call transferMoney even if the user wasn’t valid!
Not using {brackets} after an if is considered an anti-pattern. That is a bad habit you should avoid, as the long-term consequence can be unhealthy. You won’t contract an illness, but we’ve learned over time that certain anti-patterns can make your code unmaintainable.
To give you a feel for the many checks it can do, let’s talk about one of the more amusingly named ones. Cyclomatic complexity. Obviously, you know what this is, right?
...😰
I’m kidding. I remember once thinking that it was a reference to a washing machine feature. 😉
Cyclomatic complexity is a metric for measuring how many nested conditions (or ifs) your code has. Why is this important? The more nested “if.. then.. if.. then.. if..” type statements you have, the more paths you have to test. The number of combinations grows rapidly. So, a higher cyclomatic complexity points to a higher probability of bugs. Essentially, it is the number of possible paths the JVM could take through the lines of your code.
Checkstyle helps reduce the number of defects you produce. It does this by reporting on overly complex code and known bad practices, as you’re building it. Maven has a plugin you can use to add it to your build tool. You can even configure it to fail your build if the code isn’t good enough.
Start by running:
mvn checkstyle:checkstyle-aggregate
This produces a report, which is not particularly attractive. When you scroll to the bottom, you can see how your classes violated good practices:
It’s a bit hard to read at first, but the report also contains a link which teaches you about each type of violation. So in the case of FinalParameters, you can click through to documentation which will teach you that it’s safer to change add(Double left, Double right) to add(final Double left, final Double right) and why.
Jacoco
Another popular plugin for Java build tools is Jacoco. How do you know if you’ve tested enough? We talked about the many paths through your code when you have nested if statements. Every line of code used has the potential to go wrong.
Jacoco allows you to run your tests and check how much of your whole codebase was visited by your tests.
It’s a little like strapping a GPS to your back and then sending you out into a big city to go for a stroll. If I sent you for a walk through Paris and then measured the percentage of streets you walked, it probably wouldn’t be very many because it's a huge city. I’d need a few teams of testers to walk the main streets if I’m to get coverage.
There are three lessons in this little anecdote:
It’s hard to get confidence on a large software project, so try and keep your projects small and good at doing one thing.
Keep your code simple, and write lots of unit tests to target your complex classes.
Don’t let me strap a GPS on your back! 😎
Jacoco also has a handy plugin which you can integrate into your build.
When an HTML report is generated with mvn site, you can see target/site/jacoco has been created with HTML files. If you look at these, you’d see a summary showing the percentage of tested methods per class. You can drill even deeper to see something like the following:
Can you see that the subtract() method in this example doesn’t have any tests? It’s all red. This can help you write tests where you’ve forgotten to.
FindBugs
FindBugs is another gem of a tool, which analyzes your Java code and helps you improve its quality. FindBugs is a little like Checkstyle, in that it performs static analysis of your source code to look for things you shouldn’t be doing.
Static analysis examines what your Java code looks like, and finds patterns so it can make a judgment about possible risks. This is a little like taking an online survey to check your health, but more reliable. FindBugs has a huge database of different types of known software bugs. It finds code doing things which were probably not intended, doesn’t follow good practices, and may introduce a security risk.
FindBugs has a plugin which you can integrate with your build tools. You can check for bugs with mvn findbugs:findbugs, or generate an HTML report with mvn site. Imagine that you had this buggy code which calls a method on null reference:
public Double subtract(final Double left, final Double right) {
// What does findbugs think of this impossible situation?
if (left==null && left.isNaN())
System.out.println("Do not run this line of code");
}
FindBugs would report this as:
Okay, it’s a little vague, but if you click through the NP_ALWAYS_NULL, it will explain it:
![Clicking through the link](https://user.oc-static.com/upload/2019/06/05/15597314476001_p1ch6code8.png)
As left is null, and left.isNan()
gets called, this will blow up with a NullPointerException
.
Other plugins
All of these plugins perform static analysis of your code and help you measure its quality. There are many more great plugins out there. If you’re interested, you can check out OWASP Dependency Checker, a security vulnerability scanner. OWASP provides great resources and guidance on building secure applications; it would be well worth checking out OpenClassrooms’ OWASP course!
There’s more. You should also check out PMD, another bug finder similar to FindBugs. My top tip would be to look at SonarQube, which does all the things we’ve seen here but in one very visual place. It does involve a little more setting up, though.
Try it out for yourself!
Clone the repository below, and run Maven commands in its README.md. See if you can fix some of the issues!
git clone https://github.com/OpenClassrooms-Student-Center/AchieveQualityThroughTestingInJavaB
Or use your IDE to clone https://github.com/OpenClassrooms-Student-Center/AchieveQualityThroughTestingInJavaB
You can now explore the examples from the screencast and try running the tests with:
mvn clean test site
Remember to have a look at the README. 😉
Let's recap!
The process of compiling code, running tests, and verifying the quality of your software is collectively known as a build.
You can verify the overall quality of your Java projects as part of the build by using plugins for your build tool (E.g., Maven or Gradle)
Generating human readable and visual reports about the health of your codebase lets everyone on your team know how well or badly you are doing. Remember that the whole team is responsible for the quality of your software.
Maven has several useful plugins which gives you confidence in your software and helps report on them:
Plugin | What does this give us? |
Surefire Plugin | Provides XML and HTML reports of JUnit tests. |
Checkstyle | Provides XML and HTML reports of conformance to agreed coding styles. |
Jacoco | Provides HTML and XML TEST COVERAGE reports describing how much of your code is tested. Can be used to fail a build if we don’t have enough tests! |
FindBugs | Performs static analysis by inspecting code for patterns which look like they are introducing bugs. |
Phew! You've already got a lot of testing under your belt. Check what you've learned via the Part 1 quiz, and I'll meet you in the next part to work on more advanced testing techniques!