|
1 package org.junit.runners; |
|
2 |
|
3 import java.lang.annotation.ElementType; |
|
4 import java.lang.annotation.Retention; |
|
5 import java.lang.annotation.RetentionPolicy; |
|
6 import java.lang.annotation.Target; |
|
7 import java.util.List; |
|
8 |
|
9 import org.junit.internal.builders.AllDefaultPossibilitiesBuilder; |
|
10 import org.junit.runner.Description; |
|
11 import org.junit.runner.Runner; |
|
12 import org.junit.runner.notification.RunNotifier; |
|
13 import org.junit.runners.model.InitializationError; |
|
14 import org.junit.runners.model.RunnerBuilder; |
|
15 |
|
16 /** |
|
17 * Using <code>Suite</code> as a runner allows you to manually |
|
18 * build a suite containing tests from many classes. It is the JUnit 4 equivalent of the JUnit 3.8.x |
|
19 * static {@link junit.framework.Test} <code>suite()</code> method. To use it, annotate a class |
|
20 * with <code>@RunWith(Suite.class)</code> and <code>@SuiteClasses(TestClass1.class, ...)</code>. |
|
21 * When you run this class, it will run all the tests in all the suite classes. |
|
22 */ |
|
23 public class Suite extends ParentRunner<Runner> { |
|
24 /** |
|
25 * The <code>SuiteClasses</code> annotation specifies the classes to be run when a class |
|
26 * annotated with <code>@RunWith(Suite.class)</code> is run. |
|
27 */ |
|
28 @Retention(RetentionPolicy.RUNTIME) |
|
29 @Target(ElementType.TYPE) |
|
30 public @interface SuiteClasses { |
|
31 /** |
|
32 * @return the classes to be run |
|
33 */ |
|
34 public Class<?>[] value(); |
|
35 } |
|
36 |
|
37 private static Class<?>[] getAnnotatedClasses(Class<?> klass) throws InitializationError { |
|
38 SuiteClasses annotation= klass.getAnnotation(SuiteClasses.class); |
|
39 if (annotation == null) |
|
40 throw new InitializationError(String.format("class '%s' must have a SuiteClasses annotation", klass.getName())); |
|
41 return annotation.value(); |
|
42 } |
|
43 |
|
44 private final List<Runner> fRunners; |
|
45 |
|
46 /** |
|
47 * Called reflectively on classes annotated with <code>@RunWith(Suite.class)</code> |
|
48 * |
|
49 * @param klass the root class |
|
50 * @param builder builds runners for classes in the suite |
|
51 * @throws InitializationError |
|
52 */ |
|
53 public Suite(Class<?> klass, RunnerBuilder builder) throws InitializationError { |
|
54 this(builder, klass, getAnnotatedClasses(klass)); |
|
55 } |
|
56 |
|
57 /** |
|
58 * Call this when there is no single root class (for example, multiple class names |
|
59 * passed on the command line to {@link org.junit.runner.JUnitCore} |
|
60 * |
|
61 * @param builder builds runners for classes in the suite |
|
62 * @param classes the classes in the suite |
|
63 * @throws InitializationError |
|
64 */ |
|
65 public Suite(RunnerBuilder builder, Class<?>[] classes) throws InitializationError { |
|
66 this(null, builder.runners(null, classes)); |
|
67 } |
|
68 |
|
69 /** |
|
70 * Call this when the default builder is good enough. Left in for compatibility with JUnit 4.4. |
|
71 * @param klass the root of the suite |
|
72 * @param suiteClasses the classes in the suite |
|
73 * @throws InitializationError |
|
74 */ |
|
75 protected Suite(Class<?> klass, Class<?>[] suiteClasses) throws InitializationError { |
|
76 this(new AllDefaultPossibilitiesBuilder(true), klass, suiteClasses); |
|
77 } |
|
78 |
|
79 /** |
|
80 * Called by this class and subclasses once the classes making up the suite have been determined |
|
81 * |
|
82 * @param builder builds runners for classes in the suite |
|
83 * @param klass the root of the suite |
|
84 * @param suiteClasses the classes in the suite |
|
85 * @throws InitializationError |
|
86 */ |
|
87 protected Suite(RunnerBuilder builder, Class<?> klass, Class<?>[] suiteClasses) throws InitializationError { |
|
88 this(klass, builder.runners(klass, suiteClasses)); |
|
89 } |
|
90 |
|
91 /** |
|
92 * Called by this class and subclasses once the runners making up the suite have been determined |
|
93 * |
|
94 * @param klass root of the suite |
|
95 * @param runners for each class in the suite, a {@link Runner} |
|
96 * @throws InitializationError |
|
97 */ |
|
98 protected Suite(Class<?> klass, List<Runner> runners) throws InitializationError { |
|
99 super(klass); |
|
100 fRunners = runners; |
|
101 } |
|
102 |
|
103 @Override |
|
104 protected List<Runner> getChildren() { |
|
105 return fRunners; |
|
106 } |
|
107 |
|
108 @Override |
|
109 protected Description describeChild(Runner child) { |
|
110 return child.getDescription(); |
|
111 } |
|
112 |
|
113 @Override |
|
114 protected void runChild(Runner runner, final RunNotifier notifier) { |
|
115 runner.run(notifier); |
|
116 } |
|
117 } |