or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

annotations.mdassertions.mdassumptions.mdcategories.mdindex.mdmatchers.mdrules.mdstandard-runners.mdtest-runners.mdtheories.md

categories.mddocs/

0

# Categories

1

2

Categories is an experimental feature for grouping and filtering tests using marker interfaces. It allows selective test execution based on category annotations, useful for organizing tests by type (unit, integration, performance) or other criteria.

3

4

## Capabilities

5

6

### Category Annotation

7

8

Marks tests or test classes as belonging to one or more categories. Categories are defined as marker interfaces.

9

10

```java { .api }

11

/**

12

* Marks a test method or class as belonging to categories

13

* @param value - Category interface(s) this test belongs to

14

*/

15

@Retention(RetentionPolicy.RUNTIME)

16

@Inherited

17

@ValidateWith(CategoryValidator.class)

18

public @interface Category {

19

Class<?>[] value();

20

}

21

```

22

23

**Usage Examples:**

24

25

```java

26

import org.junit.Test;

27

import org.junit.experimental.categories.Category;

28

import static org.junit.Assert.*;

29

30

// Define category marker interfaces

31

public interface SlowTests {}

32

public interface FastTests {}

33

public interface IntegrationTests {}

34

public interface UnitTests {}

35

36

// Categorize entire test class

37

@Category(UnitTests.class)

38

public class CalculatorTest {

39

@Test

40

public void testAddition() {

41

assertEquals(5, 2 + 3);

42

}

43

44

@Test

45

@Category(SlowTests.class)

46

public void testComplexCalculation() {

47

// This test is both UnitTests and SlowTests

48

performExpensiveCalculation();

49

}

50

}

51

52

// Multiple categories

53

@Category({IntegrationTests.class, SlowTests.class})

54

public class DatabaseTest {

55

@Test

56

public void testConnection() {

57

// Integration and slow test

58

connectToDatabase();

59

}

60

61

@Test

62

@Category(FastTests.class)

63

public void testConfiguration() {

64

// Override: this is fast despite class being slow

65

checkConfig();

66

}

67

}

68

69

// Method-level categories

70

public class MixedTest {

71

@Test

72

@Category(FastTests.class)

73

public void fastTest() {

74

assertTrue(true);

75

}

76

77

@Test

78

@Category(SlowTests.class)

79

public void slowTest() {

80

Thread.sleep(1000);

81

}

82

83

@Test

84

@Category({IntegrationTests.class, SlowTests.class})

85

public void integrationTest() {

86

testExternalSystem();

87

}

88

}

89

```

90

91

### Categories Runner

92

93

Special suite runner that filters tests based on included and excluded categories.

94

95

```java { .api }

96

/**

97

* Suite runner that filters tests by category

98

* Only runs tests matching category criteria

99

*/

100

@RunWith(Suite.class)

101

public class Categories extends Suite {

102

/**

103

* Creates Categories runner

104

* @param klass - Suite class

105

* @param builder - Runner builder

106

* @throws InitializationError if initialization fails

107

*/

108

public Categories(Class<?> klass, RunnerBuilder builder) throws InitializationError;

109

110

/**

111

* Specify categories to include

112

* Only tests with these categories will run

113

*/

114

@Retention(RetentionPolicy.RUNTIME)

115

@Target(ElementType.TYPE)

116

public @interface IncludeCategory {

117

/**

118

* Categories to include

119

*/

120

Class<?>[] value() default {};

121

122

/**

123

* If true, runs tests annotated with any of the categories

124

* Otherwise, runs tests only if annotated with all categories

125

*/

126

boolean matchAny() default true;

127

}

128

129

/**

130

* Specify categories to exclude

131

* Tests with these categories will not run

132

*/

133

@Retention(RetentionPolicy.RUNTIME)

134

@Target(ElementType.TYPE)

135

public @interface ExcludeCategory {

136

/**

137

* Categories to exclude

138

*/

139

Class<?>[] value() default {};

140

141

/**

142

* If true, excludes tests annotated with any of the categories

143

* Otherwise, excludes tests only if annotated with all categories

144

*/

145

boolean matchAny() default true;

146

}

147

}

148

```

149

150

**Usage Examples:**

151

152

