5858import java .util .regex .Matcher ;
5959import java .util .regex .Pattern ;
6060import java .util .stream .Collectors ;
61+ import java .util .stream .Stream ;
6162
6263
6364/**
@@ -264,39 +265,129 @@ void check(Path dir) {
264265
265266 /**
266267 * Run all methods annotated with @Test, followed by printSummary.
267- * Typically called on a tester object in main()
268+ * The methods are invoked in the order found using getDeclaredMethods.
269+ * The arguments for the invocation are provided {@link #getTestArgs(Method)}.
270+ *
271+ * Typically called on a tester object in main().
268272 *
273+ * @throws IllegalArgumentException if any test method does not have a recognized signature
269274 * @throws Exception if any errors occurred
270275 */
271276 public void runTests () throws Exception {
272- runTests (m -> new Object [ 0 ] );
277+ runTests (this :: getTestArgs );
273278 }
274279
275280 /**
276281 * Runs all methods annotated with @Test, followed by printSummary.
282+ * The methods are invoked in the order found using getDeclaredMethods.
283+ * The arguments for the invocation are provided by a given function.
284+ *
277285 * Typically called on a tester object in main()
278286 *
279287 * @param f a function which will be used to provide arguments to each
280288 * invoked method
281- * @throws Exception if any errors occurred
289+ * @throws Exception if any errors occurred while executing a test method
282290 */
283291 public void runTests (Function <Method , Object []> f ) throws Exception {
284- for (Method m : getClass ().getDeclaredMethods ()) {
292+ for (Method m : getClass ().getDeclaredMethods ()) {
285293 Annotation a = m .getAnnotation (Test .class );
286294 if (a != null ) {
287- try {
288- out .println ("Running test " + m .getName ());
289- m .invoke (this , f .apply (m ));
290- } catch (InvocationTargetException e ) {
291- Throwable cause = e .getCause ();
292- throw (cause instanceof Exception ) ? ((Exception ) cause ) : e ;
293- }
295+ runTest (m , f );
294296 out .println ();
295297 }
296298 }
297299 printSummary ();
298300 }
299301
302+ /**
303+ * Run the specified methods annotated with @Test, or all methods annotated
304+ * with @Test if none are specified, followed by printSummary.
305+ * The methods are invoked in the order given in the methodNames argument,
306+ * or the order returned by getDeclaredMethods if no names are provided.
307+ * The arguments for the invocation are provided {@link #getTestArgs(Method)}.
308+ *
309+ * Typically called on a tester object in main(String[] args), perhaps using
310+ * args as the list of method names.
311+ *
312+ * @throws IllegalStateException if any methods annotated with @Test are overloaded
313+ * @throws IllegalArgumentException if any of the method names does not name a suitable method
314+ * @throws NullPointerException if {@code methodNames} is {@code null}, or if any of the names are {@code null}
315+ * @throws Exception if any errors occurred while executing a test method
316+ */
317+ public void runTests (String ... methodNames ) throws Exception {
318+ runTests (this ::getTestArgs , methodNames );
319+ }
320+
321+ /**
322+ * Run the specified methods annotated with @Test, or all methods annotated
323+ * with @Test if non are specified, followed by printSummary.
324+ * The methods are invoked in the order given in the methodNames argument,
325+ * or the order returned by getDeclaredMethods if no names are provided.
326+ * The arguments for the invocation are provided {@link #getTestArgs(Method)}.
327+ *
328+ * Typically called on a tester object in main(String[] args), perhaps using
329+ * args as the list of method names.
330+ *
331+ * @throws IllegalStateException if any methods annotated with @Test are overloaded
332+ * @throws IllegalArgumentException if any of the method names does not name a suitable method
333+ * @throws NullPointerException if {@code methodNames} is {@code null}, or if any of the names are {@code null}
334+ * @throws Exception if any errors occurred while executing a test method
335+ */
336+ public void runTests (Function <Method , Object []> f , String ... methodNames ) throws Exception {
337+ if (methodNames .length == 0 ) {
338+ runTests (f );
339+ } else {
340+ Map <String , Method > testMethods = Stream .of (getClass ().getDeclaredMethods ())
341+ .filter (this ::isTestMethod )
342+ .collect (Collectors .toMap (Method ::getName , Function .identity (),
343+ (o , n ) -> {
344+ throw new IllegalStateException ("test method " + o .getName () + " is overloaded" );
345+ }));
346+
347+ List <Method > list = new ArrayList <>();
348+ for (String mn : methodNames ) {
349+ Method m = testMethods .get (mn );
350+ if (m == null ) {
351+ throw new IllegalArgumentException ("test method " + mn + " not found" );
352+ }
353+ list .add (m );
354+ }
355+
356+ for (Method m : list ) {
357+ runTest (m , f );
358+ }
359+ }
360+ }
361+
362+ protected boolean isTestMethod (Method m ) {
363+ return m .getAnnotation (Test .class ) != null ;
364+ }
365+
366+ protected Object [] getTestArgs (Method m ) throws IllegalArgumentException {
367+ Class <?>[] paramTypes = m .getParameterTypes ();
368+ if (paramTypes .length == 0 ) {
369+ return new Object [] {};
370+ } else if (paramTypes .length == 1 && paramTypes [0 ] == Path .class ) {
371+ return new Object [] { Path .of (m .getName ())};
372+ } else {
373+ throw new IllegalArgumentException ("unknown signature for method "
374+ + m + Stream .of (paramTypes )
375+ .map (Class ::toString )
376+ .collect (Collectors .joining (", " , "(" , ")" ))) ;
377+ }
378+ }
379+
380+ protected void runTest (Method m , Function <Method , Object []> f ) throws Exception {
381+ try {
382+ out .println ("Running test " + m .getName ());
383+ m .invoke (this , f .apply (m ));
384+ } catch (InvocationTargetException e ) {
385+ Throwable cause = e .getCause ();
386+ throw (cause instanceof Exception ) ? ((Exception ) cause ) : e ;
387+ }
388+
389+ }
390+
300391 /**
301392 * Runs javadoc.
302393 * The output directory used by this call and the final exit code
@@ -1470,4 +1561,4 @@ void write() {
14701561 }
14711562 }
14721563
1473- }
1564+ }
0 commit comments