Skip to content

Commit

Permalink
console runner can now discover and execute all tests in classpath
Browse files Browse the repository at this point in the history
  • Loading branch information
jlink committed Nov 18, 2015
1 parent c05f0de commit 258c548
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 13 deletions.
Expand Up @@ -12,6 +12,7 @@

import static java.util.stream.Collectors.toList;

import java.io.File;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
Expand Down Expand Up @@ -219,6 +220,36 @@ public static boolean isPackage(String packageName) {
packageName);
}

public static List<Class<?>> findAllClassesInClassFiles(Predicate<Class<?>> classTester) {
ClasspathScanner scanner = new ClasspathScanner(ReflectionUtils::getDefaultClassLoader,
ReflectionUtils::loadClass);
List<Class<?>> collectedClasses = new ArrayList<>();
// @formatter:off
getAllClasspathRootDirectories().stream()
.filter(File::exists)
.forEach(root -> collectedClasses.addAll(scanner.scanForClassesInClasspathRoot(root, classTester)));
// @formatter:on
return collectedClasses;
}

private static List<File> getAllClasspathRootDirectories() {
//TODO This is quite a hack, since sometimes the classpath is quite different
//A real solution would require the build tools / IDEs to hand in all root directories
String fullClassPath = System.getProperty("java.class.path");
final String separator = System.getProperty("path.separator");
// @formatter:off
return Arrays.stream(fullClassPath.split(separator))
.filter(part -> !part.endsWith(".jar"))
.map(dirPath -> new File(dirPath))
.collect(Collectors.toList());
// @formatter:on
}

public static List<Class<?>> findAllClassesInClasspathRoot(File root, Predicate<Class<?>> classTester) {
return new ClasspathScanner(ReflectionUtils::getDefaultClassLoader,
ReflectionUtils::loadClass).scanForClassesInClasspathRoot(root, classTester);
}

public static List<Class<?>> findAllClassesInPackage(String basePackageName, Predicate<Class<?>> classTester) {
return new ClasspathScanner(ReflectionUtils::getDefaultClassLoader,
ReflectionUtils::loadClass).scanForClassesInPackage(basePackageName, classTester);
Expand Down
Expand Up @@ -47,7 +47,10 @@ public class ConsoleRunner {
description = "Disable colored output (not supported by all terminals)")
private boolean disableAnsiColors;

@Arguments(description = "Test classes, methods or packages to execute")
@Option(name = {"-a", "--all"}, description = "Run all tests")
private boolean runAllTests;

@Arguments(description = "Test classes, methods or packages to execute (ignore if --all|-a has been chosen)")
private List<String> arguments;

// @formatter:on
Expand Down Expand Up @@ -89,8 +92,13 @@ private void run() {
// @formatter:on
);

TestPlanSpecification testPlanSpecification = TestPlanSpecification.build(
testPlanSpecificationElementsFromArguments());
TestPlanSpecification testPlanSpecification = null;
if (runAllTests) {
testPlanSpecification = TestPlanSpecification.build(TestPlanSpecification.allTests());
}
else {
testPlanSpecification = TestPlanSpecification.build(testPlanSpecificationElementsFromArguments());
}

// TODO Provide means to allow manipulation of test plan?
launcher.execute(testPlanSpecification);
Expand Down
@@ -0,0 +1,25 @@
/*
* Copyright 2015 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution and is available at
*
* http://www.eclipse.org/legal/epl-v10.html
*/

package org.junit.gen5.engine;

import lombok.Value;

@Value
public class AllTestsSpecification implements TestPlanSpecificationElement {

//TODO Should get list of classpath roots from build tools or IDEs
//private Set<File> classpathRoots;

@Override
public void accept(TestPlanSpecificationVisitor visitor) {
visitor.visitAllTestsSpecification();
}
}
Expand Up @@ -66,6 +66,10 @@ public static TestPlanSpecificationElement forName(String anyName) {
String.format("'%s' specifies neither a class, nor a method, nor a package.", anyName));
}

public static TestPlanSpecificationElement allTests() {
return new AllTestsSpecification();
}

public static List<TestPlanSpecificationElement> forNames(Collection<String> classNames) {
return forNames(classNames.stream());
}
Expand Down
Expand Up @@ -25,4 +25,8 @@ default void visitClassSpecification(Class<?> testClass) {

default void visitMethodSpecification(Class<?> testClass, Method testMethod) {
}

default void visitAllTestsSpecification() {
}

}
Expand Up @@ -10,9 +10,6 @@

package org.junit.gen5.engine.junit4;

import java.util.Arrays;
import java.util.List;

import lombok.Data;

import org.junit.gen5.commons.util.ReflectionUtils;
Expand Down Expand Up @@ -54,9 +51,14 @@ public void visitClassSpecification(Class<?> testClass) {

@Override
public void visitPackageSpecification(String packageName) {
List<Class<?>> candidateClasses = ReflectionUtils.findAllClassesInPackage(packageName,
isJUnit4TestClassWithTests);
candidateClasses.stream().forEach(this::visitClassSpecification);
ReflectionUtils.findAllClassesInPackage(packageName, isJUnit4TestClassWithTests).stream().forEach(
this::visitClassSpecification);
}

@Override
public void visitAllTestsSpecification() {
ReflectionUtils.findAllClassesInClassFiles(isJUnit4TestClassWithTests).stream().forEach(
testClass -> visitClassSpecification(testClass));
}

private void addRecursively(JUnit4TestDescriptor parent) {
Expand Down
Expand Up @@ -13,7 +13,6 @@
import static org.junit.gen5.commons.util.ReflectionUtils.*;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

import org.junit.gen5.commons.util.ReflectionUtils;
Expand Down Expand Up @@ -61,8 +60,14 @@ public void visitUniqueIdSpecification(String uniqueId) {

@Override
public void visitPackageSpecification(String packageName) {
List<Class<?>> candidateClasses = findAllClassesInPackage(packageName, isTestClassWithTests);
candidateClasses.stream().forEach(testClass -> visitClassSpecification(testClass));
findAllClassesInPackage(packageName, isTestClassWithTests).stream().forEach(
testClass -> visitClassSpecification(testClass));
}

@Override
public void visitAllTestsSpecification() {
ReflectionUtils.findAllClassesInClassFiles(isTestClassWithTests).stream().forEach(
testClass -> visitClassSpecification(testClass));
}
});
}
Expand Down
2 changes: 1 addition & 1 deletion sample-project/build.gradle
Expand Up @@ -13,7 +13,7 @@ task runSampleTestCases(type: JavaExec) {
classpath = sourceSets.test.runtimeClasspath
classpath += project(':junit-console').sourceSets.main.runtimeClasspath
main = 'org.junit.gen5.console.ConsoleRunner'
args 'com.example'
args '--all' // 'com.example'
}

test {
Expand Down

0 comments on commit 258c548

Please sign in to comment.