0
# Testing Annotations
1
2
Control expected warnings and analysis behavior for testing static analysis rules and validation. These annotations are primarily used for testing SpotBugs itself and validating static analysis behavior in codebases.
3
4
**Note:** Most testing annotations in this package are deprecated as of SpotBugs 4.x in favor of programmatic test matchers using `edu.umd.cs.findbugs.test.matcher.BugInstanceMatcher`. The annotation-based approach has limitations with modern Java features like lambdas.
5
6
## Capabilities
7
8
### ExpectWarning Annotation
9
10
Indicate that SpotBugs should generate a warning at the annotated location.
11
12
```java { .api }
13
/**
14
* Annotation indicating that a FindBugs warning is expected.
15
*
16
* @deprecated The annotation based approach is useless for lambdas.
17
* Write expectations using edu.umd.cs.findbugs.test.matcher.BugInstanceMatcher
18
* matchers in test source directory
19
*/
20
@Deprecated
21
@Retention(RetentionPolicy.CLASS)
22
@interface ExpectWarning {
23
/**
24
* The value indicates the bug code (e.g., NP) or bug pattern (e.g.,
25
* IL_INFINITE_LOOP) of the expected warning. Can be a comma-separated list.
26
*/
27
String value();
28
29
/** Want a warning at this priority or higher */
30
Confidence confidence() default Confidence.LOW;
31
32
/** Expect a warning at least this scary */
33
int rank() default 20;
34
35
/** Expect at least this many warnings */
36
int num() default 1;
37
}
38
```
39
40
**Usage Examples:**
41
42
```java
43
public class AnalysisTestClass {
44
45
// Expect null pointer warning
46
@ExpectWarning("NP_NULL_ON_SOME_PATH")
47
public void methodWithNullIssue() {
48
String str = null;
49
System.out.println(str.length()); // Should trigger null pointer warning
50
}
51
52
// Expect multiple warnings (note: deprecated approach)
53
@ExpectWarning(value = "EI_EXPOSE_REP,EI_EXPOSE_REP2", num = 2)
54
public Date[] getDatesWithExposure() {
55
return internalDates; // Should trigger representation exposure warnings
56
}
57
58
// Expect specific number of warnings
59
@ExpectWarning(value = "URF_UNREAD_FIELD", num = 3)
60
public class ClassWithUnreadFields {
61
private String unreadField1; // Should trigger warning
62
private String unreadField2; // Should trigger warning
63
private String unreadField3; // Should trigger warning
64
private String usedField; // Should not trigger warning
65
66
public void useField() {
67
System.out.println(usedField);
68
}
69
}
70
71
// Test resource leak detection
72
@ExpectWarning("OS_OPEN_STREAM")
73
public void methodWithResourceLeak() throws IOException {
74
FileInputStream stream = new FileInputStream("test.txt");
75
// Stream not closed - should trigger warning
76
stream.read();
77
}
78
}
79
80
// Package-level testing
81
@ExpectWarning(value = "UWF_UNWRITTEN_FIELD", num = 5)
82
package com.example.test;
83
84
// Class-level testing
85
@ExpectWarning("SE_BAD_FIELD")
86
public class SerializationTestClass implements Serializable {
87
private transient Object nonSerializableField; // Should trigger warning
88
}
89
```
90
91
### NoWarning Annotation
92
93
Indicate that SpotBugs should not generate warnings at the annotated location.
94
95
```java { .api }
96
/**
97
* Annotation indicating that no FindBugs warning is expected.
98
*
99
* @deprecated The annotation based approach is useless for lambdas.
100
* Write expectations using edu.umd.cs.findbugs.test.matcher.BugInstanceMatcher
101
* matchers in test source directory
102
*/
103
@Deprecated
104
@Retention(RetentionPolicy.CLASS)
105
@interface NoWarning {
106
/**
107
* The value indicates the bug code (e.g., NP) or bug pattern (e.g.,
108
* IL_INFINITE_LOOP) that should not be reported
109
*/
110
String value();
111
112
/** Want no warning at this priority or higher */
113
Confidence confidence() default Confidence.LOW;
114
115
/** Want no warning at this rank or scarier */
116
int rank() default 20;
117
118
/** Tolerate up to this many warnings */
119
int num() default 0;
120
}
121
```
122
123
**Usage Examples:**
124
125
```java
126
public class SafeCodeTestClass {
127
128
// This method should not trigger null pointer warnings
129
@NoWarning("NP_NULL_ON_SOME_PATH")
130
public void safeNullHandling(@Nullable String input) {
131
if (input != null) { // Proper null check
132
System.out.println(input.length());
133
}
134
}
135
136
// No resource leak warnings expected
137
@NoWarning("OS_OPEN_STREAM")
138
public void properResourceHandling() throws IOException {
139
try (FileInputStream stream = new FileInputStream("test.txt")) {
140
stream.read(); // Properly closed via try-with-resources
141
}
142
}
143
144
// No representation exposure warnings
145
@NoWarning({"EI_EXPOSE_REP", "EI_EXPOSE_REP2"})
146
public Date[] getSafeDatesCopy() {
147
return Arrays.copyOf(internalDates, internalDates.length); // Returns copy
148
}
149
150
// General - no warnings should be generated
151
@NoWarning
152
public void perfectlyCleanMethod(@NonNull String input) {
153
String processed = input.trim().toLowerCase();
154
logger.info("Processed: " + processed);
155
}
156
}
157
158
// Class-level no warnings
159
@NoWarning("SE_BAD_FIELD")
160
public class WellDesignedSerializable implements Serializable {
161
private static final long serialVersionUID = 1L;
162
private String name; // Properly serializable field
163
private transient Logger logger = LoggerFactory.getLogger(getClass()); // Transient non-serializable
164
}
165
```
166
167
### DesireWarning Annotation
168
169
Indicate that you would like SpotBugs to generate a warning (for testing detector development).
170
171
```java { .api }
172
/**
173
* Annotation indicating that a FindBugs warning is desired.
174
*
175
* @deprecated The annotation based approach is useless for lambdas.
176
* Write expectations using edu.umd.cs.findbugs.test.matcher.BugInstanceMatcher
177
* matchers in test source directory
178
*/
179
@Deprecated
180
@Retention(RetentionPolicy.CLASS)
181
@interface DesireWarning {
182
/**
183
* The value indicates the bug code (e.g., NP) or bug pattern (e.g.,
184
* IL_INFINITE_LOOP) of the desired warning
185
*/
186
String value();
187
188
/** Want a warning at this priority or higher */
189
Confidence confidence() default Confidence.LOW;
190
191
/** Desire a warning at least this scary */
192
int rank() default 20;
193
194
/** Desire at least this many warnings */
195
int num() default 1;
196
}
197
```
198
199
**Usage Examples:**
200
201
```java
202
public class DetectorTestClass {
203
204
// Would like SpotBugs to detect this potential issue
205
@DesireWarning("POTENTIAL_SECURITY_ISSUE")
206
public void methodWithPotentialSecurityProblem() {
207
// Code that might have security implications
208
String userInput = getUserInput();
209
executeCommand(userInput); // Potentially dangerous
210
}
211
212
// Desire warning for performance issue
213
@DesireWarning("PERFORMANCE_ISSUE")
214
public void inefficientMethod() {
215
for (int i = 0; i < 1000000; i++) {
216
String result = ""; // String concatenation in loop
217
for (int j = 0; j < 100; j++) {
218
result += "x"; // Inefficient string building
219
}
220
}
221
}
222
223
// Multiple desired warnings
224
@DesireWarning(value = {"MEMORY_LEAK", "RESOURCE_LEAK"}, num = 2)
225
public void methodWithMultipleIssues() {
226
List<Object> list = new ArrayList<>();
227
while (true) {
228
list.add(new LargeObject()); // Potential memory leak
229
if (someCondition()) {
230
FileInputStream stream = new FileInputStream("file.txt");
231
// Stream not closed - resource leak
232
break;
233
}
234
}
235
}
236
}
237
```
238
239
### DesireNoWarning Annotation
240
241
Indicate that you would prefer SpotBugs not generate warnings (for testing false positive reduction).
242
243
```java { .api }
244
/**
245
* Annotation indicating that no FindBugs warnings of the specified type is desired.
246
*
247
* @deprecated The annotation based approach is useless for lambdas.
248
* Write expectations using edu.umd.cs.findbugs.test.matcher.BugInstanceMatcher
249
* matchers in test source directory
250
*/
251
@Deprecated
252
@Retention(RetentionPolicy.CLASS)
253
@interface DesireNoWarning {
254
/**
255
* The value indicates the bug code (e.g., NP) or bug pattern (e.g.,
256
* IL_INFINITE_LOOP) that is desired to not be reported
257
*/
258
String value();
259
260
/** @deprecated - use confidence instead */
261
@Deprecated
262
Priority priority() default Priority.LOW;
263
264
/** Want no warning at this priority or higher */
265
Confidence confidence() default Confidence.LOW;
266
267
/** Tolerate up to this many warnings */
268
int num() default 0;
269
}
270
```
271
272
**Usage Examples:**
273
274
```java
275
public class FalsePositiveTestClass {
276
277
// This should not trigger null pointer warnings (complex but safe logic)
278
@DesireNoWarning("NP_NULL_ON_SOME_PATH")
279
public void complexButSafeNullHandling(@Nullable String input) {
280
// Complex logic that is actually safe but might confuse analysis
281
String processed = Optional.ofNullable(input)
282
.filter(s -> !s.isEmpty())
283
.map(String::trim)
284
.orElse("default");
285
System.out.println(processed.length()); // Safe due to orElse
286
}
287
288
// Should not warn about unused field (used via reflection)
289
@DesireNoWarning("URF_UNREAD_FIELD")
290
public class ReflectionBasedClass {
291
@SuppressWarnings("unused") // Used via reflection
292
private String reflectionField = "value";
293
294
// Field is accessed via reflection in framework code
295
}
296
297
// Should not warn about synchronization (external synchronization)
298
@DesireNoWarning("IS_FIELD_NOT_GUARDED")
299
public class ExternallySynchronizedClass {
300
private int counter; // Synchronized externally
301
302
// This field is protected by external synchronization mechanism
303
public void increment() {
304
counter++; // Safe due to external synchronization
305
}
306
}
307
}
308
```
309
310
## Testing Workflow Integration
311
312
### Test Suite Integration
313
314
```java
315
/**
316
* Test class for validating SpotBugs detector behavior
317
*/
318
public class SpotBugsDetectorTest {
319
320
// Test that detector correctly identifies issues
321
@Test
322
public void testDetectorFindsIssues() {
323
// Methods annotated with @ExpectWarning should generate warnings
324
testMethodWithExpectedWarnings();
325
}
326
327
@ExpectWarning(value = "NULL_DEREFERENCE", num = 1)
328
private void testMethodWithExpectedWarnings() {
329
String str = null;
330
str.length(); // Should be detected
331
}
332
333
// Test that detector doesn't generate false positives
334
@Test
335
public void testDetectorAvoidsFalsePositives() {
336
// Methods annotated with @NoWarning should not generate warnings
337
testSafeMethod();
338
}
339
340
@NoWarning("NULL_DEREFERENCE")
341
private void testSafeMethod() {
342
String str = getString();
343
if (str != null) {
344
str.length(); // Safe usage
345
}
346
}
347
}
348
```
349
350
### Continuous Integration
351
352
```java
353
// Package-level testing configuration
354
@ExpectWarning(value = "SECURITY_ISSUE", num = 0) // Expect no security issues
355
@NoWarning({"NP_NULL_ON_SOME_PATH", "OS_OPEN_STREAM"}) // These should be clean
356
package com.example.production;
357
```
358
359
### Custom Detector Validation
360
361
```java
362
public class CustomDetectorTest {
363
364
// Test new detector finds the issue
365
@DesireWarning("CUSTOM_PATTERN_ISSUE")
366
public void methodWithCustomIssue() {
367
// Code that should trigger custom detector
368
customPatternThatShouldBeDetected();
369
}
370
371
// Test that custom detector doesn't over-report
372
@DesireNoWarning("CUSTOM_PATTERN_ISSUE")
373
public void methodWithoutCustomIssue() {
374
// Similar code that should not trigger detector
375
safeCustomPattern();
376
}
377
}
378
```
379
380
## Best Practices
381
382
1. **Use in test code**: These annotations are primarily for testing, not production code
383
2. **Validate detectors**: Use @ExpectWarning to ensure detectors find real issues
384
3. **Test false positives**: Use @NoWarning to verify clean code doesn't trigger warnings
385
4. **Guide development**: Use @DesireWarning to specify what new detectors should find
386
5. **Refine analysis**: Use @DesireNoWarning to identify false positive patterns
387
6. **Document test intent**: Include comments explaining why warnings are expected or not expected
388
7. **Regular validation**: Run tests regularly to ensure detector behavior remains consistent
389
8. **Version control**: Track changes in expected warnings as code evolves