Merge lp:~yshavit/namedparameterizedrunner/init_dump into lp:namedparameterizedrunner

Proposed by Yuval Shavit
Status: Merged
Merged at revision: 2
Proposed branch: lp:~yshavit/namedparameterizedrunner/init_dump
Merge into: lp:namedparameterizedrunner
Diff against target: 1616 lines (+1551/-0)
11 files modified
.bzrignore (+4/-0)
pom.xml (+67/-0)
src/main/java/com/motpot/npr/Failing.java (+22/-0)
src/main/java/com/motpot/npr/NamedParameterizedRunner.java (+570/-0)
src/main/java/com/motpot/npr/OnlyIf.java (+20/-0)
src/main/java/com/motpot/npr/OnlyIfNot.java (+20/-0)
src/main/java/com/motpot/npr/Parameterization.java (+152/-0)
src/main/java/com/motpot/npr/ParameterizationBuilder.java (+159/-0)
src/test/java/com/motpot/npr/NamedParameterizedRunnerTest.java (+316/-0)
src/test/java/com/motpot/npr/OnlyIfUsageTest.java (+68/-0)
src/test/java/com/motpot/npr/ParameterizationBuilderTest.java (+153/-0)
To merge this branch: bzr merge lp:~yshavit/namedparameterizedrunner/init_dump
Reviewer Review Type Date Requested Status
Yuval Shavit Pending
Review via email: mp+74631@code.launchpad.net

Description of the change

