View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections4;
18  
19  import junit.framework.TestCase;
20  import junit.framework.TestSuite;
21  
22  /**
23   * A {@link TestCase} that can define both simple and bulk test methods.
24   * <p>
25   * A <I>simple test method</I> is the type of test traditionally
26   * supplied by {@link TestCase}.  To define a simple test, create a public
27   * no-argument method whose name starts with "test".  You can specify
28   * the name of simple test in the constructor of {@code BulkTest};
29   * a subsequent call to {@link TestCase#run} will run that simple test.
30   * <p>
31   * A <I>bulk test method</I>, on the other hand, returns a new instance
32   * of {@code BulkTest}, which can itself define new simple and bulk
33   * test methods.  By using the {@link #makeSuite} method, you can
34   * automatically create a hierarchical suite of tests and child bulk tests.
35   * <p>
36   * For instance, consider the following two classes:
37   *
38   * <Pre>
39   *  public class SetTest extends BulkTest {
40   *
41   *      private Set set;
42   *
43   *      public SetTest(Set set) {
44   *          this.set = set;
45   *      }
46   *
47   *      @Test
48   *      public void testContains() {
49   *          boolean r = set.contains(set.iterator().next()));
50   *          assertTrue("Set should contain first element, r);
51   *      }
52   *
53   *      @Test
54   *      public void testClear() {
55   *          set.clear();
56   *          assertTrue("Set should be empty after clear", set.isEmpty());
57   *      }
58   *  }
59   *
60   *
61   *  public class HashMapTest extends BulkTest {
62   *
63   *      private Map makeFullMap() {
64   *          HashMap result = new HashMap();
65   *          result.put("1", "One");
66   *          result.put("2", "Two");
67   *          return result;
68   *      }
69   *
70   *      @Test
71   *      public void testClear() {
72   *          Map map = makeFullMap();
73   *          map.clear();
74   *          assertTrue("Map empty after clear", map.isEmpty());
75   *      }
76   *
77   *      public BulkTest bulkTestKeySet() {
78   *          return new SetTest(makeFullMap().keySet());
79   *      }
80   *
81   *      public BulkTest bulkTestEntrySet() {
82   *          return new SetTest(makeFullMap().entrySet());
83   *      }
84   *  }
85   *  </Pre>
86   *
87   *  In the above examples, {@code SetTest} defines two
88   *  simple test methods and no bulk test methods; {@code HashMapTest}
89   *  defines one simple test method and two bulk test methods.  When
90   *  {@code makeSuite(HashMapTest.class).run} is executed,
91   *  <I>five</I> simple test methods will be run, in this order:<P>
92   *
93   *  <Ol>
94   *  <Li>HashMapTest.testClear()
95   *  <Li>HashMapTest.bulkTestKeySet().testContains();
96   *  <Li>HashMapTest.bulkTestKeySet().testClear();
97   *  <Li>HashMapTest.bulkTestEntrySet().testContains();
98   *  <Li>HashMapTest.bulkTestEntrySet().testClear();
99   *  </Ol>
100  *
101  *  In the graphical junit test runners, the tests would be displayed in
102  *  the following tree:<P>
103  *
104  *  <UL>
105  *  <LI>HashMapTest</LI>
106  *      <UL>
107  *      <LI>testClear
108  *      <LI>bulkTestKeySet
109  *          <UL>
110  *          <LI>testContains
111  *          <LI>testClear
112  *          </UL>
113  *      <LI>bulkTestEntrySet
114  *          <UL>
115  *          <LI>testContains
116  *          <LI>testClear
117  *          </UL>
118  *      </UL>
119  *  </UL>
120  *
121  *  A subclass can override a superclass's bulk test by
122  *  returning {@code null} from the bulk test method.  If you only
123  *  want to override specific simple tests within a bulk test, use the
124  *  {@link #ignoredTests} method.<P>
125  *
126  *  Note that if you want to use the bulk test methods, you <I>must</I>
127  *  define your {@code suite()} method to use {@link #makeSuite}.
128  *  The ordinary {@link TestSuite} constructor doesn't know how to
129  *  interpret bulk test methods.
130  */
131 public class BulkTest implements Cloneable {
132 
133     // Note:  BulkTest is Cloneable to make it easier to construct
134     // BulkTest instances for simple test methods that are defined in
135     // anonymous inner classes.  Basically we don't have to worry about
136     // finding weird constructors.  (And even if we found them, technically
137     // it'd be illegal for anyone but the outer class to invoke them).
138     // Given one BulkTest instance, we can just clone it and reset the
139     // method name for every simple test it defines.
140 
141     /** Path to test data resources */
142     protected static final String TEST_DATA_PATH = "src/test/resources/org/apache/commons/collections4/data/test/";
143 
144     /** Path to test properties resources */
145     public static final String TEST_PROPERTIES_PATH = "src/test/resources/org/apache/commons/collections4/properties/";
146 
147     /**
148      *  The full name of this bulk test instance.  This is the full name
149      *  that is compared to {@link #ignoredTests} to see if this
150      *  test should be ignored.  It's also displayed in the text runner
151      *  to ease debugging.
152      */
153     String verboseName;
154 
155     /**
156      *  the name of the simple test method
157      */
158     private final String name;
159 
160     /**
161      *  Constructs a new {@code BulkTest} instance that will run the
162      *  specified simple test.
163      *
164      *  @param name  the name of the simple test method to run
165      */
166     public BulkTest(final String name) {
167         this.name = name;
168         this.verboseName = getClass().getName();
169     }
170 
171     /**
172      *  Creates a clone of this {@code BulkTest}.<P>
173      *
174      *  @return  a clone of this {@code BulkTest}
175      */
176     @Override
177     public Object clone() {
178         try {
179             return super.clone();
180         } catch (final CloneNotSupportedException e) {
181             throw new Error(); // should never happen
182         }
183     }
184 
185     /**
186      *  Returns the name of the simple test method of this {@code BulkTest}.
187      *
188      *  @return the name of the simple test method of this {@code BulkTest}
189      */
190     public String getName() {
191         return name;
192     }
193 
194     /**
195      *  Returns an array of test names to ignore.<P>
196      *
197      *  If a test that's defined by this {@code BulkTest} or
198      *  by one of its bulk test methods has a name that's in the returned
199      *  array, then that simple test will not be executed.<P>
200      *
201      *  A test's name is formed by taking the class name of the
202      *  root {@code BulkTest}, eliminating the package name, then
203      *  appending the names of any bulk test methods that were invoked
204      *  to get to the simple test, and then appending the simple test
205      *  method name.  The method names are delimited by periods:
206      *
207      *  <pre>
208      *  HashMapTest.bulkTestEntrySet.testClear
209      *  </pre>
210      *
211      *  is the name of one of the simple tests defined in the sample classes
212      *  described above.  If the sample {@code HashMapTest} class
213      *  included this method:
214      *
215      *  <pre>
216      *  public String[] ignoredTests() {
217      *      return new String[] { "HashMapTest.bulkTestEntrySet.testClear" };
218      *  }
219      *  </pre>
220      *
221      *  then the entry set's clear method wouldn't be tested, but the key
222      *  set's clear method would.
223      *
224      *  @return an array of the names of tests to ignore, or null if
225      *   no tests should be ignored
226      */
227     public String[] ignoredTests() {
228         return null;
229     }
230 
231     /**
232      *  Returns the display name of this {@code BulkTest}.
233      *
234      *  @return the display name of this {@code BulkTest}
235      */
236     @Override
237     public String toString() {
238         return getName() + "(" + verboseName + ") ";
239     }
240 
241 }