```java

153

import org.junit.experimental.categories.Categories;

154

import org.junit.experimental.categories.Categories.IncludeCategory;

155

import org.junit.experimental.categories.Categories.ExcludeCategory;

156

import org.junit.runner.RunWith;

157

import org.junit.runners.Suite.SuiteClasses;

158

159

// Run only fast tests

160

@RunWith(Categories.class)

161

@IncludeCategory(FastTests.class)

162

@SuiteClasses({

163

CalculatorTest.class,

164

StringUtilsTest.class,

165

DateUtilsTest.class,

166

DatabaseTest.class

167

})

168

public class FastTestSuite {

169

// Only tests marked with @Category(FastTests.class) will run

170

}

171

172

// Run all except slow tests

173

@RunWith(Categories.class)

174

@ExcludeCategory(SlowTests.class)

175

@SuiteClasses({

176

CalculatorTest.class,

177

DatabaseTest.class,

178

NetworkTest.class

179

})

180

public class QuickTestSuite {

181

// All tests except those marked @Category(SlowTests.class)

182

}

183

184

// Run integration tests only

185

@RunWith(Categories.class)

186

@IncludeCategory(IntegrationTests.class)

187

@SuiteClasses({

188

DatabaseTest.class,

189

ApiTest.class,

190

NetworkTest.class,

191

FileSystemTest.class

192

})

193

public class IntegrationTestSuite {

194

}

195

196

// Include and exclude together

197

@RunWith(Categories.class)

198

@IncludeCategory(IntegrationTests.class)

199

@ExcludeCategory(SlowTests.class)

200

@SuiteClasses({

201

DatabaseTest.class,

202

ApiTest.class,

203

NetworkTest.class

204

})

205

public class FastIntegrationSuite {

206

// Only fast integration tests

207

}

208

```

209

210

### CategoryFilter

211

212

Programmatic filtering of tests by category. Used for custom test execution.

213

214

```java { .api }

215

/**

216

* Filter for selecting tests by category

217

*/

218

public class CategoryFilter extends Filter {

219

/**

220

* Create filter that includes only matching categories

221

* @param categoryType - Category to include

222

* @return CategoryFilter

223

*/

224

public static CategoryFilter include(Class<?> categoryType);

225

226

/**

227

* Create filter that includes only matching categories

228

* @param includes - Categories to include

229

* @return CategoryFilter

230

*/

231

public static CategoryFilter include(Class<?>... includes);

232

233

/**

234

* Create filter that excludes matching categories

235

* @param categoryType - Category to exclude

236

* @return CategoryFilter

237

*/

238

public static CategoryFilter exclude(Class<?> categoryType);

239

240

/**

241

* Create filter that excludes matching categories

242

* @param excludes - Categories to exclude

243

* @return CategoryFilter

244

*/

245

public static CategoryFilter exclude(Class<?>... excludes);

246

247

/**

248

* Create filter with include and exclude rules

249

* @param matchAnyInclusions - Whether to match any (true) or all (false) inclusion categories

250

* @param inclusions - Set of categories to include

251

* @param matchAnyExclusions - Whether to match any (true) or all (false) exclusion categories

252

* @param exclusions - Set of categories to exclude

253

* @return CategoryFilter

254

*/

255

public static CategoryFilter categoryFilter(

256

boolean matchAnyInclusions,

257

Set<Class<?>> inclusions,

258

boolean matchAnyExclusions,

259

Set<Class<?>> exclusions

260

);

261

262

/**

263

* Check if test should run

264

* @param description - Test description

265

* @return true if test should run

266

*/

267

public boolean shouldRun(Description description);

268

269

/**

270

* Get filter description

271

* @return Description string

272

*/

273

public String describe();

274

}

275

```

276

277

**Usage Examples:**

278

279