Initial commit, copied from lp:akiban-server/trunk

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file '.bzrignore'
--- .bzrignore 1970-01-01 00:00:00 +0000
+++ .bzrignore 2011-09-08 16:01:22 +0000
@@ -0,0 +1,4 @@
1named-parameterized-runner.iml
2named-parameterized-runner.ipr
3named-parameterized-runner.iws
4./target
05
=== added file 'pom.xml'
--- pom.xml 1970-01-01 00:00:00 +0000
+++ pom.xml 2011-09-08 16:01:22 +0000
@@ -0,0 +1,67 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<project>
3 <modelVersion>4.0.0</modelVersion>
4 <groupId>com.motpot</groupId>
5 <artifactId>named-parameterized-runner</artifactId>
6 <packaging>jar</packaging>
7 <version>0.8.0</version>
8 <name>named-parameterized-runner</name>
9 <dependencies>
10 <dependency>
11 <groupId>junit</groupId>
12 <artifactId>junit</artifactId>
13 <version>4.8.1</version>
14 </dependency>
15 <dependency>
16 <groupId>org.slf4j</groupId>
17 <artifactId>slf4j-api</artifactId>
18 <version>1.6.1</version>
19 </dependency>
20 </dependencies>
21 <build>
22 <plugins>
23 <plugin>
24 <groupId>org.apache.maven.plugins</groupId>
25 <artifactId>maven-jar-plugin</artifactId>
26 <version>2.2</version>
27 <executions>
28 <execution>
29 <goals>
30 <goal>test-jar</goal>
31 </goals>
32 </execution>
33 </executions>
34 </plugin>
35 <plugin>
36 <groupId>org.apache.maven.plugins</groupId>
37 <artifactId>maven-compiler-plugin</artifactId>
38 <version>2.3.2</version>
39 <configuration>
40 <source>1.6</source>
41 <target>1.6</target>
42 </configuration>
43 </plugin>
44 <plugin>
45 <groupId>org.apache.maven.plugins</groupId>
46 <artifactId>maven-source-plugin</artifactId>
47 <version>2.1.2</version>
48 <executions>
49 <execution>
50 <id>attach-sources</id>
51 <phase>package</phase>
52 <goals>
53 <goal>jar</goal>
54 </goals>
55 </execution>
56 </executions>
57 </plugin>
58 <plugin>
59 <groupId>org.apache.maven.plugins</groupId>
60 <artifactId>maven-surefire-plugin</artifactId>
61 <version>2.6</version>
62 </plugin>
63 </plugins>
64</build>
65
66</project>
67
068
=== added directory 'src'
=== added directory 'src/main'
=== added directory 'src/main/java'
=== added directory 'src/main/java/com'
=== added directory 'src/main/java/com/motpot'
=== added directory 'src/main/java/com/motpot/npr'
=== added file 'src/main/java/com/motpot/npr/Failing.java'
--- src/main/java/com/motpot/npr/Failing.java 1970-01-01 00:00:00 +0000
+++ src/main/java/com/motpot/npr/Failing.java 2011-09-08 16:01:22 +0000
@@ -0,0 +1,22 @@
1package com.motpot.npr;
2
3import java.lang.annotation.ElementType;
4import java.lang.annotation.Retention;
5import java.lang.annotation.RetentionPolicy;
6import java.lang.annotation.Target;
7
8/**
9 * Represents a failing test.
10 */
11@Retention(RetentionPolicy.RUNTIME)
12@Target(ElementType.METHOD)
13public @interface Failing
14{
15 /**
16 * For parameterized tests, the optional list of parameterizations that are failing.
17 *
18 * This is ignored by non-parameterized class runners. For parameterized runners,
19 * not specifying this value means that all parameterizations are failing.
20 */
21 String[] value() default {};
22}
023
=== added file 'src/main/java/com/motpot/npr/NamedParameterizedRunner.java'
--- src/main/java/com/motpot/npr/NamedParameterizedRunner.java 1970-01-01 00:00:00 +0000
+++ src/main/java/com/motpot/npr/NamedParameterizedRunner.java 2011-09-08 16:01:22 +0000
@@ -0,0 +1,570 @@
1package com.motpot.npr;
2
3import org.slf4j.Logger;
4import org.slf4j.LoggerFactory;
5import org.junit.Ignore;
6import org.junit.internal.builders.IgnoredClassRunner;
7import org.junit.runner.Runner;
8import org.junit.runner.notification.RunNotifier;
9import org.junit.runners.BlockJUnit4ClassRunner;
10import org.junit.runners.Suite;
11import org.junit.runners.model.FrameworkMethod;
12import org.junit.runners.model.InitializationError;
13import org.junit.runners.model.Statement;
14import org.junit.runners.model.TestClass;
15
16import java.lang.annotation.ElementType;
17import java.lang.annotation.Retention;
18import java.lang.annotation.RetentionPolicy;
19import java.lang.annotation.Target;
20import java.lang.reflect.Field;
21import java.lang.reflect.Method;
22import java.lang.reflect.Modifier;
23import java.lang.reflect.ParameterizedType;
24import java.lang.reflect.Type;
25import java.util.*;
26import java.util.regex.Pattern;
27
28public final class NamedParameterizedRunner extends Suite
29{
30 /**
31 * <p>Parameterization override filter (works by name).</p>
32 *
33 * <p>If this property is set, then only parameterization names that match its value will be processed. These
34 * names behave like @Failing names (in terms of regexes, etc). If this property is set and a test that matches
35 * it is marked as @Failing, that test will still get run. For instance, if a parameterization named
36 * <tt>myFooTest</tt> is marked as failing for a given test (either because the entire parameterization is marked
37 * as failing, or because of a <tt>@Failing</tt> annotation on the method), and if you have a system property
38 * <tt>{@value} == "/myFoo/"</tt>, then the test <em>will</em> be run.
39 */
40 public final static String PARAMETERIZATION_OVERRIDE = "test.params";
41 /**
42 * <p>Annotation for a method which provides parameters for an
43 * {@link NamedParameterizedRunner} suite.</p>
44 *
45 * <p>A class that is run with {@linkplain NamedParameterizedRunner} <em>must</em> have exactly one method
46 * marked with this annotation, and that method must:</p>
47 * <ul>
48 * <li>be public</li>
49 * <li>be static</li>
50 * <li>take no arguments</li>
51 * <li>return Collection of {@link Parameterization} objects.</li>
52 * </ul>
53 */
54 @Retention(RetentionPolicy.RUNTIME)
55 @Target(ElementType.METHOD)
56 public static @interface TestParameters {
57 }
58
59 private final static Logger logger = LoggerFactory.getLogger(NamedParameterizedRunner.class);
60 private final List<Runner> runners;
61
62 /**
63 * Adapted from {@link org.junit.runners.Parameterized}'s nested class
64 * @see
65 */
66 static class ReifiedParamRunner extends BlockJUnit4ClassRunner
67 {
68 private final Parameterization parameterization;
69 private final boolean overrideOn;
70 private Object testObject = null;
71
72 private static class OnlyIfErrorFrameworkMethod extends FrameworkMethod {
73 private final OnlyIfException exception;
74
75 private OnlyIfErrorFrameworkMethod(Method method, OnlyIfException exception) {
76 super(method);
77 this.exception = exception;
78 }
79
80 @Override
81 public Object invokeExplosively(Object target, Object... params) throws Throwable {
82 throw exception;
83 }
84 }
85
86 public ReifiedParamRunner(Class<?> klass, Parameterization parameterization, boolean overrideOn)
87 throws InitializationError
88 {
89 super(klass);
90 this.parameterization = parameterization;
91 this.overrideOn = overrideOn;
92 }
93
94 /**
95 * For debugging.
96 * @return parameterization.toString()
97 * @throws NullPointerException if parameterization is null
98 */
99 String paramToString()
100 {
101 return parameterization.toString();
102 }
103
104 /**
105 * For debugging
106 * @return the override value
107 */
108 boolean overrideOn()
109 {
110 return overrideOn;
111 }
112
113 /**
114 * For debugging.
115 * @param name the name of the child FrameworkMethod to get
116 * @return the child, or null if it doesn't exist
117 */
118 FrameworkMethod getChild(String name)
119 {
120 for (FrameworkMethod method : getChildren())
121 {
122 if (method.getMethod().toString().equals(name))
123 {
124 return method;
125 }
126 }
127 return null;
128 }
129
130 /**
131 * For debugging
132 * @return the number of children in this runner
133 */
134 int getChildrenCount() {
135 return getChildren().size();
136 }
137
138 /**
139 * For debugging (and only for assertion messages)
140 * @return shows human-readable info about the children
141 */
142 String describeChildren() {
143 List<FrameworkMethod> children = getChildren();
144 if (children == null) {
145 return "null";
146 }
147 List<String> descriptions = new ArrayList<String>(children.size());
148 for (FrameworkMethod method : children) {
149 descriptions.add( method.getName() );
150 }
151 return descriptions.toString();
152 }
153
154 @Override
155 public Object createTest() throws Exception
156 {
157 if (testObject != null) {
158 return testObject;
159 }
160 try
161 {
162 testObject = getTestClass().getOnlyConstructor().newInstance(parameterization.getArguments());
163 return testObject;
164 }
165 catch(IllegalArgumentException e)
166 {
167 throw new IllegalArgumentException("parameters: " + Arrays.toString(parameterization.getArguments()), e);
168 }
169 }
170
171 @Override
172 protected List<FrameworkMethod> getChildren() {
173 List<FrameworkMethod> ret = super.getChildren();
174 for(ListIterator<FrameworkMethod> iter = ret.listIterator(); iter.hasNext(); ) {
175 FrameworkMethod frameworkMethod = iter.next();
176 try {
177 if (!onlyIfFilter(frameworkMethod)) {
178 iter.remove();
179 }
180 } catch (OnlyIfException e) {
181 iter.set(new OnlyIfErrorFrameworkMethod(frameworkMethod.getMethod(), e));
182 }
183 }
184 return ret;
185 }
186
187 @Override
188 public String getName()
189 {
190 return parameterization.getName();
191 }
192
193 @Override
194 public String testName(FrameworkMethod method)
195 {
196 return String.format("%s [%s]", method.getName(), parameterization.getName());
197 }
198
199 @Override
200 protected void validateConstructor(List<Throwable> errors)
201 {
202 validateOnlyOneConstructor(errors);
203 }
204
205 @Override
206 protected Statement classBlock(RunNotifier notifier)
207 {
208 return childrenInvoker(notifier);
209 }
210
211 @Override
212 protected void runChild(FrameworkMethod method, RunNotifier notifier)
213 {
214 if (expectedToPass(method))
215 {
216 super.runChild(method, notifier);
217 }
218 else
219 {
220 notifier.fireTestIgnored( describeChild(method));
221 }
222 }
223
224 private static class OnlyIfException extends Exception {
225 private OnlyIfException(String message, Throwable cause) {
226 super(message, cause);
227 }
228
229 private OnlyIfException(String message) {
230 super(message);
231 }
232 }
233
234 boolean onlyIfFilter(FrameworkMethod method) throws OnlyIfException {
235 OnlyIf onlyIf = method.getAnnotation(OnlyIf.class);
236 if (onlyIf != null) {
237 if (!runOnlyIf(onlyIf.value(), true)) {
238 return false;
239 }
240 }
241 OnlyIfNot onlyIfNot = method.getAnnotation(OnlyIfNot.class);
242 return onlyIfNot == null || runOnlyIf(onlyIfNot.value(), false);
243 }
244
245 private boolean runOnlyIf(String methodName, boolean mustEqual) throws OnlyIfException {
246 boolean result;
247 if (methodName.endsWith("()")) {
248 methodName = methodName.substring(0, methodName.length() - 2); // snip off the "()"
249 result = execOnlyIfMethod(methodName);
250 }
251 else {
252 result = getOnlyIfField(methodName);
253 }
254 return result == mustEqual;
255 }
256
257
258 private boolean execOnlyIfMethod(String methodName) throws OnlyIfException {
259 final Object result;
260 final Method onlyIfMethod;
261 final Class<?> testClass = getTestClass().getJavaClass();
262 try {
263 onlyIfMethod = testClass.getMethod(methodName);
264 } catch (NoSuchMethodException e) {
265 throw new OnlyIfException("no such method: public boolean " + methodName + "()", e);
266 }
267 if (!onlyIfMethod.getReturnType().equals(boolean.class)) {
268 throw new OnlyIfException("no such method: public boolean " + methodName + "()");
269 }
270 try {
271 Object test = createTest();
272 result = onlyIfMethod.invoke(test);
273 } catch (Exception e) {
274 throw new OnlyIfException("couldn't invoke " + methodName + "()", e);
275 }
276 try {
277 return (Boolean) result;
278 } catch (ClassCastException e) {
279 throw new OnlyIfException("method " + methodName + "() didn't return boolean", e);
280 }
281 }
282
283 private boolean getOnlyIfField(String fieldName) throws OnlyIfException {
284 final Class<?> testClass = getTestClass().getJavaClass();
285 final Field field;
286 try {
287 field = testClass.getField(fieldName);
288 } catch (Exception e) {
289 throw new OnlyIfException("Can't get field: " + fieldName, e);
290 }
291 try {
292 Object test = createTest();
293 return field.getBoolean(test);
294 } catch (Exception e) {
295 throw new OnlyIfException("couldn't get boolean field " + fieldName + "()", e);
296 }
297 }
298
299 boolean expectedToPass(FrameworkMethod method)
300 {
301 if (overrideOn)
302 {
303 return true;
304 }
305 if (! parameterization.expectedToPass())
306 {
307 return false;
308 }
309 Failing failing = method.getAnnotation(Failing.class);
310 if (failing == null)
311 {
312 return true;
313 }
314 if (failing.value().length == 0)
315 {
316 return false;
317 }
318
319 for (final String paramName : failing.value())
320 {
321 if (paramNameUsesRegex(paramName))
322 {
323 if (paramNameMatchesRegex(parameterization.getName(), paramName))
324 {
325 return false;
326 }
327 }
328 else if (parameterization.getName().equals(paramName))
329 {
330 return false;
331 }
332 }
333 return true;
334 }
335 }
336
337 static boolean paramNameUsesRegex(String paramName)
338 {
339 return paramName.length() > 2
340 && (paramName.charAt(0)=='/')
341 && (paramName.charAt(paramName.length()-1)=='/');
342 }
343
344 /**
345 * Returns whether a given parameterization matches a given regex. The regex should be in "/regex/" format.
346 * @param paramName the haystack, as it were
347 * @param paramRegex a string that starts and ends with '/', and between them has a needle.
348 * @return whether the paramRegex is found in paramName
349 */
350 static boolean paramNameMatchesRegex(String paramName, String paramRegex)
351 {
352 assert paramRegex.charAt(0)=='/';
353 assert paramRegex.charAt(paramRegex.length()-1)=='/';
354 assert paramRegex.length() > 2;
355 String regex = paramRegex.substring(1, paramRegex.length()-1);
356 return Pattern.compile(regex).matcher(paramName).find();
357 }
358
359 @SuppressWarnings("unused") // Invoked by reflection
360 public NamedParameterizedRunner(Class<?> klass) throws Throwable
361 {
362 super(klass, Collections.<Runner>emptyList());
363
364 if (getTestClass().getJavaClass().getAnnotation(Ignore.class) != null)
365 {
366 runners = Collections.unmodifiableList(Arrays.asList((Runner)new IgnoredClassRunner(klass)));
367 return;
368 }
369
370 List<Runner> localRunners = new LinkedList<Runner>();
371
372 Collection<Parameterization> parameterizations = getParameterizations();
373 checkFailingParameterizations(parameterizations);
374
375 final String override = System.getProperty(PARAMETERIZATION_OVERRIDE);
376 final boolean overrideIsRegex = (override != null) && paramNameUsesRegex(override);
377 if (override != null)
378 {
379 String msg = "Override is set to";
380 if (overrideIsRegex)
381 {
382 msg += " regex";
383 }
384 msg += ":" + override;
385 logger.info(msg);
386 }
387 for (Parameterization param : parameterizations)
388 {
389 final boolean useThisParam;
390 if (override == null)
391 {
392 useThisParam = true;
393 }
394 else if (overrideIsRegex)
395 {
396 useThisParam = paramNameMatchesRegex(param.getName(), override);
397 }
398 else
399 {
400 useThisParam = param.getName().equals(override);
401 }
402 if (useThisParam)
403 {
404 if (override != null)
405 {
406 logger.info("Adding parameterization: " + param.getName());
407 }
408 localRunners.add(new ReifiedParamRunner(getTestClass().getJavaClass(), param, override != null));
409 }
410 }
411 runners = Collections.unmodifiableList(localRunners);
412 }
413
414 @Override
415 protected List<Runner> getChildren()
416 {
417 return runners;
418 }
419
420 /**
421 * Gets the parameterization
422 * @return the parameterization collection
423 * @throws Throwable if the annotation requirements are not met, or if there's an error in invoking
424 * the class's "get parameterizations" method.
425 */
426 private Collection<Parameterization> getParameterizations() throws Throwable
427 {
428 TestClass cls = getTestClass();
429 List<FrameworkMethod> methods = cls.getAnnotatedMethods(TestParameters.class);
430
431 if (methods.size() != 1)
432 {
433 throw new Exception("class " + cls.getName() + " must have exactly 1 method annotated with "
434 + TestParameters.class.getSimpleName() +"; found " + methods.size());
435 }
436
437 FrameworkMethod method = methods.get(0);
438 checkParameterizationMethod(method);
439
440 @SuppressWarnings("unchecked")
441 Collection<Parameterization> ret = (Collection<Parameterization>) method.invokeExplosively(null);
442 checkParameterizations(ret);
443 return ret;
444 }
445
446 /**
447 * Checks the parameterizations collection for correctness
448 * @param collection the collection
449 * @throws Exception if the collection was null or contained duplicates
450 */
451 private void checkParameterizations(Collection<Parameterization> collection) throws Exception
452 {
453 if (collection == null)
454 {
455 throw new Exception("parameterizations collection may not return null");
456 }
457 Set<String> duplicates = new HashSet<String>();
458 Set<Parameterization> checkSet = new HashSet<Parameterization>();
459 for (Parameterization param : collection)
460 {
461 if (param == null)
462 {
463 throw new Exception("parameterization collection may not contain null values");
464 }
465 if (!checkSet.add(param))
466 {
467 duplicates.add(param.getName());
468 }
469 }
470 if (duplicates.size() != 0)
471 {
472 throw new Exception("duplicated parameterization names: " + duplicates);
473 }
474 }
475
476 /**
477 * Checks the @Failing annotations on @Test methods.
478 *
479 * Specifically, this checks that no item in the @Failing list is repeated, and that each item in that list
480 * corresponds to an actual parameterization.
481 * @param parameterizations the known parameterizations; will not be modified.
482 * @throws org.junit.runners.model.InitializationError if a check fails
483 */
484 private void checkFailingParameterizations(Collection<Parameterization> parameterizations) throws InitializationError
485 {
486 Collection<String> paramNames = new HashSet<String>();
487 for (Parameterization param : parameterizations)
488 {
489 boolean added = paramNames.add(param.getName());
490 assert added : "uncaught duplicate: " + param;
491 }
492
493 Set<String> duplicatesChecker = new HashSet<String>();
494 for(FrameworkMethod method : super.getTestClass().getAnnotatedMethods(Failing.class))
495 {
496 String[] failing = method.getAnnotation(Failing.class).value();
497 if (failing != null)
498 {
499 for(int i=0; i < failing.length; ++i)
500 {
501 if (!duplicatesChecker.add(failing[i]))
502 {
503 throw new InitializationError("duplicate parameterization name in @Failing list: "
504 + method.getName() + "[" + i + "]<" + failing[i] + ">");
505 }
506 if ( !(paramNameUsesRegex(failing[i]) || paramNames.contains(failing[i])) )
507 {
508 throw new InitializationError("parameterization is marked as failing, "
509 + "but isn't in list of parameterizations: "
510 + method.getName() + "[" + i + "]<" + failing[i] +"> not in " + paramNames);
511 }
512 }
513 duplicatesChecker.clear();
514 }
515 }
516 }
517
518
519 /**
520 * Checks the parameterization method for correctness.
521 * @param frameworkMethod the method
522 * @throws Exception if the annotation requirements are not met
523 */
524 private static void checkParameterizationMethod(FrameworkMethod frameworkMethod) throws Exception
525 {
526 final Method method = frameworkMethod.getMethod();
527
528 if (method.getParameterTypes().length != 0)
529 {
530 throw new Exception(complainingThat(method, "must take no arguments"));
531 }
532
533 final int modifiers = frameworkMethod.getMethod().getModifiers();
534 if (! Modifier.isPublic(modifiers))
535 {
536 throw new Exception(complainingThat(method, "must be public"));
537 }
538 if (! Modifier.isStatic(modifiers))
539 {
540 throw new Exception(complainingThat(method, "must be static"));
541 }
542
543 final Type genericRet = method.getGenericReturnType();
544 final String mustReturnCorrectly = "must return Collection of " + Parameterization.class;
545 if (! (genericRet instanceof ParameterizedType))
546 {
547 throw new Exception(complainingThat(method, mustReturnCorrectly));
548 }
549 final ParameterizedType ret = (ParameterizedType) genericRet;
550 if (!(ret.getRawType() instanceof Class) && Collection.class.isAssignableFrom((Class)ret.getRawType()))
551 {
552 throw new Exception(complainingThat(method, mustReturnCorrectly));
553 }
554 if (ret.getActualTypeArguments().length != 1)
555 {
556 throw new Exception(complainingThat(method, mustReturnCorrectly + "; raw Collection is not allowed"));
557 }
558 if (!ret.getActualTypeArguments()[0].equals(Parameterization.class))
559 {
560 throw new Exception(complainingThat(method, mustReturnCorrectly));
561 }
562 }
563
564 private static String complainingThat(Method method, String mustBe)
565 {
566 assert method != null;
567 assert mustBe != null;
568 return String.format("%s.%s() %s", method.getDeclaringClass().getName(), method.getName(), mustBe);
569 }
570}
0571
=== added file 'src/main/java/com/motpot/npr/OnlyIf.java'
--- src/main/java/com/motpot/npr/OnlyIf.java 1970-01-01 00:00:00 +0000
+++ src/main/java/com/motpot/npr/OnlyIf.java 2011-09-08 16:01:22 +0000
@@ -0,0 +1,20 @@
1package com.motpot.npr;
2
3import java.lang.annotation.ElementType;
4import java.lang.annotation.Retention;
5import java.lang.annotation.RetentionPolicy;
6import java.lang.annotation.Target;
7
8/**
9 * Represents a condition for running a test.
10 */
11@Retention(RetentionPolicy.RUNTIME)
12@Target(ElementType.METHOD)
13public @interface OnlyIf
14{
15 /**
16 * The method that should be invoked to see if this annotated method should be run
17 * @return
18 */
19 String value();
20}
021
=== added file 'src/main/java/com/motpot/npr/OnlyIfNot.java'
--- src/main/java/com/motpot/npr/OnlyIfNot.java 1970-01-01 00:00:00 +0000
+++ src/main/java/com/motpot/npr/OnlyIfNot.java 2011-09-08 16:01:22 +0000
@@ -0,0 +1,20 @@
1package com.motpot.npr;
2
3import java.lang.annotation.ElementType;
4import java.lang.annotation.Retention;
5import java.lang.annotation.RetentionPolicy;
6import java.lang.annotation.Target;
7
8/**
9 * Represents a condition for running a test.
10 */
11@Retention(RetentionPolicy.RUNTIME)
12@Target(ElementType.METHOD)
13public @interface OnlyIfNot
14{
15 /**
16 * The method that should be invoked to see if this annotated method should be run
17 * @return
18 */
19 String value();
20}
021
=== added file 'src/main/java/com/motpot/npr/Parameterization.java'
--- src/main/java/com/motpot/npr/Parameterization.java 1970-01-01 00:00:00 +0000
+++ src/main/java/com/motpot/npr/Parameterization.java 2011-09-08 16:01:22 +0000
@@ -0,0 +1,152 @@
1package com.motpot.npr;
2
3import java.util.Arrays;
4import java.util.Iterator;
5import java.util.LinkedList;
6import java.util.List;
7
8public final class Parameterization
9{
10 private String name;
11 private final List<Object> args;
12 private boolean expectedToPass;
13
14 public static Parameterization create(String name, Object... args)
15 {
16 return new Parameterization(name, true, args);
17 }
18
19 public static Parameterization failing(String name, Object... args)
20 {
21 return new Parameterization(name, false, args);
22 }
23
24 public Parameterization(String name, boolean isPassing, Object... args)
25 {
26 if (name == null) {
27 throw new IllegalArgumentException("name can't be null");
28 }
29 if (args == null) {
30 throw new IllegalArgumentException("args can't be null");
31 }
32 this.name = name;
33 this.args = new LinkedList<Object>(Arrays.asList(args));
34 this.expectedToPass = isPassing;
35 }
36
37 /**
38 * <p>Creates a copy of this parameterization.</p>
39 *
40 * <p>The original parameterization's arguments list is copied shallowly.</p>
41 * @param copyFrom the original parameterization
42 */
43 public Parameterization(Parameterization copyFrom)
44 {
45 this.name = copyFrom.name;
46 this.args = new LinkedList<Object>(copyFrom.args);
47 this.expectedToPass = copyFrom.expectedToPass;
48 }
49
50 public String getName()
51 {
52 return name;
53 }
54
55 public void setName(String name)
56 {
57 this.name = name;
58 }
59
60 /**
61 * Returns this parameterization's arguments as an Object array.
62 *
63 * This array is <em>not</em> backed by the parameterization, so changes in one are not reflected in the other.
64 * However, the array is a shallow copy, so modifying an element of the parameterization in the list will be
65 * reflected in the array, and the vice versa.
66 * @return the arguments
67 */
68 public Object[] getArguments()
69 {
70 return args.toArray();
71 }
72
73 /**
74 * Returns this parameterization's arguments as a list.
75 *
76 * This list is backed by the parameterization, so changes to one are reflected in the other.
77 * @return a list of arguments, backed by the parameterization
78 */
79 public List<Object> getArgsAsList()
80 {
81 return args;
82 }
83
84 public boolean expectedToPass()
85 {
86 return expectedToPass;
87 }
88
89 public void setExpectedToPass(boolean expectedToPass)
90 {
91 this.expectedToPass = expectedToPass;
92 }
93
94 @Override
95 public boolean equals(Object o)
96 {
97 if (this == o)
98 {
99 return true;
100 }
101 if (o == null || getClass() != o.getClass())
102 {
103 return false;
104 }
105 Parameterization that = (Parameterization) o;
106 return name.equals(that.name);
107 }
108
109 @Override
110 public int hashCode()
111 {
112 return name.hashCode();
113 }
114
115 public boolean equivalent(Parameterization other)
116 {
117 if (!this.name.equals(other.name))
118 return false;
119 if (this.expectedToPass != other.expectedToPass)
120 return false;
121 if (this.args.size() != other.args.size())
122 return false;
123
124 Iterator<Object> myIter = this.args.iterator();
125 Iterator<Object> otherIter = other.args.iterator();
126
127 while (myIter.hasNext())
128 {
129 Object mine = myIter.next();
130 Object his = otherIter.next();
131
132 if (mine == null)
133 {
134 if (his != null)
135 {
136 return false;
137 }
138 }
139 else if (!mine.equals(his))
140 {
141 return false;
142 }
143 }
144 return true;
145 }
146
147 @Override
148 public String toString()
149 {
150 return "Parameterization[" + (expectedToPass? "PASSING " : "FAILING ") + name + ": " + args + " ]";
151 }
152}
0153
=== added file 'src/main/java/com/motpot/npr/ParameterizationBuilder.java'
--- src/main/java/com/motpot/npr/ParameterizationBuilder.java 1970-01-01 00:00:00 +0000
+++ src/main/java/com/motpot/npr/ParameterizationBuilder.java 2011-09-08 16:01:22 +0000
@@ -0,0 +1,159 @@
1package com.motpot.npr;
2
3import java.util.LinkedList;
4import java.util.List;
5
6public final class ParameterizationBuilder
7{
8 private final List<Parameterization> list;
9
10 /**
11 * Creates a builder with no starting parameterizations.
12 */
13 public ParameterizationBuilder()
14 {
15 this(new LinkedList<Parameterization>());
16 }
17
18 /**
19 * Creates a builder backed by a list. Changes to the one will be reflected in the other, and {@linkplain #asList()}
20 * will return the same instance as is passed to this method.
21 * @param backingList The list that backs this builder.
22 */
23 public ParameterizationBuilder(List<Parameterization> backingList)
24 {
25 list = backingList;
26 }
27
28 /**
29 * Adds a parameterization to the end of the list.
30 * @param name the parameterization's name
31 * @param args the parameterization's arguments
32 */
33 public void add(String name, Object... args)
34 {
35 list.add(Parameterization.create(name, args));
36 }
37
38 /**
39 * Adds a parameterization that's expected to fail to the end of the list
40 * @param name the parameterization's name
41 * @param args the parameterization's arguments
42 */
43 public void addFailing(String name, Object... args)
44 {
45 list.add(Parameterization.failing(name, args));
46 }
47
48 /**
49 * Adds a parameterization to the end of the list.
50 * @param name the parameterization's name
51 * @param expectedToPass whether the parameterization is expected to pass any tests
52 * @param args the parameterization's arguments
53 */
54 public void create(String name, boolean expectedToPass, Object... args)
55 {
56 list.add(new Parameterization(name, expectedToPass, args));
57 }
58
59 /**
60 * <p>Performs a cartesian product of parameterizations by prepending each of the incoming args to each
61 * existing parameter's arg list.</p>
62 *
63 * For instance, if you have parameters <tt>[ ("A", 1, 2, 3) and ("B", 4, 5, 6) ]</tt>, and you called
64 * <tt>multiplyParametersByPrepending("foo-", 'c', "bar", 'd')</tt>, you would get the following
65 * parameterizations, in this order:
66 * <ol>
67 * <li>"foo-A", 'c', 1, 2, 3</li>
68 * <li>"bar-A", 'd', 1, 2, 3</li>
69 * <li>"foo-B", 'c', 4, 5, 6</li>
70 * <li>"bar-B", 'd', 1, 2, 3</li>
71 * </ol>
72 * @param args the list of named args to multiply by. Every other element (starting with the first) in the list must
73 * be a String that represents the name prefix; the element following each prefix is the argument to append to
74 * the args list.
75 * @throws IllegalArgumentException if the args aren't given as String-Object pairings.
76 * @throws IllegalStateException if there are no existing parameterizations to multiply by
77 */
78 public void multiplyParametersByPrepending(Object... args)
79 {
80 cartesianProduct(false, args);
81 }
82
83 /**
84 * <p>Performs a cartesian product of parameterizations by appending each of the incoming args to each
85 * existing parameter's arg list. If you supply a prefix, it will also be appended to each parameter's name.</p>
86 *
87 * <p>This works just like {@link #multiplyParametersByPrepending(Object...)}, only each parameter label and
88 * value is appended instead of prepended.</p>
89 * @param args the list of named args to multiply by. Every other element (starting with the first) in the list must
90 * be a String that represents the name suffix; the element following each suffix is the argument to append to
91 * the args list.
92 * @throws IllegalArgumentException if the args aren't given as String-Object pairings.
93 * @throws IllegalStateException if there are no existing parameterizations to multiply by
94 * @see #multiplyParametersByPrepending(Object...)
95 */
96 public void multiplyParametersByAppending(Object... args)
97 {
98 cartesianProduct(true, args);
99 }
100
101 private void cartesianProduct(boolean append, Object[] args)
102 {
103 if (list.size() == 0)
104 {
105 throw new IllegalStateException("can't multiply yet -- no args defined");
106 }
107 if ( (args.length % 2) != 0)
108 {
109 throw new IllegalArgumentException("odd number of arguments");
110 }
111
112 List<Parameterization> product = new LinkedList<Parameterization>();
113 for (Parameterization param : list)
114 {
115 Object[] origArgs = param.getArguments();
116 Object[] newArgs = new Object[origArgs.length + 1];
117 System.arraycopy(origArgs, 0, newArgs, append ? 0 : 1, origArgs.length);
118
119 for(int i=0; i < args.length; i+= 2)
120 {
121 String label;
122 try
123 {
124 label = (String)args[i];
125 }
126 catch (ClassCastException e)
127 {
128 throw new IllegalArgumentException("argument at index " + i + " is not a String");
129 }
130
131 if (label == null)
132 {
133 label = param.getName();
134 }
135 else
136 {
137 label = append ?
138 param.getName() + label
139 : label + param.getName();
140 }
141 newArgs[append ? origArgs.length : 0] = args[i+1];
142 product.add(new Parameterization(label, param.expectedToPass(), newArgs));
143 }
144 }
145
146 list.clear();
147 list.addAll(product);
148 }
149
150 /**
151 * Represents this builder's parameterizations. The returning list is backed by this builder, so changes
152 * to either are seen in both.
153 * @return the list that backs this builder
154 */
155 public List<Parameterization> asList()
156 {
157 return list;
158 }
159}
0160
=== added directory 'src/test'
=== added directory 'src/test/java'
=== added directory 'src/test/java/com'
=== added directory 'src/test/java/com/motpot'
=== added directory 'src/test/java/com/motpot/npr'
=== added file 'src/test/java/com/motpot/npr/NamedParameterizedRunnerTest.java'
--- src/test/java/com/motpot/npr/NamedParameterizedRunnerTest.java 1970-01-01 00:00:00 +0000
+++ src/test/java/com/motpot/npr/NamedParameterizedRunnerTest.java 2011-09-08 16:01:22 +0000
@@ -0,0 +1,316 @@
1package com.motpot.npr;
2
3import com.motpot.npr.NamedParameterizedRunner.ReifiedParamRunner;
4import org.junit.After;
5import org.junit.Before;
6import org.junit.Test;
7import org.junit.runner.Runner;
8import org.junit.runners.model.FrameworkMethod;
9
10import java.util.*;
11
12import static junit.framework.Assert.*;
13
14public final class NamedParameterizedRunnerTest
15{
16 private final static List<Parameterization> builderList = new LinkedList<Parameterization>();
17 private Properties oldProperties;
18 private Properties workingProperties;
19
20 @Before
21 public void setUp()
22 {
23 builderList.clear();
24 oldProperties = System.getProperties();
25 workingProperties = new Properties(oldProperties);
26 System.setProperties(workingProperties);
27 }
28
29 @After
30 public void tearDown()
31 {
32 System.setProperties(oldProperties);
33 }
34
35 public final static class RunEverythingTest
36 {
37 @NamedParameterizedRunner.TestParameters
38 @SuppressWarnings("unused")
39 public static List<Parameterization> params() { return builderList; }
40
41 public RunEverythingTest(char unused)
42 {
43 assert unused != 'a'; // just to shut it up about it not being used
44 }
45
46 @Test
47 public void one() {}
48
49 @Test
50 public void two() {}
51 }
52
53 public final static class OneFailingTest
54 {
55 @NamedParameterizedRunner.TestParameters
56 @SuppressWarnings("unused")
57 public static List<Parameterization> params() { return builderList; }
58
59 public OneFailingTest(char unused)
60 {
61 assert unused != 'a'; // just to shut it up about it not being used
62 }
63
64 @Test
65 public void passing() {}
66
67 @Failing @Test
68 public void failing() {}
69 }
70
71 public final static class OnlyIfTest
72 {
73 @NamedParameterizedRunner.TestParameters
74 @SuppressWarnings("unused")
75 public static List<Parameterization> params() { return builderList; }
76
77 private final int number;
78 @SuppressWarnings("unused") public final boolean numberIs1; // used by @OnlyIf
79
80 public OnlyIfTest(int number) {
81 this.number = number;
82 this.numberIs1 = is1();
83 }
84
85 @Test
86 public void alwaysRun() {}
87
88 @Test @OnlyIf("is1()")
89 public void testIs1Method() {
90 assertEquals("number", 1, number);
91 }
92
93 @Test @OnlyIf("numberIs1")
94 public void testIs1Field() {
95 assertEquals("number", 1, number);
96 }
97
98 public boolean is1() {
99 return number == 1;
100 }
101 }
102
103 @Test
104 public void testRegexUsed()
105 {
106 assertFalse("//", NamedParameterizedRunner.paramNameUsesRegex("//"));
107 assertTrue("/a/", NamedParameterizedRunner.paramNameUsesRegex("/a/"));
108 }
109
110 @Test
111 public void testRegexMatches()
112 {
113 assertFalse("/a/ against 'foo'", NamedParameterizedRunner.paramNameMatchesRegex("foo", "/a/"));
114 assertTrue("/a/ against 'foo bar'", NamedParameterizedRunner.paramNameMatchesRegex("foo bar", "/a/"));
115 assertFalse("/foo/ against 'o'", NamedParameterizedRunner.paramNameMatchesRegex("o", "/foo/"));
116 }
117
118 @Test
119 public void testRunEverythingPasses() throws Throwable
120 {
121 ParameterizationBuilder builder = new ParameterizationBuilder(builderList);
122 builder.add("alpha", 'a');
123 builder.add("beta", 'b');
124
125 NamedParameterizedRunner runner = new NamedParameterizedRunner(RunEverythingTest.class);
126
127 Map<String,ReifiedParamRunner> map = testParameterizations(runner,
128 "Parameterization[PASSING alpha: [a] ]",
129 "Parameterization[PASSING beta: [b] ]");
130
131 testOverrides(map.values(), false);
132
133 testFrameworkMethod(map.get("Parameterization[PASSING alpha: [a] ]"), RunEverythingTest.class, "one", true);
134 testFrameworkMethod(map.get("Parameterization[PASSING alpha: [a] ]"), RunEverythingTest.class, "two", true);
135 testFrameworkMethod(map.get("Parameterization[PASSING beta: [b] ]"), RunEverythingTest.class, "one", true);
136 testFrameworkMethod(map.get("Parameterization[PASSING beta: [b] ]"), RunEverythingTest.class, "two", true);
137 }
138
139 @Test
140 public void testRunEverythingAlphaPasses() throws Throwable
141 {
142 ParameterizationBuilder builder = new ParameterizationBuilder(builderList);
143 builder.add("alpha", 'a');
144 builder.addFailing("beta", 'b');
145
146 NamedParameterizedRunner runner = new NamedParameterizedRunner(RunEverythingTest.class);
147
148 Map<String,ReifiedParamRunner> map = testParameterizations(runner,
149 "Parameterization[PASSING alpha: [a] ]",
150 "Parameterization[FAILING beta: [b] ]");
151
152 testOverrides(map.values(), false);
153
154 testFrameworkMethod(map.get("Parameterization[PASSING alpha: [a] ]"), RunEverythingTest.class, "one", true);
155 testFrameworkMethod(map.get("Parameterization[PASSING alpha: [a] ]"), RunEverythingTest.class, "two", true);
156 testFrameworkMethod(map.get("Parameterization[FAILING beta: [b] ]"), RunEverythingTest.class, "one", false);
157 testFrameworkMethod(map.get("Parameterization[FAILING beta: [b] ]"), RunEverythingTest.class, "two", false);
158 }
159
160 @Test
161 public void testOneMethodFailing() throws Throwable
162 {
163 ParameterizationBuilder builder = new ParameterizationBuilder(builderList);
164 builder.add("alpha", 'a');
165 builder.add("beta", 'b');
166
167 NamedParameterizedRunner runner = new NamedParameterizedRunner(OneFailingTest.class);
168
169 Map<String,ReifiedParamRunner> map = testParameterizations(runner,
170 "Parameterization[PASSING alpha: [a] ]",
171 "Parameterization[PASSING beta: [b] ]");
172
173 testOverrides(map.values(), false);
174
175 testFrameworkMethod(map.get("Parameterization[PASSING alpha: [a] ]"), OneFailingTest.class, "passing", true);
176 testFrameworkMethod(map.get("Parameterization[PASSING alpha: [a] ]"), OneFailingTest.class, "failing", false);
177 testFrameworkMethod(map.get("Parameterization[PASSING beta: [b] ]"), OneFailingTest.class, "passing", true);
178 testFrameworkMethod(map.get("Parameterization[PASSING beta: [b] ]"), OneFailingTest.class, "failing", false);
179 }
180
181 @Test
182 public void testOverrideOfFailingMethod() throws Throwable
183 {
184 workingProperties.put(NamedParameterizedRunner.PARAMETERIZATION_OVERRIDE, "beta");
185 ParameterizationBuilder builder = new ParameterizationBuilder(builderList);
186 builder.add("alpha", 'a');
187 builder.add("beta", 'b');
188
189 NamedParameterizedRunner runner = new NamedParameterizedRunner(OneFailingTest.class);
190
191 Map<String,ReifiedParamRunner> map = testParameterizations(runner,
192 "Parameterization[PASSING beta: [b] ]");
193
194 testOverrides(map.values(), true);
195
196 testFrameworkMethod(map.get("Parameterization[PASSING beta: [b] ]"), OneFailingTest.class, "passing", true);
197 testFrameworkMethod(map.get("Parameterization[PASSING beta: [b] ]"), OneFailingTest.class, "failing", true);
198 }
199
200 @Test
201 public void testOverrideOfFailingParam() throws Throwable
202 {
203 workingProperties.put(NamedParameterizedRunner.PARAMETERIZATION_OVERRIDE, "beta");
204 ParameterizationBuilder builder = new ParameterizationBuilder(builderList);
205 builder.add("alpha", 'a');
206 builder.addFailing("beta", 'b');
207
208 NamedParameterizedRunner runner = new NamedParameterizedRunner(OneFailingTest.class);
209
210 Map<String,ReifiedParamRunner> map = testParameterizations(runner,
211 "Parameterization[FAILING beta: [b] ]");
212
213 testOverrides(map.values(), true);
214
215 testFrameworkMethod(map.get("Parameterization[FAILING beta: [b] ]"), OneFailingTest.class, "passing", true);
216 testFrameworkMethod(map.get("Parameterization[FAILING beta: [b] ]"), OneFailingTest.class, "failing", true);
217 }
218
219 @Test
220 public void testOverrideUsingRegex() throws Throwable
221 {
222 workingProperties.put(NamedParameterizedRunner.PARAMETERIZATION_OVERRIDE, "/a/");
223 ParameterizationBuilder builder = new ParameterizationBuilder(builderList);
224 builder.add("alpha", 'a');
225 builder.addFailing("beta", 'b');
226
227 NamedParameterizedRunner runner = new NamedParameterizedRunner(OneFailingTest.class);
228
229 Map<String,ReifiedParamRunner> map = testParameterizations(runner,
230 "Parameterization[PASSING alpha: [a] ]",
231 "Parameterization[FAILING beta: [b] ]");
232
233 testOverrides(map.values(), true);
234
235 testFrameworkMethod(map.get("Parameterization[PASSING alpha: [a] ]"), OneFailingTest.class, "passing", true);
236 testFrameworkMethod(map.get("Parameterization[PASSING alpha: [a] ]"), OneFailingTest.class, "failing", true);
237 testFrameworkMethod(map.get("Parameterization[FAILING beta: [b] ]"), OneFailingTest.class, "passing", true);
238 testFrameworkMethod(map.get("Parameterization[FAILING beta: [b] ]"), OneFailingTest.class, "failing", true);
239 }
240
241 @Test
242 public void testOnlyIf() throws Throwable {
243 ParameterizationBuilder builder = new ParameterizationBuilder(builderList);
244 builder.add("one", 1);
245 builder.add("two", 2);
246
247 NamedParameterizedRunner runner = new NamedParameterizedRunner(OnlyIfTest.class);
248
249 Map<String,ReifiedParamRunner> map = testParameterizations(runner,
250 "Parameterization[PASSING one: [1] ]",
251 "Parameterization[PASSING two: [2] ]");
252
253 {
254 ReifiedParamRunner forOne = map.get("Parameterization[PASSING one: [1] ]");
255 assertEquals("param one: " + forOne.describeChildren(), 3, forOne.getChildrenCount());
256 testFrameworkMethod(forOne, OnlyIfTest.class, "testIs1Method", true);
257 testFrameworkMethod(forOne, OnlyIfTest.class, "testIs1Field", true);
258 testFrameworkMethod(forOne, OnlyIfTest.class, "alwaysRun", true);
259 }
260 {
261 ReifiedParamRunner forTwo = map.get("Parameterization[PASSING two: [2] ]");
262 assertEquals("param two: " + forTwo.describeChildren(), 1, forTwo.getChildrenCount());
263 testFrameworkMethod(forTwo, OnlyIfTest.class, "alwaysRun", true);
264 }
265 }
266
267 private static void testOverrides(Collection<ReifiedParamRunner> runners, boolean expectedOverride)
268 {
269 for (ReifiedParamRunner runner : runners)
270 {
271 assertEquals(runner.toString(), expectedOverride, runner.overrideOn());
272 }
273 }
274
275 private static void testFrameworkMethod(ReifiedParamRunner runner, Class<?> testClass, String testMethod,
276 boolean expectedToPass)
277 {
278 String frameworkMethodString = "public void " + testClass.getName() + "." + testMethod + "()";
279 FrameworkMethod method = runner.getChild(frameworkMethodString);
280 assertNotNull(frameworkMethodString, method);
281 assertEquals(frameworkMethodString, expectedToPass, runner.expectedToPass(method));
282 }
283
284 /**
285 * Confirms that each given name has a {@linkplain ReifiedParamRunner} associated with it, and returns the
286 * name -> runner map
287 * @param runner the parameterized runner
288 * @param names the expected names
289 * @return a map of names to reified runners
290 */
291 private static Map<String,ReifiedParamRunner> testParameterizations(NamedParameterizedRunner runner, String... names)
292 {
293 List<Runner> children = runner.getChildren();
294 assertEquals("children.size()", names.length, children.size());
295
296 Set<String> expectedNames = new HashSet<String>(names.length, 1.0f);
297 for (String name : names) {
298 assertTrue("unexpected error, duplicate name: " + name, expectedNames.add(name));
299 }
300
301 Map<String,ReifiedParamRunner> foundRunners = new HashMap<String, ReifiedParamRunner>();
302 for (Runner child : children)
303 {
304 ReifiedParamRunner reified = (ReifiedParamRunner)child;
305 String paramToString = reified.paramToString();
306 assertNull("duplicate name: " + paramToString, foundRunners.put(paramToString, reified));
307 }
308
309 for (String expected : expectedNames)
310 {
311 assertTrue("didn't find expected param: " + expected, foundRunners.containsKey(expected));
312 }
313
314 return foundRunners;
315 }
316}
0317
=== added file 'src/test/java/com/motpot/npr/OnlyIfUsageTest.java'
--- src/test/java/com/motpot/npr/OnlyIfUsageTest.java 1970-01-01 00:00:00 +0000
+++ src/test/java/com/motpot/npr/OnlyIfUsageTest.java 2011-09-08 16:01:22 +0000
@@ -0,0 +1,68 @@
1package com.motpot.npr;
2
3import org.junit.Test;
4import org.junit.runner.RunWith;
5
6import java.util.List;
7
8import static org.junit.Assert.*;
9
10@RunWith(NamedParameterizedRunner.class)
11public final class OnlyIfUsageTest {
12 @NamedParameterizedRunner.TestParameters
13 public static List<Parameterization> params() {
14 ParameterizationBuilder builder = new ParameterizationBuilder();
15 builder.add("foo", "foo");
16 builder.add("bar", "bar");
17 return builder.asList();
18 }
19
20 private final String string;
21 public final boolean stringIsFoo;
22
23 public OnlyIfUsageTest(String string) {
24 this.string = string;
25 stringIsFoo = "foo".equals(string);
26 }
27
28 @Test @OnlyIf("isFoo()")
29 public void equalsFoo() {
30 assertEquals("string", "foo", string);
31 }
32
33 @Test @OnlyIf("stringIsFoo")
34 public void equalsFooByField() {
35 assertEquals("string", "foo", string);
36 }
37
38 @Test @OnlyIfNot("isFoo()")
39 public void notEqualsFoo() {
40 if ("foo".equals(string)) {
41 fail("found a foo!");
42 }
43 }
44
45 @Test @OnlyIf("hasThreeChars()") @OnlyIfNot("lastCharR()")
46 public void threeCharNoTrailingR() {
47 assertEquals("string length", 3, string.length());
48 assertFalse("last char was r! <" + string + '>', string.charAt(2) == 'r');
49 }
50
51 @Test
52 public void stringNotNull() {
53 assertNotNull("string", string);
54 }
55
56 public boolean isFoo() {
57 return "foo".equals(string);
58 }
59
60 public boolean hasThreeChars() {
61 return string.length() == 3;
62 }
63
64 public boolean lastCharR() {
65 // for simplicity, we'll assume string not null, string.length > 0
66 return string.charAt( string.length() - 1) == 'r';
67 }
68}
069
=== added file 'src/test/java/com/motpot/npr/ParameterizationBuilderTest.java'
--- src/test/java/com/motpot/npr/ParameterizationBuilderTest.java 1970-01-01 00:00:00 +0000
+++ src/test/java/com/motpot/npr/ParameterizationBuilderTest.java 2011-09-08 16:01:22 +0000
@@ -0,0 +1,153 @@
1package com.motpot.npr;
2
3import org.junit.Test;
4
5import java.util.Arrays;
6import java.util.List;
7
8import static junit.framework.Assert.*;
9
10
11public final class ParameterizationBuilderTest
12{
13 @Test
14 public void testAdd()
15 {
16 ParameterizationBuilder builder = new ParameterizationBuilder();
17 builder.add("hello", 1, "someString", 50L);
18
19 List<Parameterization> params = builder.asList();
20 assertEquals("params size", 1, params.size());
21 assertEquivalent("only one",
22 Parameterization.create("hello", 1, "someString", 50L),
23 params.get(0));
24 }
25
26 @Test
27 public void testAddFailing()
28 {
29 ParameterizationBuilder builder = new ParameterizationBuilder();
30 builder.addFailing("hello", 1, "someString", 50L);
31
32 List<Parameterization> params = builder.asList();
33 assertEquals("params size", 1, params.size());
34 assertEquivalent("only one",
35 Parameterization.failing("hello", 1, "someString", 50L),
36 params.get(0));
37 }
38
39 @Test
40 public void testCreate()
41 {
42 ParameterizationBuilder builder = new ParameterizationBuilder();
43 builder.create("hello", true, 1, "someString", 50L);
44 builder.create("hi", false, -1, "anotherString", -50L);
45
46 List<Parameterization> params = builder.asList();
47 assertEquals("params size", 2, params.size());
48 assertEquivalent("passing",
49 new Parameterization("hello", true, 1, "someString", 50L),
50 params.get(0));
51 assertEquivalent("failing",
52 new Parameterization("hi", false, -1, "anotherString", -50L),
53 params.get(1));
54 }
55
56 @Test
57 public void testAppend()
58 {
59 ParameterizationBuilder builder = new ParameterizationBuilder();
60 builder.add("ONE", 1, 2, 3);
61 builder.addFailing("TWO", 4, 5, 6);
62 builder.multiplyParametersByAppending("-a", 'a', "-b", 'b', "-c", 'c');
63
64 List<Parameterization> expected = Arrays.asList(
65 Parameterization.create("ONE-a", 1, 2, 3, 'a'),
66 Parameterization.create("ONE-b", 1, 2, 3, 'b'),
67 Parameterization.create("ONE-c", 1, 2, 3, 'c'),
68 Parameterization.failing("TWO-a", 4, 5, 6, 'a'),
69 Parameterization.failing("TWO-b", 4, 5, 6, 'b'),
70 Parameterization.failing("TWO-c", 4, 5, 6, 'c')
71 );
72 List<Parameterization> actual = builder.asList();
73
74 assertEquals("params size", expected.size(), actual.size());
75
76 for(int i=0, len=expected.size(); i<len; ++i)
77 {
78 assertEquivalent("param " + i, expected.get(i), actual.get(i));
79 }
80 }
81
82 @Test
83 public void testPrepend()
84 {
85 ParameterizationBuilder builder = new ParameterizationBuilder();
86 builder.add("ONE", 1, 2, 3);
87 builder.addFailing("TWO", 4, 5, 6);
88 builder.multiplyParametersByPrepending("a:", 'a', "b:", 'b', "c:", 'c');
89
90 List<Parameterization> expected = Arrays.asList(
91 Parameterization.create("a:ONE", 'a', 1, 2, 3),
92 Parameterization.create("b:ONE", 'b', 1, 2, 3),
93 Parameterization.create("c:ONE", 'c', 1, 2, 3),
94 Parameterization.failing("a:TWO", 'a', 4, 5, 6),
95 Parameterization.failing("b:TWO", 'b', 4, 5, 6),
96 Parameterization.failing("c:TWO", 'c', 4, 5, 6)
97 );
98 List<Parameterization> actual = builder.asList();
99
100 assertEquals("params size", expected.size(), actual.size());
101
102 for(int i=0, len=expected.size(); i<len; ++i)
103 {
104 assertEquivalent("param " + i, expected.get(i), actual.get(i));
105 }
106 }
107
108 @Test
109 public void testListBackedByBuilder()
110 {
111 ParameterizationBuilder builder = new ParameterizationBuilder();
112 List<Parameterization> list = builder.asList();
113
114 assertEquals("list size before building", 0, list.size());
115
116 builder.add("whatever", 'a');
117 assertEquals("list size after building", 1, list.size());
118
119 assertSame("new list", builder.asList(), list);
120 }
121
122 @Test(expected=IllegalArgumentException.class)
123 public void builderMultiplierArgsNotPaired()
124 {
125 ParameterizationBuilder builder = new ParameterizationBuilder();
126 builder.add("whatever", 1);
127
128 builder.multiplyParametersByAppending("label", 2, 3);
129 }
130
131 @Test(expected=IllegalArgumentException.class)
132 public void builderMultiplierArgsLabelNotString()
133 {
134 ParameterizationBuilder builder = new ParameterizationBuilder();
135 builder.add("whatever", 1);
136
137 builder.multiplyParametersByAppending("label", 2, 3, "this label is in the wrong place");
138 }
139
140 @Test(expected=IllegalStateException.class)
141 public void builderMultipliesByZero()
142 {
143 new ParameterizationBuilder().multiplyParametersByAppending();
144 }
145
146 private static void assertEquivalent(String message, Parameterization expected, Parameterization actual)
147 {
148 if (!expected.equivalent(actual))
149 {
150 fail(message + " expected<" + expected + "> but was <" + actual + ">");
151 }
152 }
153}

Subscribers

People subscribed via source and target branches

to all changes: