gpt4 book ai didi

java - 务实地允许用户选择要运行的 JUnit 测试类

转载 作者:行者123 更新时间:2023-11-30 06:02:44 25 4
gpt4 key购买 nike

我正在尝试将类列表作为参数传递。 (我可以这样做吗?)我正在使用 JUnit 和 Selenium,我有由 JUnit 测试套件类调用的 JUnit 测试类,使用 @SuiteClasses() 并且该测试套件类由包含 main() 的类。我的想法是允许用户从主类中选择 JUnit 类,这些类将存储在某种列表中。调用要运行的 JUnit 测试类的测试套件将使用该列表并调用这些 JUnit 类。

<小时/>

原始代码:调用应该运行的 JUnit 测试类的测试套件类(有效)⬇

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 {

}

我正在尝试将其更改为类似⬇

@SuiteClasses(runnerClass.classesToTest)

在运行者类(class)中我会有这样的东西。我在想,我也许可以从 prop 文件中提取类的名称,并允许用户选择将哪些类添加到变量 classesToTest

public class runnerClass {    
public static Class<?>[] classesToTest = { testCase1.class, testCase2.class };
public static void main(String[] args) {
...
}
}

当我尝试做这样的事情时,我收到此错误⬇

The value for annotation attribute Suite.SuiteClasses.value must be a class literal

JavaDoc for @SuiteClasses()

<小时/>

所以问题是,我可以做到这一点吗?我是否错误地创建了 classesToTest 变量?

最佳答案

我在 JUnit 框架中找不到任何解决方案,因此我编写了一个快速而肮脏的测试运行程序。它只是调用所有用@Test注释的方法,甚至是不可访问的方法(以防万一)。

它不适用于任何包含 UnitTest 结果显示工具的 IDE。

它的用法如下:

public static void main(String[] args) {
Runner run = new Runner(TestCase.class, TestCase2.class);
for(Exception e : run.runUnchecked()) {
System.err.println(e.getCause());
}
}

您可以将类作为可变参数或普通数组传递,两者都可以。运行程序将返回测试的异常列表。如果测试失败,它会抛出异常,要么是导致失败的异常,要么是断言失败,则抛出 AssertionFailedError被抛出。您可以使用 e.getCause() 轻松打印一行描述,这将显示如下消息:org.opentest4j.AssertionFailedError: expected: <1> but was: <2>

我的示例代码适用于 JUnit Jupiter 测试,您可以通过更改 Test 来调整它类被导入到 Runner 类中。这必须与您的测试用例所使用的相同。

这是代码

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);
}
}
}

关于java - 务实地允许用户选择要运行的 JUnit 测试类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51952282/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com