Skip to content

Commit 427396f

Browse files
author
Michael Nedzelsky
committed
initial commit
1 parent e3bf967 commit 427396f

File tree

10 files changed

+548
-0
lines changed

10 files changed

+548
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
target/*
2+
*.iml
3+
.idea/*

README.md

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Cover Annotations
2+
3+
Cover Annotations allows users to annotate their Java codebase with advice on how best to test it.
4+
In turn this can be used by [Diffblue Cover](https://diffblue.com/cover) to tune the tests it writes.
5+
6+
## Installation
7+
8+
### Maven
9+
10+
In order to use the annotations in your Maven project then the Diffblue repository and `cover-annotations` dependency will need to be added into your `pom.xml`:
11+
12+
```xml
13+
<dependencies>
14+
<dependency>
15+
<groupId>com.diffblue.cover</groupId>
16+
<artifactId>cover-annotations</artifactId>
17+
<version>1.0.0</version>
18+
</dependency>
19+
</dependencies>
20+
```
21+
22+
### Gradle
23+
24+
In order to use the annotations in your Gradle project then the Diffblue repository and `cover-annotations` dependency will need to be added into your `build.gradle`:
25+
26+
```gradle
27+
dependencies {
28+
implementation("com.diffblue.cover:cover-annotations:1.0.0")
29+
}
30+
```
31+
32+
Or similarly for `build.gradle.kts`:
33+
34+
```
35+
dependencies {
36+
implementation("com.diffblue.cover:cover-annotations:1.0.0")
37+
}
38+
```
39+
40+
## Annotations
41+
42+
Annotations placed on packages affect tests for all classes and methods under test in that package.
43+
Annotations placed on classes affect tests for that class and all it's methods under test, overriding package level annotations.
44+
Annotations placed on methods affect just that method under test, overriding package and class level annotations.
45+
46+
| Annotation | Equivalent `dcover create` option |
47+
|:----------------------------|:--------------------------------------------------|
48+
| `@InTestsMock` | `--mock`, `--disable-mock-inputs` |
49+
| `@InTestsMockConstruction` | `--mock-construction` |
50+
| `@InTestsMockStatic` | `--mock-static` |
51+
52+
The annotations will be respected by Diffblue Cover via both command line and IntelliJ Plugin.
53+
When used from the command line in conjunction with equivalent options then the command line options take priority over the annotations found.
54+
55+
### Using `@InTestsMock`
56+
57+
Perhaps you have a method that Diffblue Cover would ordinarily test using an `Integer` but you'd prefer to see it tested using `Mockito.mock(..)`.
58+
In this case you could annotate the method (or class, or package) to recommend mocking `Number`:
59+
60+
```java
61+
public class ClassUnderTest {
62+
@InTestsMock(Number.class)
63+
public static String methodUnderTest(Number number) {
64+
return String.valueOf(number.intValue());
65+
}
66+
}
67+
```
68+
69+
Conversely, if Diffblue Cover normally does mock a particular class, and you have a particular location where it shouldn't be then you can forbid it:
70+
71+
```java
72+
public class ClassUnderTest {
73+
@InTestsMock(value = Number.class, decision = MockDecision.FORBIDDEN)
74+
public static String methodUnderTest(Number number) {
75+
return String.valueOf(number.intValue());
76+
}
77+
}
78+
```
79+
80+
### Using `@InTestsMockConstruction`
81+
82+
Perhaps you have a method that Diffblue Cover is unable to test, and you think it could make more progress using `Mockito.mockConstruction(Random.class)`.
83+
In this case you could annotate the method (or class, or package) to recommend mocking construction of `Random`:
84+
85+
```java
86+
public class ClassUnderTest {
87+
@InTestsMockConstruction(Random.class)
88+
public static int methodUnderTest() {
89+
return new Random().nextInt();
90+
}
91+
}
92+
```
93+
94+
### Using `@InTestsMockStatic`
95+
96+
Perhaps you have a method that Diffblue Cover is unable to test, and you think it could make more progress using `Mockito.mockStatic(UUID.class)`.
97+
In this case you could annotate the method (or class, or package) to recommend mocking static methods of `UUID`:
98+
99+
```java
100+
public class ClassUnderTest {
101+
@InTestsMockStatic(UUID.class)
102+
public static Path methodUnderTest() {
103+
return Paths.get(UUID.randomUUID() + ".zip");
104+
}
105+
}
106+
```

pom.xml

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
~ Copyright 2024 Diffblue Limited. All Rights Reserved.
4+
~ Unpublished proprietary source code.
5+
~ Use is governed by https://docs.diffblue.com/licenses/eula
6+
-->
7+
<project xmlns="http://maven.apache.org/POM/4.0.0"
8+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
9+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
10+
<modelVersion>4.0.0</modelVersion>
11+
<groupId>com.diffblue.cover</groupId>
12+
<artifactId>cover-annotations</artifactId>
13+
<version>1.0.0</version>
14+
<packaging>jar</packaging>
15+
16+
<name>Cover Annotations</name>
17+
<description>
18+
Annotations for end users to enable fine-grained control of Diffblue Cover.
19+
There are some expectations of open-sourcing the annotations and so module
20+
contents must be kept free of intellectual property.
21+
</description>
22+
<url>https://www.diffblue.com/</url>
23+
24+
<licenses>
25+
<license>
26+
<name>Apache License, Version 2.0</name>
27+
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
28+
<distribution>repo</distribution>
29+
</license>
30+
</licenses>
31+
32+
<developers>
33+
<developer>
34+
<id>developer-id</id>
35+
<name>Diffblue Ltd</name>
36+
<email>support@diffblue.com</email>
37+
<organization>Diffblue</organization>
38+
<organizationUrl>https://www.diffblue.com</organizationUrl>
39+
</developer>
40+
</developers>
41+
42+
<scm>
43+
<url>https://github.com/diffblue/cover-annotations</url>
44+
<connection>scm:git:git://github.com/diffblue/cover-annotations.git</connection>
45+
</scm>
46+
47+
<properties>
48+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
49+
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
50+
<maven.compiler.plugin.version>3.13.0</maven.compiler.plugin.version>
51+
<maven.javadoc.plugin.version>3.6.3</maven.javadoc.plugin.version>
52+
<maven.source.plugin.version>3.3.0</maven.source.plugin.version>
53+
<gpg.plugin.version>3.2.1</gpg.plugin.version>
54+
</properties>
55+
56+
<distributionManagement>
57+
<snapshotRepository>
58+
<id>ossrh</id><!-- nb this must be the same as the 'id' field in 'settings.xml' -->
59+
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
60+
</snapshotRepository>
61+
</distributionManagement>
62+
63+
<profiles>
64+
<profile>
65+
<id>stdbuild</id>
66+
<activation>
67+
<activeByDefault>true</activeByDefault>
68+
</activation>
69+
<build>
70+
71+
<plugins>
72+
73+
<plugin>
74+
<groupId>org.apache.maven.plugins</groupId>
75+
<artifactId>maven-compiler-plugin</artifactId>
76+
<version>${maven.compiler.plugin.version}</version>
77+
<configuration>
78+
<source>1.8</source>
79+
<target>1.8</target>
80+
</configuration>
81+
</plugin>
82+
<!-- Source plugin to include sources in the final artifact -->
83+
<plugin>
84+
<groupId>org.apache.maven.plugins</groupId>
85+
<artifactId>maven-source-plugin</artifactId>
86+
<version>${maven.source.plugin.version}</version>
87+
<executions>
88+
<execution>
89+
<id>attach-sources</id>
90+
<goals>
91+
<goal>jar</goal>
92+
</goals>
93+
</execution>
94+
</executions>
95+
</plugin>
96+
97+
<!-- Javadoc plugin to include Javadoc in the final artifact -->
98+
<plugin>
99+
<groupId>org.apache.maven.plugins</groupId>
100+
<artifactId>maven-javadoc-plugin</artifactId>
101+
<version>${maven.javadoc.plugin.version}</version>
102+
<executions>
103+
<execution>
104+
<id>attach-javadocs</id>
105+
<goals>
106+
<goal>jar</goal>
107+
</goals>
108+
</execution>
109+
</executions>
110+
</plugin>
111+
</plugins>
112+
</build>
113+
</profile>
114+
<profile>
115+
<id>sign</id>
116+
<activation>
117+
<activeByDefault>false</activeByDefault>
118+
</activation>
119+
<build>
120+
<plugins>
121+
<!-- GPG Plugin for signing artifacts -->
122+
<plugin>
123+
<groupId>org.apache.maven.plugins</groupId>
124+
<artifactId>maven-gpg-plugin</artifactId>
125+
<version>${gpg.plugin.version}</version>
126+
<executions>
127+
<execution>
128+
<id>sign-artifacts</id>
129+
<phase>verify</phase>
130+
<goals>
131+
<goal>sign</goal>
132+
</goals>
133+
</execution>
134+
</executions>
135+
</plugin>
136+
137+
</plugins>
138+
</build>
139+
</profile>
140+
</profiles>
141+
142+
</project>
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2024 Diffblue Limited. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package com.diffblue.cover.annotations;
17+
18+
import static com.diffblue.cover.annotations.MockDecision.RECOMMENDED;
19+
import static java.lang.annotation.ElementType.METHOD;
20+
import static java.lang.annotation.ElementType.PACKAGE;
21+
import static java.lang.annotation.ElementType.TYPE;
22+
import static java.lang.annotation.RetentionPolicy.CLASS;
23+
24+
import java.lang.annotation.Repeatable;
25+
import java.lang.annotation.Retention;
26+
import java.lang.annotation.Target;
27+
28+
/**
29+
* Indicates whether tests of the annotated item should mock the classes identified by {@link
30+
* #value()}. Without annotation then mocking is assumed to be {@link MockDecision#ALLOWED}, but
31+
* with annotation then the decision defaults to {@link MockDecision#RECOMMENDED}. The decision can
32+
* be overridden with an explicit {@link #decision()} value.
33+
*/
34+
@Retention(CLASS)
35+
@Target({PACKAGE, TYPE, METHOD})
36+
@Repeatable(InTestsMock.Repeatable.class)
37+
public @interface InTestsMock {
38+
39+
/** Collects multiple {@link InTestsMock} annotations. */
40+
@Retention(CLASS)
41+
@Target({PACKAGE, TYPE, METHOD})
42+
@interface Repeatable {
43+
InTestsMock[] value();
44+
}
45+
46+
/**
47+
* @return the classes to mock (or not).
48+
*/
49+
Class<?>[] value();
50+
51+
/**
52+
* @return the mocking decision to apply.
53+
*/
54+
MockDecision decision() default RECOMMENDED;
55+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2024 Diffblue Limited. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package com.diffblue.cover.annotations;
17+
18+
import static com.diffblue.cover.annotations.MockDecision.RECOMMENDED;
19+
import static java.lang.annotation.ElementType.METHOD;
20+
import static java.lang.annotation.ElementType.PACKAGE;
21+
import static java.lang.annotation.ElementType.TYPE;
22+
import static java.lang.annotation.RetentionPolicy.CLASS;
23+
24+
import java.lang.annotation.Repeatable;
25+
import java.lang.annotation.Retention;
26+
import java.lang.annotation.Target;
27+
28+
/**
29+
* Indicates whether tests of the annotated item should mock constructions of the classes identified
30+
* by {@link #value()}. Without annotation then mocking is assumed to be {@link
31+
* MockDecision#ALLOWED}, but with annotation then the decision defaults to {@link
32+
* MockDecision#RECOMMENDED}. The decision can be overridden with an explicit {@link #decision()}
33+
* value.
34+
*/
35+
@Retention(CLASS)
36+
@Repeatable(InTestsMockConstruction.Repeatable.class)
37+
public @interface InTestsMockConstruction {
38+
39+
/** Collects multiple {@link InTestsMockConstruction} annotations. */
40+
@Retention(CLASS)
41+
@Target({PACKAGE, TYPE, METHOD})
42+
@interface Repeatable {
43+
InTestsMockConstruction[] value();
44+
}
45+
46+
/**
47+
* @return the classes to mock (or not).
48+
*/
49+
Class<?>[] value();
50+
51+
/**
52+
* @return the mocking decision to apply.
53+
*/
54+
MockDecision decision() default RECOMMENDED;
55+
}

0 commit comments

Comments
 (0)