```java

280

import org.junit.experimental.categories.CategoryFilter;

281

import org.junit.runner.JUnitCore;

282

import org.junit.runner.Request;

283

import org.junit.runner.Result;

284

import java.util.Set;

285

import java.util.HashSet;

286

287

public class CategoryRunner {

288

public static void main(String[] args) {

289

// Run only fast tests

290

Request request = Request.aClass(AllTests.class);

291

request = request.filterWith(CategoryFilter.include(FastTests.class));

292

Result result = new JUnitCore().run(request);

293

294

// Run all except slow tests

295

Request request2 = Request.aClass(AllTests.class);

296

request2 = request2.filterWith(CategoryFilter.exclude(SlowTests.class));

297

Result result2 = new JUnitCore().run(request2);

298

299

// Complex filtering with categoryFilter

300

Set<Class<?>> inclusions = new HashSet<>();

301

inclusions.add(IntegrationTests.class);

302

Set<Class<?>> exclusions = new HashSet<>();

303

exclusions.add(SlowTests.class);

304

305

CategoryFilter filter = CategoryFilter.categoryFilter(

306

true, // Match any inclusion category

307

inclusions, // Include integration tests

308

true, // Match any exclusion category

309

exclusions // Exclude slow tests

310

);

311

Request request3 = Request.aClass(AllTests.class);

312

request3 = request3.filterWith(filter);

313

Result result3 = new JUnitCore().run(request3);

314

}

315

}

316

317

// Custom test runner with categories

318

public class CustomCategoryRunner {

319

public static Result runCategories(Class<?> testClass, Class<?>... categories) {

320

Request request = Request.aClass(testClass);

321

request = request.filterWith(CategoryFilter.include(categories));

322

return new JUnitCore().run(request);

323

}

324

325

public static void main(String[] args) {

326

// Run specific categories

327

Result result = runCategories(

328

MyTestSuite.class,

329

FastTests.class,

330

UnitTests.class

331

);

332

System.out.println("Tests run: " + result.getRunCount());

333

}

334

}

335

```

336

337

## Common Category Patterns

338

339

### Test Type Categories

340

341

Organize tests by their nature and scope.

342

343

```java

344

// Marker interfaces for test types

345

public interface UnitTests {}

346

public interface IntegrationTests {}

347

public interface EndToEndTests {}

348

public interface PerformanceTests {}

349

public interface SecurityTests {}

350

351

@Category(UnitTests.class)

352

public class BusinessLogicTest {

353

@Test

354

public void testCalculation() {

355

// Pure unit test

356

}

357

}

358

359

@Category(IntegrationTests.class)

360

public class DatabaseIntegrationTest {

361

@Test

362

public void testDatabaseQuery() {

363

// Tests with database

364

}

365

}

366

367

@Category(EndToEndTests.class)

368

public class UserFlowTest {

369

@Test

370

public void testCompleteUserJourney() {

371

// Full system test

372

}

373

}

374

```

375

376

### Speed Categories

377

378

Group tests by execution time for quick feedback loops.

379

380

```java

381

public interface FastTests {} // < 100ms

382

public interface MediumTests {} // 100ms - 1s

383

public interface SlowTests {} // > 1s

384

385

@Category(FastTests.class)

386

public class QuickUnitTest {

387

@Test

388

public void instantTest() {

389

assertEquals(4, 2 + 2);

390

}

391

}

392

393

@Category(SlowTests.class)

394

public class HeavyIntegrationTest {

395

@Test

396

public void testLargeDataset() {

397

processMillionRecords();

398

}

399

}

400

```

401

402

### Environment Categories

403

404

Tests that require specific environments or resources.

405

406

```java

407

public interface RequiresDatabase {}

408

public interface RequiresNetwork {}

409

public interface RequiresDocker {}

410

public interface RequiresLinux {}

411

public interface RequiresWindows {}

412

413

@Category(RequiresDatabase.class)

414

public class DatabaseTest {

415

@Test

416

public void testQuery() {

417

// Needs database

418

}

419

}

420

421

@Category({RequiresNetwork.class, RequiresDocker.class})

422

public class MicroserviceTest {

423

@Test

424

public void testServiceCommunication() {

425

// Needs network and Docker

426

}

427

}

428

```

429

430

### Feature Categories

431

432

Organize by feature or module being tested.

433

434

```java

435

public interface PaymentTests {}

436

public interface AuthenticationTests {}

437

public interface ReportingTests {}

438

public interface NotificationTests {}

439

440

@Category(PaymentTests.class)

441

public class PaymentProcessorTest {

442

@Test

443

public void testPayment() {

444

processPayment();

445

}

446

}

447

448

@Category(AuthenticationTests.class)

449

public class LoginTest {

450

@Test

451

public void testLogin() {

452

authenticateUser();

453

}

454

}

455

```

