View Javadoc

1   /*
2    * Copyright 2010-2013 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.testdoc.core.doc;
17  
18  import java.io.Serializable;
19  import java.util.ArrayList;
20  import java.util.Collections;
21  import java.util.List;
22  
23  import org.apache.commons.lang.NullArgumentException;
24  import org.apache.commons.lang.ObjectUtils;
25  import org.apache.commons.lang.StringUtils;
26  
27  /**
28   * The test documentation of a single scenario of a unit-under-test.
29   *
30   * @todo check deserialized form for not being tampered with.
31   * @author <a href="mailto:robert.reiner@smartics.de">Robert Reiner</a>
32   * @version $Revision:591 $
33   */
34  public final class ScenarioTestDoc implements Serializable,
35      Comparable<ScenarioTestDoc>
36  {
37    // ******************************** Fields ********************************
38  
39    // --- constants ----------------------------------------------------------
40  
41    /**
42     * The class version identifier.
43     * <p>
44     * The value of this constant is {@value}.
45     * </p>
46     */
47    private static final long serialVersionUID = 1L;
48  
49    // --- members ------------------------------------------------------------
50  
51    /**
52     * The name of the method under test.
53     *
54     * @serial
55     */
56    private final String uutMethod;
57  
58    /**
59     * The sort key defining the natural order of scenarios.
60     *
61     * @serial
62     */
63    private final SortKey sortKey;
64  
65    /**
66     * The type of the test case the test has been specified in.
67     *
68     * @serial
69     */
70    private final Type testCaseType;
71  
72    /**
73     * The test method of a scenario.
74     *
75     * @serial
76     */
77    private final TestMethodDoc testMethod;
78  
79    /**
80     * The categories of the scenario.
81     *
82     * @serial
83     */
84    private final List<String> categories;
85  
86    // ***************************** Initializer ******************************
87  
88    // ***************************** Constructors *****************************
89  
90    /**
91     * Convenience constructor specifying the test case type as a {@link String} .
92     *
93     * @param testCaseType the type of the test case the test has been specified
94     *          in.
95     * @param testMethod the test method of a scenario.
96     * @throws IllegalArgumentException if <code>testCaseType</code> is
97     *           <code>null</code> or <code>testName</code> or
98     *           <code>testSentence</code> is blank.
99     */
100   public ScenarioTestDoc(final String testCaseType,
101       final TestMethodDoc testMethod) throws IllegalArgumentException
102   {
103     this(null, new Type(testCaseType), testMethod, null,
104         new SortKey(null, null));
105   }
106 
107   /**
108    * Convenience constructor specifying the test case type as a {@link String} .
109    *
110    * @param uutMethod the name of the method under test.
111    * @param testCaseType the type of the test case the test has been specified
112    *          in.
113    * @param testMethod the test method of a scenario.
114    * @throws IllegalArgumentException if <code>testCaseType</code> is
115    *           <code>null</code> or <code>testName</code> or
116    *           <code>testSentence</code> is blank.
117    */
118   public ScenarioTestDoc(final String uutMethod, final String testCaseType,
119       final TestMethodDoc testMethod) throws IllegalArgumentException
120   {
121     this(uutMethod, new Type(testCaseType), testMethod, null, new SortKey(null,
122         null));
123   }
124 
125   /**
126    * Convenience constructor specifying the test case type as a {@link String} .
127    *
128    * @param uutMethod the name of the method under test.
129    * @param testCaseType the type of the test case the test has been specified
130    *          in.
131    * @param testMethod the test method of a scenario.
132    * @param categories the categories of the scenario.
133    * @throws IllegalArgumentException if <code>testCaseType</code> is
134    *           <code>null</code> or <code>testName</code> or
135    *           <code>testSentence</code> is blank.
136    */
137   public ScenarioTestDoc(final String uutMethod, final String testCaseType,
138       final TestMethodDoc testMethod, final List<String> categories)
139     throws IllegalArgumentException
140   {
141     this(uutMethod, new Type(testCaseType), testMethod, categories,
142         new SortKey(null, null));
143   }
144 
145   /**
146    * Convenience constructor.
147    *
148    * @param uutMethod the name of the method under test.
149    * @param testCaseType the type of the test case the test has been specified
150    *          in.
151    * @param testMethod the test method of a scenario.
152    * @throws IllegalArgumentException if <code>testCaseType</code> or
153    *           <code>testMethod</code> is <code>null</code>.
154    */
155   public ScenarioTestDoc(final String uutMethod, final Type testCaseType,
156       final TestMethodDoc testMethod) throws IllegalArgumentException
157   {
158     this(uutMethod, testCaseType, testMethod, null, new SortKey(null, null));
159   }
160 
161   /**
162    * Convenience constructor.
163    *
164    * @param testCaseType the type of the test case the test has been specified
165    *          in.
166    * @param testMethod the test method of a scenario.
167    * @param categories the categories of the scenario. May be <code>null</code>.
168    * @throws IllegalArgumentException if <code>testCaseType</code> or
169    *           <code>testMethod</code> is <code>null</code>.
170    */
171   public ScenarioTestDoc(final Type testCaseType,
172       final TestMethodDoc testMethod, final List<String> categories)
173     throws IllegalArgumentException
174   {
175     this(null, testCaseType, testMethod, categories, new SortKey(null, null));
176   }
177 
178   /**
179    * Default constructor.
180    *
181    * @param uutMethod the name of the method under test.
182    * @param testCaseType the type of the test case the test has been specified
183    *          in.
184    * @param testMethod the test method of a scenario.
185    * @param categories the categories of the scenario. May be <code>null</code>.
186    * @param sortKey the sort key defining the natural order of scenarios.
187    * @throws IllegalArgumentException if <code>testCaseType</code>,
188    *           <code>testMethod</code>, or <code>sortKey</code> is
189    *           <code>null</code>.
190    */
191   public ScenarioTestDoc(final String uutMethod, final Type testCaseType,
192       final TestMethodDoc testMethod, final List<String> categories,
193       final SortKey sortKey) throws IllegalArgumentException
194   {
195     checkArguments(uutMethod, testCaseType, testMethod, sortKey);
196 
197     this.uutMethod = uutMethod;
198     this.testCaseType = testCaseType;
199     this.testMethod = testMethod;
200     this.categories =
201         (categories != null ? new ArrayList<String>(categories)
202             : new ArrayList<String>());
203     this.sortKey = sortKey;
204   }
205 
206   // ***************************** Inner Classes ****************************
207 
208   // ******************************** Methods *******************************
209 
210   // --- init ---------------------------------------------------------------
211 
212   private static void checkArguments(final String uutMethod,
213       final Type testCaseType, final TestMethodDoc testMethod,
214       final SortKey sortKey)
215   {
216     if (uutMethod != null && StringUtils.isBlank(uutMethod))
217     {
218       throw new IllegalArgumentException(
219           "The method name may be 'null', but must not be the empty string or contain only whitespaces.");
220     }
221     if (null == testCaseType)
222     {
223       throw new NullArgumentException("testCaseType");
224     }
225     if (testMethod == null)
226     {
227       throw new NullArgumentException("testMethod");
228     }
229     if (sortKey == null)
230     {
231       throw new NullArgumentException("sortKey");
232     }
233   }
234 
235   // --- get&set ------------------------------------------------------------
236 
237   /**
238    * Returns the name of the method under test.
239    *
240    * @return the name of the method under test.
241    */
242   public String getUutMethod()
243   {
244     return uutMethod;
245   }
246 
247   /**
248    * Returns a unique identifier for a test method.
249    *
250    * @return the unique identifier for the test method.
251    * @warning Please note that the identifier is <strong>not unique if the
252    *          method is overloaded</strong>. Since test methods never have
253    *          parameters and the parameters of theories should not be
254    *          significant, this usually is no problem.
255    * @impl The value is calculated each time it is requested.
256    */
257   public String getId()
258   {
259     return testCaseType.toString() + '#' + testMethod.getTestName();
260   }
261 
262   /**
263    * Returns the type of the test case the test has been specified in.
264    *
265    * @return the type of the test case the test has been specified in. The
266    *         returned value is never <code>null</code>.
267    */
268   public Type getTestCaseType()
269   {
270     return testCaseType;
271   }
272 
273   /**
274    * Returns the test method of a scenario.
275    *
276    * @return the test method of a scenario.
277    */
278   public TestMethodDoc getTestMethod()
279   {
280     return testMethod;
281   }
282 
283   /**
284    * Returns the categories of the scenario.
285    *
286    * @return the categories of the scenario.
287    */
288   public List<String> getCategories()
289   {
290     return Collections.unmodifiableList(categories);
291   }
292 
293   /**
294    * Returns the sort key defining the natural order of scenarios.
295    *
296    * @return the sort key defining the natural order of scenarios.
297    */
298   public SortKey getSortKey()
299   {
300     return sortKey;
301   }
302 
303   // --- business -----------------------------------------------------------
304 
305   // --- object basics ------------------------------------------------------
306 
307   /**
308    * Returns the hash code of the object.
309    *
310    * @return the hash code.
311    */
312   @Override
313   public int hashCode()
314   {
315     int result = 17;
316     result = 37 * result + testCaseType.hashCode();
317     result = 37 * result + testMethod.hashCode();
318 
319     return result;
320   }
321 
322   /**
323    * Returns <code>true</code> if the given object is semantically equal to the
324    * given object, <code>false</code> otherwise.
325    *
326    * @param object the instance to compare to.
327    * @return <code>true</code> if the given object is semantically equal to the
328    *         given object, <code>false</code> otherwise.
329    */
330   @Override
331   public boolean equals(final Object object)
332   {
333     if (this == object)
334     {
335       return true;
336     }
337     else if (object == null || getClass() != object.getClass())
338     {
339       return false;
340     }
341 
342     final ScenarioTestDoc other = (ScenarioTestDoc) object;
343 
344     return (ObjectUtils.equals(uutMethod, other.uutMethod)
345             && this.testCaseType.equals(other.testCaseType)
346             && this.testMethod.equals(other.testMethod) && categories
347         .equals(other.categories));
348   }
349 
350   /**
351    * {@inheritDoc}
352    * <p>
353    * The natural order is defined by the {@link SortKey} property.
354    * </p>
355    *
356    * @see java.lang.Comparable#compareTo(java.lang.Object)
357    */
358   @Override
359   public int compareTo(final ScenarioTestDoc other)
360   {
361     return sortKey.compareTo(other.sortKey);
362   }
363 
364   /**
365    * Returns the string representation of the object.
366    *
367    * @return the string representation of the object.
368    */
369   @Override
370   public String toString()
371   {
372     final StringBuilder buffer = new StringBuilder();
373 
374     if (uutMethod != null)
375     {
376       buffer.append("UUT method : ").append(uutMethod).append('\n');
377     }
378     buffer.append("Test case : ").append(testCaseType).append(", ");
379     buffer.append('\n').append(testMethod);
380     if (!categories.isEmpty())
381     {
382       buffer.append("\nCategories:");
383       for (final String category : categories)
384       {
385         buffer.append(' ').append(category);
386       }
387     }
388     buffer.append("\nSort Key: ").append(sortKey);
389     return buffer.toString();
390   }
391 }