0
# Test Runners
1
2
Test runners are responsible for executing tests and reporting results. JUnit provides `JUnitCore` as the main facade for running tests programmatically, while the `Runner` class hierarchy enables custom test execution strategies.
3
4
## Capabilities
5
6
### JUnitCore
7
8
The main entry point for running tests programmatically. Can be used from the command line or from Java code to execute test classes and collect results.
9
10
```java { .api }
11
/**
12
* Facade for running tests and collecting results
13
*/
14
public class JUnitCore {
15
/**
16
* Run tests from command line
17
* @param args - Fully qualified class names of test classes
18
*/
19
public static void main(String... args);
20
21
/**
22
* Run tests and return results
23
* @param classes - Test classes to run
24
* @return Results of test execution
25
*/
26
public Result run(Class<?>... classes);
27
28
/**
29
* Run tests and return results (alias for run)
30
* @param classes - Test classes to run
31
* @return Results of test execution
32
*/
33
public Result runClasses(Class<?>... classes);
34
35
/**
36
* Run tests using a Request
37
* @param request - Configured test request
38
* @return Results of test execution
39
*/
40
public Result run(Request request);
41
42
/**
43
* Run tests with a specific runner
44
* @param runner - Runner to use
45
* @return Results of test execution
46
*/
47
public Result run(Runner runner);
48
49
/**
50
* Run a JUnit 3.x style test
51
* @param test - JUnit 3.x Test to run
52
* @return Results of test execution
53
*/
54
public Result run(junit.framework.Test test);
55
56
/**
57
* Add a listener to be notified of test events
58
* @param listener - Listener to add
59
*/
60
public void addListener(RunListener listener);
61
62
/**
63
* Remove a previously added listener
64
* @param listener - Listener to remove
65
*/
66
public void removeListener(RunListener listener);
67
68
/**
69
* Get JUnit version string
70
* @return Version string (e.g., "4.13.2")
71
*/
72
public String getVersion();
73
}
74
```
75
76
**Usage Examples:**
77
78
```java
79
import org.junit.runner.JUnitCore;
80
import org.junit.runner.Result;
81
import org.junit.runner.notification.Failure;
82
83
public class TestRunner {
84
public static void main(String[] args) {
85
// Run single test class
86
Result result = JUnitCore.runClasses(MyTest.class);
87
System.out.println("Tests run: " + result.getRunCount());
88
System.out.println("Failures: " + result.getFailureCount());
89
90
// Run multiple test classes
91
Result multiResult = JUnitCore.runClasses(
92
TestClass1.class,
93
TestClass2.class,
94
TestClass3.class
95
);
96
97
// Check results
98
if (!multiResult.wasSuccessful()) {
99
System.out.println("Some tests failed:");
100
for (Failure failure : multiResult.getFailures()) {
101
System.out.println(failure.toString());
102
}
103
}
104
105
// Print execution time
106
System.out.println("Execution time: " + multiResult.getRunTime() + "ms");
107
}
108
}
109
```
110
111
```java
112
import org.junit.runner.JUnitCore;
113
import org.junit.runner.Result;
114
import org.junit.runner.notification.RunListener;
115
import org.junit.runner.Description;
116
import org.junit.runner.notification.Failure;
117
118
public class CustomTestRunner {
119
public static void main(String[] args) {
120
JUnitCore core = new JUnitCore();
121
122
// Add custom listener
123
core.addListener(new RunListener() {
124
@Override
125
public void testStarted(Description description) {
126
System.out.println("Starting: " + description.getDisplayName());
127
}
128
129
@Override
130
public void testFinished(Description description) {
131
System.out.println("Finished: " + description.getDisplayName());
132
}
133
134
@Override
135
public void testFailure(Failure failure) {
136
System.out.println("Failed: " + failure.getDescription().getDisplayName());
137
}
138
});
139
140
Result result = core.run(MyTest.class);
141
System.exit(result.wasSuccessful() ? 0 : 1);
142
}
143
}
144
```
145
146
### Result
147
148
Collects and summarizes test execution results. Contains counts of runs, failures, and ignored tests, along with timing information.
149
150
```java { .api }
151
/**
152
* Test execution results
153
*/
154
public class Result implements Serializable {
155
/**
156
* Get number of tests that were run
157
* @return Count of executed tests
158
*/
159
public int getRunCount();
160
161
/**
162
* Get number of tests that failed
163
* @return Count of failed tests
164
*/
165
public int getFailureCount();
166
167
/**
168
* Get number of tests that were ignored
169
* @return Count of ignored tests
170
*/
171
public int getIgnoreCount();
172
173
/**
174
* Get number of assumption failures
175
* @return Count of assumption failures (tests skipped)
176
*/
177
public int getAssumptionFailureCount();
178
179
/**
180
* Get total execution time in milliseconds
181
* @return Execution time in milliseconds
182
*/
183
public long getRunTime();
184
185
/**
186
* Get list of all failures
187
* @return List of Failure objects
188
*/
189
public List<Failure> getFailures();
190
191
/**
192
* Check if all tests passed
193
* @return true if no failures or assumption violations
194
*/
195
public boolean wasSuccessful();
196
197
/**
198
* Create a listener that populates this result
199
* @return RunListener that updates this result
200
*/
201
public RunListener createListener();
202
}
203
```
204
205
**Usage Examples:**
206
207
```java
208
import org.junit.runner.JUnitCore;
209
import org.junit.runner.Result;
210
import org.junit.runner.notification.Failure;
211
212
public class ResultAnalyzer {
213
public static void analyzeResults(Result result) {
214
System.out.println("=== Test Results ===");
215
System.out.println("Tests run: " + result.getRunCount());
216
System.out.println("Failures: " + result.getFailureCount());
217
System.out.println("Ignored: " + result.getIgnoreCount());
218
System.out.println("Assumptions failed: " + result.getAssumptionFailureCount());
219
System.out.println("Time: " + result.getRunTime() + "ms");
220
System.out.println("Success: " + result.wasSuccessful());
221
222
if (!result.wasSuccessful()) {
223
System.out.println("\n=== Failures ===");
224
for (Failure failure : result.getFailures()) {
225
System.out.println(failure.getTestHeader());
226
System.out.println(failure.getMessage());
227
System.out.println(failure.getTrace());
228
}
229
}
230
}
231
232
public static void main(String[] args) {
233
Result result = JUnitCore.runClasses(MyTest.class);
234
analyzeResults(result);
235
}
236
}
237
```
238
239
### Runner
240
241
Abstract base class for test runners. Custom runners extend this class to implement specialized test execution strategies.
242
243
```java { .api }
244
/**
245
* Base class for test runners
246
*/
247
public abstract class Runner implements Describable {
248
/**
249
* Get description of tests this runner will execute
250
* @return Description object
251
*/
252
public abstract Description getDescription();
253
254
/**
255
* Run the tests, notifying the given notifier of events
256
* @param notifier - Notifier for test events
257
*/
258
public abstract void run(RunNotifier notifier);
259
260
/**
261
* Get count of tests that will be run
262
* @return Number of tests
263
*/
264
public int testCount();
265
}
266
```
267
268
**Usage Examples:**
269
270
```java
271
import org.junit.runner.Runner;
272
import org.junit.runner.Description;
273
import org.junit.runner.notification.RunNotifier;
274
import org.junit.runners.model.InitializationError;
275
276
public class CustomRunner extends Runner {
277
private Class<?> testClass;
278
279
public CustomRunner(Class<?> testClass) throws InitializationError {
280
this.testClass = testClass;
281
}
282
283
@Override
284
public Description getDescription() {
285
return Description.createSuiteDescription(testClass);
286
}
287
288
@Override
289
public void run(RunNotifier notifier) {
290
Description description = getDescription();
291
notifier.fireTestStarted(description);
292
293
try {
294
// Custom test execution logic
295
Object testInstance = testClass.getDeclaredConstructor().newInstance();
296
// Run test methods...
297
notifier.fireTestFinished(description);
298
} catch (Exception e) {
299
notifier.fireTestFailure(new Failure(description, e));
300
}
301
}
302
}
303
```
304
305
### Request
306
307
Encapsulates a request to run tests with specific configuration. Supports filtering, sorting, and custom runners.
308
309
```java { .api }
310
/**
311
* A request to run tests
312
*/
313
public abstract class Request {
314
/**
315
* Create a request to run all tests in classes
316
* @param computer - Strategy for running tests
317
* @param classes - Test classes to run
318
* @return Request object
319
*/
320
public static Request classes(Computer computer, Class<?>... classes);
321
322
/**
323
* Create a request to run all tests in classes
324
* @param classes - Test classes to run
325
* @return Request object
326
*/
327
public static Request classes(Class<?>... classes);
328
329
/**
330
* Create a request to run tests with a custom runner
331
* @param runner - Runner to use
332
* @return Request object
333
*/
334
public static Request runner(Runner runner);
335
336
/**
337
* Create a request to run a single method
338
* @param clazz - Test class
339
* @param methodName - Method name
340
* @return Request object
341
*/
342
public static Request method(Class<?> clazz, String methodName);
343
344
/**
345
* Create a request for a test suite
346
* @param clazz - Test class
347
* @return Request object
348
*/
349
public static Request aClass(Class<?> clazz);
350
351
/**
352
* Create a request for a test class without JUnit 3 suite() method
353
* @param clazz - Test class
354
* @return Request object
355
*/
356
public static Request classWithoutSuiteMethod(Class<?> clazz);
357
358
/**
359
* Create a request that will report an error
360
* @param klass - Test class that has error
361
* @param cause - Exception that caused the error
362
* @return Request object
363
*/
364
public static Request errorReport(Class<?> klass, Throwable cause);
365
366
/**
367
* Get the runner for this request
368
* @return Runner object
369
*/
370
public abstract Runner getRunner();
371
372
/**
373
* Filter the tests to run
374
* @param filter - Filter to apply
375
* @return Filtered request
376
*/
377
public Request filterWith(Filter filter);
378
379
/**
380
* Filter the tests by description
381
* @param desiredDescription - Description to match
382
* @return Filtered request
383
*/
384
public Request filterWith(Description desiredDescription);
385
386
/**
387
* Sort the tests
388
* @param comparator - Comparison function for ordering
389
* @return Sorted request
390
*/
391
public Request sortWith(Comparator<Description> comparator);
392
393
/**
394
* Order the tests using an Ordering
395
* @param ordering - Ordering to apply
396
* @return Ordered request
397
*/
398
public Request orderWith(Ordering ordering);
399
}
400
```
401
402
**Usage Examples:**
403
404
```java
405
import org.junit.runner.JUnitCore;
406
import org.junit.runner.Request;
407
import org.junit.runner.Result;
408
409
public class RequestExamples {
410
public static void runSingleMethod() {
411
// Run just one test method
412
Request request = Request.method(MyTest.class, "testAddition");
413
Result result = new JUnitCore().run(request);
414
}
415
416
public static void runWithFilter() {
417
// Run only fast tests
418
Request request = Request.aClass(MyTest.class);
419
request = request.filterWith(new CategoryFilter(FastTests.class));
420
Result result = new JUnitCore().run(request);
421
}
422
423
public static void runSorted() {
424
// Run tests in specific order
425
Request request = Request.aClass(MyTest.class);
426
request = request.sortWith(new Comparator<Description>() {
427
public int compare(Description d1, Description d2) {
428
return d1.getMethodName().compareTo(d2.getMethodName());
429
}
430
});
431
Result result = new JUnitCore().run(request);
432
}
433
}
434
```
435
436
### RunNotifier
437
438
Notifies listeners about test execution events. Used by runners to report test progress.
439
440
```java { .api }
441
/**
442
* Notifies listeners of test execution events
443
*/
444
public class RunNotifier {
445
/**
446
* Add a listener
447
* @param listener - Listener to add
448
*/
449
public void addListener(RunListener listener);
450
451
/**
452
* Add a listener at the front of the list
453
* @param listener - Listener to add first
454
*/
455
public void addFirstListener(RunListener listener);
456
457
/**
458
* Remove a listener
459
* @param listener - Listener to remove
460
*/
461
public void removeListener(RunListener listener);
462
463
/**
464
* Notify that a test suite is starting
465
* @param description - Description of suite
466
*/
467
public void fireTestSuiteStarted(Description description);
468
469
/**
470
* Notify that a test suite finished
471
* @param description - Description of suite
472
*/
473
public void fireTestSuiteFinished(Description description);
474
475
/**
476
* Notify that test run started
477
* @param description - Description of run
478
*/
479
public void fireTestRunStarted(Description description);
480
481
/**
482
* Notify that test run finished
483
* @param result - Result of test run
484
*/
485
public void fireTestRunFinished(Result result);
486
487
/**
488
* Notify that a test started
489
* @param description - Description of test
490
*/
491
public void fireTestStarted(Description description);
492
493
/**
494
* Notify that a test finished
495
* @param description - Description of test
496
*/
497
public void fireTestFinished(Description description);
498
499
/**
500
* Notify that a test failed
501
* @param failure - Failure information
502
*/
503
public void fireTestFailure(Failure failure);
504
505
/**
506
* Notify that a test was ignored
507
* @param description - Description of ignored test
508
*/
509
public void fireTestIgnored(Description description);
510
511
/**
512
* Notify that an assumption failed (test skipped)
513
* @param failure - Assumption failure
514
*/
515
public void fireTestAssumptionFailed(Failure failure);
516
517
/**
518
* Request that test run stop
519
*/
520
public void pleaseStop();
521
}
522
```
523
524
### RunListener
525
526
Abstract class for listening to test execution events. Extend this to create custom test reporters or loggers.
527
528
```java { .api }
529
/**
530
* Listener for test execution events
531
*/
532
public abstract class RunListener {
533
/**
534
* Called when test run starts
535
* @param description - Description of test run
536
*/
537
public void testRunStarted(Description description) throws Exception;
538
539
/**
540
* Called when test run finishes
541
* @param result - Result of test run
542
*/
543
public void testRunFinished(Result result) throws Exception;
544
545
/**
546
* Called when test suite starts
547
* @param description - Description of suite
548
*/
549
public void testSuiteStarted(Description description) throws Exception;
550
551
/**
552
* Called when test suite finishes
553
* @param description - Description of suite
554
*/
555
public void testSuiteFinished(Description description) throws Exception;
556
557
/**
558
* Called when a test starts
559
* @param description - Description of test
560
*/
561
public void testStarted(Description description) throws Exception;
562
563
/**
564
* Called when a test finishes
565
* @param description - Description of test
566
*/
567
public void testFinished(Description description) throws Exception;
568
569
/**
570
* Called when a test fails
571
* @param failure - Failure information
572
*/
573
public void testFailure(Failure failure) throws Exception;
574
575
/**
576
* Called when an assumption fails (test skipped)
577
* @param failure - Assumption failure
578
*/
579
public void testAssumptionFailure(Failure failure);
580
581
/**
582
* Called when a test is ignored
583
* @param description - Description of ignored test
584
*/
585
public void testIgnored(Description description) throws Exception;
586
}
587
```
588
589
**Usage Examples:**
590
591
```java
592
import org.junit.runner.notification.RunListener;
593
import org.junit.runner.Description;
594
import org.junit.runner.notification.Failure;
595
import org.junit.runner.Result;
596
597
public class DetailedLogger extends RunListener {
598
private long startTime;
599
600
@Override
601
public void testRunStarted(Description description) {
602
System.out.println("Starting test run: " + description.getDisplayName());
603
startTime = System.currentTimeMillis();
604
}
605
606
@Override
607
public void testRunFinished(Result result) {
608
long duration = System.currentTimeMillis() - startTime;
609
System.out.println("Test run finished in " + duration + "ms");
610
System.out.println("Tests: " + result.getRunCount());
611
System.out.println("Failures: " + result.getFailureCount());
612
System.out.println("Ignored: " + result.getIgnoreCount());
613
}
614
615
@Override
616
public void testStarted(Description description) {
617
System.out.println(" Running: " + description.getMethodName());
618
}
619
620
@Override
621
public void testFinished(Description description) {
622
System.out.println(" Finished: " + description.getMethodName());
623
}
624
625
@Override
626
public void testFailure(Failure failure) {
627
System.err.println(" FAILED: " + failure.getDescription().getMethodName());
628
System.err.println(" " + failure.getMessage());
629
}
630
631
@Override
632
public void testIgnored(Description description) {
633
System.out.println(" IGNORED: " + description.getMethodName());
634
}
635
}
636
637
// Usage
638
JUnitCore core = new JUnitCore();
639
core.addListener(new DetailedLogger());
640
core.run(MyTest.class);
641
```
642
643
### Filter
644
645
Filters tests based on custom criteria. Runners that implement `Filterable` can have filters applied to remove tests that don't match. Commonly used to run specific test methods or exclude certain categories.
646
647
```java { .api }
648
/**
649
* Abstract base class for filtering tests
650
*/
651
public abstract class Filter {
652
/**
653
* A null Filter that passes all tests through
654
*/
655
public static final Filter ALL;
656
657
/**
658
* Returns a Filter that only runs the single method described by desiredDescription
659
* @param desiredDescription - Description to match
660
* @return Filter that matches only this description
661
*/
662
public static Filter matchMethodDescription(Description desiredDescription);
663
664
/**
665
* Determine if the test should be run
666
* @param description - Description of the test
667
* @return true if the test should be run
668
*/
669
public abstract boolean shouldRun(Description description);
670
671
/**
672
* Returns a textual description of this Filter
673
* @return Description string
674
*/
675
public abstract String describe();
676
677
/**
678
* Invoke with a Runner to cause all tests it intends to run to first be checked with the filter
679
* @param child - The runner to be filtered
680
* @throws NoTestsRemainException if the receiver removes all tests
681
*/
682
public void apply(Object child) throws NoTestsRemainException;
683
684
/**
685
* Returns a new Filter that accepts the intersection of tests accepted by this Filter and second
686
* @param second - Filter to intersect with
687
* @return Intersected filter
688
*/
689
public Filter intersect(Filter second);
690
}
691
```
692
693
**Usage Examples:**
694
695
```java
696
import org.junit.runner.JUnitCore;
697
import org.junit.runner.Request;
698
import org.junit.runner.manipulation.Filter;
699
import org.junit.runner.Description;
700
701
public class FilterExamples {
702
// Run only a single test method
703
public static void runSingleMethod() {
704
Request request = Request.aClass(MyTest.class);
705
Description methodDesc = Description.createTestDescription(
706
MyTest.class, "testAddition");
707
request = request.filterWith(Filter.matchMethodDescription(methodDesc));
708
new JUnitCore().run(request);
709
}
710
711
// Custom filter for fast tests
712
public static void runFastTests() {
713
Request request = Request.aClass(MyTest.class);
714
request = request.filterWith(new Filter() {
715
@Override
716
public boolean shouldRun(Description description) {
717
// Run if annotated with @Fast or if it's a suite
718
return description.getAnnotation(Fast.class) != null
719
|| !description.isTest();
720
}
721
722
@Override
723
public String describe() {
724
return "fast tests only";
725
}
726
});
727
new JUnitCore().run(request);
728
}
729
730
// Combine multiple filters
731
public static void runIntersectedFilters() {
732
Filter fastFilter = new FastTestFilter();
733
Filter categoryFilter = new CategoryFilter(DatabaseTests.class);
734
735
// Run tests that match both filters
736
Filter combined = fastFilter.intersect(categoryFilter);
737
Request request = Request.aClass(MyTest.class).filterWith(combined);
738
new JUnitCore().run(request);
739
}
740
}
741
```
742
743
### Filterable
744
745
Interface for runners that support test filtering. Implement this interface to allow tests to be filtered at runtime.
746
747
```java { .api }
748
/**
749
* Interface for runners that allow filtering
750
*/
751
public interface Filterable {
752
/**
753
* Remove tests that don't pass the parameter filter
754
* @param filter - The Filter to apply
755
* @throws NoTestsRemainException if all tests are filtered out
756
*/
757
void filter(Filter filter) throws NoTestsRemainException;
758
}
759
```
760
761
### Sortable
762
763
Interface for runners that support test sorting. Implement this interface to allow tests to be sorted by custom criteria.
764
765
```java { .api }
766
/**
767
* Interface for runners that allow sorting of tests
768
*/
769
public interface Sortable {
770
/**
771
* Sorts the tests using sorter
772
* @param sorter - The Sorter to use for sorting the tests
773
*/
774
void sort(Sorter sorter);
775
}
776
```
777
778
### Orderable
779
780
Interface for runners that support test ordering. Extends `Sortable` to provide more powerful ordering capabilities through the `Orderer` class. While `Sortable` uses comparators for simple sorting, `Orderable` supports complex ordering strategies including shuffling and custom ordering algorithms.
781
782
```java { .api }
783
/**
784
* Interface for runners that allow ordering of tests
785
*
786
* Beware of using this interface to cope with order dependencies between tests.
787
* Tests that are isolated from each other are less expensive to maintain and
788
* can be run individually.
789
*
790
* @since 4.13
791
*/
792
public interface Orderable extends Sortable {
793
/**
794
* Orders the tests using orderer
795
* @param orderer - The Orderer to apply
796
* @throws InvalidOrderingException if orderer does something invalid (like remove or add children)
797
*/
798
void order(Orderer orderer) throws InvalidOrderingException;
799
}
800
```
801
802
**Usage Examples:**
803
804
```java
805
import org.junit.runner.manipulation.Orderable;
806
import org.junit.runner.manipulation.Orderer;
807
import org.junit.runner.manipulation.Ordering;
808
import org.junit.runner.manipulation.InvalidOrderingException;
809
import org.junit.runner.Description;
810
import java.util.Random;
811
812
public class OrderableRunnerExample {
813
// Using Request.orderWith() to order tests (recommended approach)
814
public static void orderTestsWithShuffle() {
815
Request request = Request.aClass(MyTest.class);
816
817
// Create a shuffled ordering with a specific seed for reproducibility
818
Random random = new Random(12345L);
819
Ordering ordering = Ordering.shuffledBy(random);
820
821
// Apply ordering to request
822
request = request.orderWith(ordering);
823
new JUnitCore().run(request);
824
}
825
826
// Custom runner implementing Orderable
827
public static class CustomOrderableRunner extends Runner implements Orderable {
828
private List<Description> children;
829
830
@Override
831
public void order(Orderer orderer) throws InvalidOrderingException {
832
// Let the orderer determine the order
833
children = orderer.order(children);
834
}
835
836
@Override
837
public void sort(Sorter sorter) {
838
// Also support simple sorting
839
Collections.sort(children, sorter);
840
}
841
842
@Override
843
public Description getDescription() {
844
Description suite = Description.createSuiteDescription("Custom Suite");
845
for (Description child : children) {
846
suite.addChild(child);
847
}
848
return suite;
849
}
850
851
@Override
852
public void run(RunNotifier notifier) {
853
// Run tests in the ordered sequence
854
for (Description child : children) {
855
notifier.fireTestStarted(child);
856
// Execute test...
857
notifier.fireTestFinished(child);
858
}
859
}
860
}
861
}
862
```
863
864
### Sorter
865
866
Orders tests using a comparator. Generally used through `Request.sortWith()` rather than directly.
867
868
```java { .api }
869
/**
870
* Orders tests based on a comparator
871
*/
872
public class Sorter extends Ordering implements Comparator<Description> {
873
/**
874
* NULL is a Sorter that leaves elements in an undefined order
875
*/
876
public static final Sorter NULL;
877
878
/**
879
* Creates a Sorter that uses comparator to sort tests
880
* @param comparator - The Comparator to use when sorting tests
881
*/
882
public Sorter(Comparator<Description> comparator);
883
884
/**
885
* Sorts the tests in target using comparator
886
* @param target - Runner to sort (typically implements Sortable)
887
*/
888
public void apply(Object target);
889
890
/**
891
* Compare two descriptions
892
* @param o1 - First description
893
* @param o2 - Second description
894
* @return Comparison result
895
*/
896
public int compare(Description o1, Description o2);
897
}
898
```
899
900
**Usage Examples:**
901
902
```java
903
import org.junit.runner.JUnitCore;
904
import org.junit.runner.Request;
905
import org.junit.runner.manipulation.Sorter;
906
import org.junit.runner.Description;
907
import java.util.Comparator;
908
909
public class SorterExamples {
910
// Sort tests alphabetically by method name
911
public static void runAlphabetically() {
912
Request request = Request.aClass(MyTest.class);
913
request = request.sortWith(new Comparator<Description>() {
914
public int compare(Description d1, Description d2) {
915
return d1.getMethodName().compareTo(d2.getMethodName());
916
}
917
});
918
new JUnitCore().run(request);
919
}
920
921
// Sort tests by annotation priority
922
public static void runByPriority() {
923
Sorter sorter = new Sorter(new Comparator<Description>() {
924
public int compare(Description d1, Description d2) {
925
Priority p1 = d1.getAnnotation(Priority.class);
926
Priority p2 = d2.getAnnotation(Priority.class);
927
int priority1 = (p1 != null) ? p1.value() : Integer.MAX_VALUE;
928
int priority2 = (p2 != null) ? p2.value() : Integer.MAX_VALUE;
929
return Integer.compare(priority1, priority2);
930
}
931
});
932
933
Request request = Request.aClass(MyTest.class);
934
request = request.sortWith(sorter);
935
new JUnitCore().run(request);
936
}
937
}
938
```
939
940
### Alphanumeric
941
942
Built-in sorter that orders tests alphanumerically by display name. Implements both `Sorter` and `Ordering.Factory`, making it usable with both the `sortWith()` and `orderWith()` APIs. This is a convenient way to get consistent, alphabetical test execution without writing custom comparison logic.
943
944
```java { .api }
945
/**
946
* A sorter that orders tests alphanumerically by test name
947
* @since 4.13
948
*/
949
public final class Alphanumeric extends Sorter implements Ordering.Factory {
950
/**
951
* Creates an Alphanumeric sorter
952
*/
953
public Alphanumeric();
954
955
/**
956
* Creates an Ordering instance using the given context
957
* @param context - Context for creating ordering
958
* @return This Alphanumeric instance as an Ordering
959
*/
960
public Ordering create(Context context);
961
}
962
```
963
964
**Usage Examples:**
965
966
```java
967
import org.junit.runner.JUnitCore;
968
import org.junit.runner.Request;
969
import org.junit.runner.manipulation.Alphanumeric;
970
971
public class AlphanumericExamples {
972
// Sort tests alphabetically using sortWith
973
public static void sortAlphabetically() {
974
Request request = Request.aClass(MyTest.class);
975
request = request.sortWith(new Alphanumeric());
976
new JUnitCore().run(request);
977
}
978
979
// Order tests alphabetically using orderWith
980
public static void orderAlphabetically() {
981
Request request = Request.aClass(MyTest.class);
982
Alphanumeric alphanumeric = new Alphanumeric();
983
try {
984
request = request.orderWith(
985
alphanumeric.create(null) // Context not needed for Alphanumeric
986
);
987
} catch (Exception e) {
988
e.printStackTrace();
989
}
990
new JUnitCore().run(request);
991
}
992
993
// Example test class - methods will run in alphabetical order
994
public static class MyTest {
995
@Test
996
public void testZebra() { }
997
998
@Test
999
public void testApple() { }
1000
1001
@Test
1002
public void testMango() { }
1003
1004
// Execution order with Alphanumeric:
1005
// 1. testApple
1006
// 2. testMango
1007
// 3. testZebra
1008
}
1009
}
1010
```
1011
1012
### FilterFactory
1013
1014
Interface for creating filters from command-line arguments or configuration. Filter factories enable dynamic filter creation based on string specifications, making it easy to filter tests without hardcoding filter logic.
1015
1016
```java { .api }
1017
/**
1018
* Extend this class to create a factory that creates Filter
1019
*/
1020
public interface FilterFactory {
1021
/**
1022
* Creates a Filter given a FilterFactoryParams argument
1023
* @param params - Parameters needed to create the Filter
1024
* @return Created filter
1025
* @throws FilterNotCreatedException if the Filter cannot be created
1026
*/
1027
Filter createFilter(FilterFactoryParams params) throws FilterNotCreatedException;
1028
1029
/**
1030
* Exception thrown if the Filter cannot be created
1031
*/
1032
class FilterNotCreatedException extends Exception {
1033
public FilterNotCreatedException(Exception exception);
1034
}
1035
}
1036
```
1037
1038
**Usage Examples:**
1039
1040
```java
1041
import org.junit.runner.FilterFactory;
1042
import org.junit.runner.FilterFactoryParams;
1043
import org.junit.runner.manipulation.Filter;
1044
import org.junit.runner.Description;
1045
1046
// Custom filter factory that filters by test name pattern
1047
public class NamePatternFilterFactory implements FilterFactory {
1048
@Override
1049
public Filter createFilter(FilterFactoryParams params)
1050
throws FilterNotCreatedException {
1051
final String pattern = params.getArgs();
1052
1053
if (pattern == null || pattern.isEmpty()) {
1054
throw new FilterNotCreatedException(
1055
new IllegalArgumentException("Pattern cannot be empty")
1056
);
1057
}
1058
1059
return new Filter() {
1060
@Override
1061
public boolean shouldRun(Description description) {
1062
if (!description.isTest()) {
1063
return true; // Include suites
1064
}
1065
String methodName = description.getMethodName();
1066
return methodName != null && methodName.contains(pattern);
1067
}
1068
1069
@Override
1070
public String describe() {
1071
return "tests containing '" + pattern + "'";
1072
}
1073
};
1074
}
1075
}
1076
1077
// Custom filter factory that filters by annotation
1078
public class AnnotationFilterFactory implements FilterFactory {
1079
@Override
1080
public Filter createFilter(FilterFactoryParams params)
1081
throws FilterNotCreatedException {
1082
final String annotationName = params.getArgs();
1083
1084
try {
1085
final Class<?> annotationClass = Class.forName(annotationName);
1086
1087
return new Filter() {
1088
@Override
1089
public boolean shouldRun(Description description) {
1090
if (!description.isTest()) {
1091
return true;
1092
}
1093
return description.getAnnotation(annotationClass) != null;
1094
}
1095
1096
@Override
1097
public String describe() {
1098
return "tests with @" + annotationClass.getSimpleName();
1099
}
1100
};
1101
} catch (ClassNotFoundException e) {
1102
throw new FilterNotCreatedException(e);
1103
}
1104
}
1105
}
1106
1107
// Usage: From command line or programmatically
1108
// java org.junit.runner.JUnitCore \
1109
// --filter=com.example.NamePatternFilterFactory=integration \
1110
// com.example.MyTestClass
1111
```
1112
1113
### FilterFactories
1114
1115
Utility class for creating filters from filter specifications. Supports parsing filter specs in the format `"package.FilterFactory=args"` and instantiating the appropriate filter factory. Used internally by JUnit's command-line runner but can also be used programmatically.
1116
1117
```java { .api }
1118
/**
1119
* Utility class whose methods create a FilterFactory
1120
*/
1121
class FilterFactories {
1122
/**
1123
* Creates a Filter from a filter specification
1124
*
1125
* A filter specification is of the form "package.of.FilterFactory=args-to-filter-factory"
1126
* or "package.of.FilterFactory"
1127
*
1128
* @param request - The request that will be filtered
1129
* @param filterSpec - The filter specification
1130
* @return Created filter
1131
* @throws FilterFactory.FilterNotCreatedException if filter cannot be created
1132
*/
1133
public static Filter createFilterFromFilterSpec(Request request, String filterSpec)
1134
throws FilterFactory.FilterNotCreatedException;
1135
1136
/**
1137
* Creates a Filter from a fully qualified class name
1138
* @param filterFactoryFqcn - The fully qualified class name of the FilterFactory
1139
* @param params - The arguments to the FilterFactory
1140
* @return Created filter
1141
* @throws FilterFactory.FilterNotCreatedException if filter cannot be created
1142
*/
1143
public static Filter createFilter(String filterFactoryFqcn, FilterFactoryParams params)
1144
throws FilterFactory.FilterNotCreatedException;
1145
1146
/**
1147
* Creates a Filter from a FilterFactory class
1148
* @param filterFactoryClass - The class of the FilterFactory
1149
* @param params - The arguments to the FilterFactory
1150
* @return Created filter
1151
* @throws FilterFactory.FilterNotCreatedException if filter cannot be created
1152
*/
1153
public static Filter createFilter(Class<? extends FilterFactory> filterFactoryClass,
1154
FilterFactoryParams params)
1155
throws FilterFactory.FilterNotCreatedException;
1156
}
1157
```
1158
1159
**Usage Examples:**
1160
1161
```java
1162
import org.junit.runner.Request;
1163
import org.junit.runner.FilterFactories;
1164
import org.junit.runner.FilterFactoryParams;
1165
import org.junit.runner.manipulation.Filter;
1166
import org.junit.runner.JUnitCore;
1167
1168
public class FilterFactoriesExamples {
1169
// Parse and apply a filter specification
1170
public static void useFilterSpec() {
1171
Request request = Request.aClass(MyTest.class);
1172
1173
try {
1174
// Format: "full.package.FilterFactoryClass=arguments"
1175
String filterSpec = "com.example.NamePatternFilterFactory=integration";
1176
Filter filter = FilterFactories.createFilterFromFilterSpec(request, filterSpec);
1177
1178
request = request.filterWith(filter);
1179
new JUnitCore().run(request);
1180
} catch (FilterFactory.FilterNotCreatedException e) {
1181
System.err.println("Failed to create filter: " + e.getMessage());
1182
}
1183
}
1184
1185
// Create filter from factory class directly
1186
public static void useFactoryClass() {
1187
Request request = Request.aClass(MyTest.class);
1188
1189
try {
1190
FilterFactoryParams params = new FilterFactoryParams(
1191
request.getRunner().getDescription(),
1192
"Fast" // Arguments for the factory
1193
);
1194
1195
Filter filter = FilterFactories.createFilter(
1196
AnnotationFilterFactory.class,
1197
params
1198
);
1199
1200
request = request.filterWith(filter);
1201
new JUnitCore().run(request);
1202
} catch (FilterFactory.FilterNotCreatedException e) {
1203
System.err.println("Failed to create filter: " + e.getMessage());
1204
}
1205
}
1206
1207
// Create filter without arguments
1208
public static void useFilterWithoutArgs() {
1209
Request request = Request.aClass(MyTest.class);
1210
1211
try {
1212
String filterSpec = "com.example.FastTestFilterFactory";
1213
Filter filter = FilterFactories.createFilterFromFilterSpec(request, filterSpec);
1214
1215
request = request.filterWith(filter);
1216
new JUnitCore().run(request);
1217
} catch (FilterFactory.FilterNotCreatedException e) {
1218
System.err.println("Failed to create filter: " + e.getMessage());
1219
}
1220
}
1221
}
1222
```
1223
1224
## Types
1225
1226
```java { .api }
1227
/**
1228
* Failure information
1229
*/
1230
public class Failure implements Serializable {
1231
public Failure(Description description, Throwable thrownException);
1232
1233
public Description getDescription();
1234
public Throwable getException();
1235
public String getMessage();
1236
public String getTestHeader();
1237
public String getTrace();
1238
public String getTrimmedTrace();
1239
}
1240
1241
/**
1242
* Thrown when a filter removes all tests from a runner
1243
*/
1244
public class NoTestsRemainException extends Exception {
1245
}
1246
1247
/**
1248
* Thrown when an ordering does something invalid (like remove or add children)
1249
* @since 4.13
1250
*/
1251
public class InvalidOrderingException extends Exception {
1252
public InvalidOrderingException();
1253
public InvalidOrderingException(String message);
1254
public InvalidOrderingException(String message, Throwable cause);
1255
}
1256
1257
/**
1258
* Represents an object that can describe itself
1259
*/
1260
public interface Describable {
1261
Description getDescription();
1262
}
1263
1264
/**
1265
* Strategy for computing runners and suites
1266
*/
1267
public class Computer {
1268
/**
1269
* Create a serial computer (runs tests sequentially)
1270
* @return Computer that runs tests one at a time
1271
*/
1272
public static Computer serial();
1273
1274
/**
1275
* Get runner for a test suite
1276
* @param parent - Parent runner
1277
* @param classes - Test classes
1278
* @return Runner for the suite
1279
*/
1280
public Runner getSuite(RunnerBuilder parent, Class<?>[] classes) throws InitializationError;
1281
1282
/**
1283
* Get runner for a single test class
1284
* @param testClass - Test class
1285
* @return Runner for the class
1286
*/
1287
protected Runner getRunner(RunnerBuilder builder, Class<?> testClass) throws Throwable;
1288
}
1289
1290
/**
1291
* Computer for running tests in parallel. Extends Computer to provide concurrent execution.
1292
* Part of org.junit.experimental package.
1293
*/
1294
public class ParallelComputer extends Computer {
1295
/**
1296
* Constructor for ParallelComputer
1297
* @param classes - true to parallelize classes, false otherwise
1298
* @param methods - true to parallelize methods, false otherwise
1299
*/
1300
public ParallelComputer(boolean classes, boolean methods);
1301
1302
/**
1303
* Create a computer that runs test classes in parallel
1304
* @return Computer that parallelizes classes
1305
*/
1306
public static Computer classes();
1307
1308
/**
1309
* Create a computer that runs test methods in parallel
1310
* @return Computer that parallelizes methods
1311
*/
1312
public static Computer methods();
1313
}
1314
1315
/**
1316
* Reorders tests. An Ordering can reverse the order of tests, sort the order or shuffle the order.
1317
* Generally used through Request.orderWith() rather than directly.
1318
* @since 4.13
1319
*/
1320
public abstract class Ordering {
1321
/**
1322
* Creates an Ordering that shuffles items using the given Random instance
1323
* @param random - Random instance for shuffling
1324
* @return Ordering that shuffles
1325
*/
1326
public static Ordering shuffledBy(Random random);
1327
1328
/**
1329
* Creates an Ordering from the given factory class
1330
* @param factoryClass - Factory class to create the ordering
1331
* @param annotatedTestClass - Test class annotated with @OrderWith
1332
* @return Created ordering
1333
* @throws InvalidOrderingException if the instance could not be created
1334
*/
1335
public static Ordering definedBy(
1336
Class<? extends Ordering.Factory> factoryClass,
1337
Description annotatedTestClass) throws InvalidOrderingException;
1338
1339
/**
1340
* Creates an Ordering from the given factory
1341
* @param factory - Factory to use
1342
* @param annotatedTestClass - Test class annotated with @OrderWith
1343
* @return Created ordering
1344
* @throws InvalidOrderingException if the instance could not be created
1345
*/
1346
public static Ordering definedBy(
1347
Ordering.Factory factory,
1348
Description annotatedTestClass) throws InvalidOrderingException;
1349
1350
/**
1351
* Order the tests in target using this ordering
1352
* @param target - Target to order (typically Orderable)
1353
* @throws InvalidOrderingException if ordering does something invalid
1354
*/
1355
public void apply(Object target) throws InvalidOrderingException;
1356
1357
/**
1358
* Implemented by sub-classes to order the descriptions
1359
* @param descriptions - Descriptions to order
1360
* @return descriptions in order
1361
*/
1362
protected abstract List<Description> orderItems(Collection<Description> descriptions);
1363
1364
/** Context about the ordering being applied */
1365
public static class Context {
1366
/**
1367
* Gets the description for the top-level target being ordered
1368
* @return Description of target
1369
*/
1370
public Description getTarget();
1371
}
1372
1373
/**
1374
* Factory for creating Ordering instances
1375
* For use with @OrderWith, needs public no-arg constructor
1376
*/
1377
public interface Factory {
1378
/**
1379
* Creates an Ordering instance using the given context
1380
* @param context - Context for creating ordering
1381
* @return Created ordering
1382
*/
1383
Ordering create(Context context);
1384
}
1385
}
1386
1387
/**
1388
* Orders tests. Used internally by Ordering to apply ordering logic.
1389
* @since 4.13
1390
*/
1391
public final class Orderer {
1392
/**
1393
* Orders the descriptions
1394
* @param descriptions - Descriptions to order
1395
* @return descriptions in order
1396
* @throws InvalidOrderingException if ordering is invalid
1397
*/
1398
public List<Description> order(Collection<Description> descriptions)
1399
throws InvalidOrderingException;
1400
1401
/**
1402
* Order the tests in target
1403
* @param target - Target to order
1404
* @throws InvalidOrderingException if ordering is invalid
1405
*/
1406
public void apply(Object target) throws InvalidOrderingException;
1407
}
1408
1409
/**
1410
* Parameters passed to FilterFactory for creating filters.
1411
* Contains the top-level test description and string arguments from filter specification.
1412
*/
1413
public final class FilterFactoryParams {
1414
/**
1415
* Creates filter factory parameters
1416
* @param topLevelDescription - Description of all tests being filtered
1417
* @param args - String arguments for the filter factory
1418
* @throws NullPointerException if either parameter is null
1419
*/
1420
public FilterFactoryParams(Description topLevelDescription, String args);
1421
1422
/**
1423
* Get the string arguments passed to the filter factory
1424
* @return Arguments string (may be empty, never null)
1425
*/
1426
public String getArgs();
1427
1428
/**
1429
* Get the description of all tests being filtered
1430
* @return Top-level description
1431
*/
1432
public Description getTopLevelDescription();
1433
}
1434
```
1435