456

457

### Build Pipeline Categories

458

459

Different category suites for different build stages.

460

461

```java

462

// CI pipeline categories

463

public interface CommitTests {} // Run on every commit

464

public interface NightlyTests {} // Run nightly

465

public interface WeeklyTests {} // Run weekly

466

public interface ManualTests {} // Run manually only

467

468

// Commit stage - fast tests only

469

@RunWith(Categories.class)

470

@IncludeCategory(CommitTests.class)

471

@SuiteClasses({/* all test classes */})

472

public class CommitStageSuite {}

473

474

// Nightly build - all automated tests

475

@RunWith(Categories.class)

476

@ExcludeCategory(ManualTests.class)

477

@SuiteClasses({/* all test classes */})

478

public class NightlyBuildSuite {}

479

480

// Usage in tests

481

@Category(CommitTests.class)

482

public class FastCoreTest {

483

// Runs on every commit

484

}

485

486

@Category({NightlyTests.class, SlowTests.class})

487

public class ExtensiveTest {

488

// Runs in nightly builds

489

}

490

```

491

492

## Maven Integration

493

494

Run specific categories from Maven command line.

495

496

```xml

497

<!-- pom.xml configuration -->

498

<build>

499

<plugins>

500

<plugin>

501

<groupId>org.apache.maven.plugins</groupId>

502

<artifactId>maven-surefire-plugin</artifactId>

503

<version>2.22.2</version>

504

<configuration>

505

<groups>com.example.FastTests</groups>

506

<excludedGroups>com.example.SlowTests</excludedGroups>

507

</configuration>

508

</plugin>

509

</plugins>

510

</build>

511

```

512

513

```bash

514

# Run specific categories from command line

515

mvn test -Dgroups=com.example.FastTests

516

mvn test -DexcludedGroups=com.example.SlowTests

517

mvn test -Dgroups=com.example.UnitTests,com.example.FastTests

518

```

519

520

## Gradle Integration

521

522

Run specific categories from Gradle.

523

524

```groovy

525

// build.gradle configuration

526

test {

527

useJUnit {

528

includeCategories 'com.example.FastTests'

529

excludeCategories 'com.example.SlowTests'

530

}

531

}

532

533

// Custom test tasks for different categories

534

task fastTests(type: Test) {

535

useJUnit {

536

includeCategories 'com.example.FastTests'

537

}

538

}

539

540

task integrationTests(type: Test) {

541

useJUnit {

542

includeCategories 'com.example.IntegrationTests'

543

}

544

}

545

```

546

547

```bash

548

# Run specific test tasks

549

./gradlew fastTests

550

./gradlew integrationTests

551

./gradlew test # All tests

552

```

553

554

## Types

555

556

```java { .api }

557

/**

558

* Base class for test filters

559

*/

560

public abstract class Filter {

561

/**

562

* Returns true if test should run

563

* @param description - Test description

564

* @return true to run test

565

*/

566

public abstract boolean shouldRun(Description description);

567

568

/**

569

* Returns description of filter

570

* @return Description string

571

*/

572

public abstract String describe();

573

574

/**

575

* Compose filters with AND logic

576

* @param second - Second filter

577

* @return Combined filter

578

*/

579

public Filter intersect(Filter second);

580

581

/**

582

* Create filter that matches anything

583

* @return Filter that allows all tests

584

*/

585

public static Filter matchAll();

586

}

587

588

/**

589

* Factory for creating category filters from command line arguments

590

*/

591

public class CategoryFilterFactory implements FilterFactory {

592

/**

593

* Create filter from factory parameters

594

* @param params - Filter parameters

595

* @return CategoryFilter

596

*/

597

public Filter createFilter(FilterFactoryParams params) throws FilterNotCreatedException;

598

}

599

600

/**

601

* Validates Category annotations

602

*/

603

public class CategoryValidator implements AnnotationValidator {

604

/**

605

* Validate category annotations on test class

606

* @param testClass - Test class to validate

607

* @return List of validation errors

608

*/

609

public List<Exception> validateAnnotatedClass(TestClass testClass);

610

}

611

```

612