我正在尝试将类列表作为参数传递。 (我可以这样做吗?)我正在使用JUnit和Selenium,我有一个JUnit测试类,这些类由JUnit测试套件类使用@SuiteClasses()
调用,而该测试套件类由包含{{1 }}。我的想法是允许用户从主类中选择JUnit类,该类将存储在某种列表中。调用要运行的JUnit测试类的测试套件将使用该列表并调用那些JUnit类。
原始代码:调用应运行(有效)的JUnit测试类的测试套件类
main()
我正在尝试将其更改为⬇
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({ TestCase1.class, TestCase2.class})
public class AllTests {
}
,在亚军课程中,我会遇到这样的事情。我当时在想,我可以从prop文件中提取类的名称,并允许用户选择将哪些类添加到变量@SuiteClasses(runnerClass.classesToTest)
⬇
classesToTest
当我尝试执行此类操作时,出现此错误⬇
注释属性Suite.SuiteClasses.value的值必须是类文字
问题在于,我可以做这项工作吗?我是否错误地创建了public class runnerClass {
public static Class<?>[] classesToTest = { testCase1.class, testCase2.class };
public static void main(String[] args) {
...
}
}
变量?
答案 0 :(得分:1)
我在JUnit框架中找不到任何解决方案,所以我写了一个快速而肮脏的TestRunner。它只会调用所有以@Test注释的方法,甚至是不可访问的方法(以防万一)。
它不能与任何包含IDE的UnitTest结果显示工具一起使用。
它的用法如下:
public static void main(String[] args) {
Runner run = new Runner(TestCase.class, TestCase2.class);
for(Exception e : run.runUnchecked()) {
System.err.println(e.getCause());
}
}
您可以将类作为vararg或普通数组传递,两者都可以工作。跑步者将返回测试的例外列表。如果测试失败,则引发异常,或者引发失败的异常,或者断言失败,则引发AssertionFailedError
。您可以使用e.getCause()
轻松地打印一行描述,这将显示如下消息:org.opentest4j.AssertionFailedError: expected: <1> but was: <2>
我的示例代码可与JUnit Jupiter测试一起使用,您可以通过更改在Runner类中导入的Test
类来对其进行调整。这必须与用于TestCases的相同。
代码在这里
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.jupiter.api.Test;
/**
* A simple JUnit Test Case Runner, which can dynamically call TestCases by
* their class.
*
* @author Alexander Daum
*
*/
public class Runner {
private Class<?>[] testCases;
public Runner(Class<?>... testCases) {
this.testCases = testCases;
}
/**
* Run all TestCases given in the constructor of this Runner.
*
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public List<Exception> run()
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
List<Exception> testErrors = new ArrayList<>();
for (Class<?> testClazz : testCases) {
Object testCase = testClazz.newInstance();
Method[] methods = testClazz.getDeclaredMethods();
methods = Arrays.stream(methods).filter(m -> m.isAnnotationPresent(Test.class)).toArray(Method[]::new);
for (Method m : methods) {
m.setAccessible(true);
try {
m.invoke(testCase);
} catch (InvocationTargetException e) {
testErrors.add(e);
}
}
}
return testErrors;
}
/**
* The same as {@link Runner#run()}, but all exceptions are wrapped in
* RuntimeException, so no try catch is neccessary, when Errorhandling is not
* required
*/
public List<Exception> runUnchecked() {
try {
return run();
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException
| InstantiationException e) {
throw new RuntimeException(e);
}
}
}