or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

default-annotations.mdindex.mdnull-safety.mdresource-management.mdreturn-value-checking.mdtesting-annotations.mdwarning-suppression.md

testing-annotations.mddocs/

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