Author: Peter Schrammel
Almost nobody likes writing unit tests - and if you agree, you may be glad to hear that manually writing all of your tests is becoming a thing of the past. We've developed Diffblue Cover, an AI tool that automatically creates unit tests for Java code, to make it easier to get the unit tests you need without spending the time it takes to write them.
Diffblue Cover: Community Edition is a free IntelliJ plugin that uses the same core technology, and is now available for anyone to use with their open-source Java projects. What does Community Edition do? So how is it actually used?
Diffblue Cover works like this:
First, Diffblue Cover ensures that your code is compiled. This is required because it performs an analysis on the bytecode. Then, it tries to trigger executions of paths through each method that it is going to test, using inputs that are similar to those a developer would choose. On the way, it mocks any dependencies that should be mocked. Finally, it figures out what the useful assertions may be and adds them to the test. Note that the assertions always reflect the current behavior of the code; Diffblue Cover is not able to anticipate your intentions and 'fix' the code for you.
Diffblue Cover is intended to be used for unit regression testing. Essentially, this means it creates unit tests that reflect the current behavior of your code (and if you'd like more information about that, we have an explanation here). If your code is currently working, Diffblue Cover captures this. Later, when you make changes to the code, these tests may fail and show you possibly unintended changes to the code (so-called "regressions"). It can also help you find bugs by review.
Diffblue Cover is significantly faster than writing manual tests from scratch. Sometimes it might not succeed in finding a suitable test for your code, in which case it may return a partial test for you to complete. But because Diffblue Cover creates unit tests in bulk in a tiny fraction of the time it'd take to write them, it helps you speed up unit test writing for new features.
Currently, Diffblue Cover is only available for Java, but will be expanded to work with other languages in the future.
The tests that Diffblue Cover creates largely follow the arrange-act-assert pattern:
Here's an example that Cover created:
@MockBean
private AmazonS3Client amazonS3Client;
@Test
public void testDownloadFileFromBucket() throws UnsupportedEncodingException {
StringInputStream objectContent = new StringInputStream("Lorem ipsum dolor sit amet.");
S3Object s3Object = new S3Object();
s3Object.setObjectContent(objectContent);
when(this.amazonS3Client
.getObject(or(isA(String.class), isNull()), or(isA(String.class), isNull())))
.thenReturn(s3Object);
S3Object actualS3Object = this.cloudStorageService.downloadFileFromBucket("bucket-name", "key")
assertSame(s3Object, actualS3Object);
}
You can download the plugin here, or by going to Preferences > Plugins > Marketplace in your IntelliJ IDE, searching for “Diffblue Cover,” and installing the community edition.
To give you an idea of what the tool does and illustrate its features, let’s look at a simple example project that uses the Spring framework: Spring Pet-Clinic. We have forked this project into https://github.com/Diffblue-benchmarks/Spring-petclinic. You’ll find the branches for each lesson of this tutorial so that you can follow along on your own.
Your first steps after having installed the plugin are:
This class implements a simple service for uploading to and downloading files from an S3 bucket.
@Service
public class CloudStorageService {
@Autowired
private AmazonS3 s3client;
public PutObjectResult uploadFileToBucket(String bucketName, String key, File file) {
return s3client.putObject(bucketName, key, file);
}
public S3Object downloadFileFromBucket(String bucketName, String key) {
return s3client.getObject(bucketName, key);
}
To create tests for this class, right-click on CloudStorageService > Write tests
When you open the event log, you'll see what the tool is doing. First, it ensures that the project compiles and figures out for which methods we want to produce unit tests. To create the tests, it has to load the Spring context and find suitable inputs to the methods to exercise paths through these methods.
Once the first test has been created you can navigate to the created test source file to see the tests. Further tests will drop in as they are produced.
Let’s have a look at this test. The tested service would communicate with an actual S3 bucket. We don’t want this to happen in a unit test, so we mock the S3 client using Mockito. We have to set up the object returned by getObject appropriately, including the content of the file.
@ExtendWith(SpringExtension.class)
public class CloudStorageServiceTest {
@MockBean
private AmazonS3Client amazonS3Client;
@Autowired
private CloudStorageService cloudStorageService;
@Test
public void testDownloadFileFromBucket() throws UnsupportedEncodingException {
StringInputStream objectContent = new StringInputStream("Lorem ipsum dolor sit amet.");
S3Object s3Object = new S3Object();
s3Object.setObjectContent(objectContent);
when(this.amazonS3Client
.getObject(or(isA(String.class), isNull()), or(isA(String.class), isNull())))
.thenReturn(s3Object);
assertSame(s3Object, this.cloudStorageService.downloadFileFromBucket("bucket-name", "key"));
}
In this example, you can see how Diffblue Cover: Community Edition creates tests that are actually useful and can even handle more complex scenarios, e.g. mocking.
Hopefully this overview gives you an idea of how Community Edition works, but if you have questions or need any help, you can contact us through the Community Forum.