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 }