1

我正在使用 java 通过代码创建 testng xml 以编程方式运行测试用例(TestNg 测试用例)。运行完全没问题。

问题:

我想执行实时上传的测试用例,这意味着我的服务器正在运行,并且我正在将新记录的测试用例(它们未编译,传递 .java 文件)上传到这个正在运行的服务器中,这些测试用例传递给上面创建的 testng xml java 代码。但是我收到错误,即 在类路径中找不到类:com.packagename.SampleTestNgTestcase 当我重新运行服务器并调用此功能时,它会执行测试用例。

我一直在浏览并尝试通过练习编译TestNg测试用例的技术来找到解决方案,但没有成功,因为没有找到如何编译测试用例的地方。

非常感谢有关我可以执行非编译测试用例的方式或其他方式,如何以编程方式编译 testcase.java 文件的任何帮助。如果需要有关问题清除的更多详细信息,我会的!

4

1 回答 1

0

编译 TestNG 测试类与编译常规 java 类没有任何不同。

假设您的 CLASSPATH 没有任何问题(下面的代码没有说明这一点),这里有一个简单的示例,您可以使用它来开始。

参考:大部分实现都深受此博客的启发和借鉴。

假设您有一个名为的文本文件sample.txt,其内容如下:

package foo.bar;
import org.testng.annotations.Test;

public class Example {
    @Test
    public void testMethod() {
        System.err.println("Hello world");
    }
}
import java.nio.file.Path;

public class ClassInfo {
  String packageName;
  String className;
  String sourceCode;
  Path javaFile;
  Path classFile;
}
import static java.nio.charset.StandardCharsets.UTF_8;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.stream.Collectors;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import org.testng.TestNG;

public class DynamicTestNgExecutor {

  public static void main(String[] args) throws Exception {
    DynamicTestNgExecutor.runTests("src/test/resources/sample.txt", "foo.bar.Example");
  }

  public static void runTests(String sourcePath, String className) throws Exception {
    ClassInfo classInfo = parse(sourcePath, className);
    saveSource(classInfo);
    compileSource(classInfo);
    runClass(classInfo, className);
  }

  private static void runClass(ClassInfo classInfo, String className)
      throws MalformedURLException, ClassNotFoundException {
    URL classUrl = classInfo.javaFile.getParent().toFile().toURI().toURL();
    if (!classInfo.packageName.isEmpty()) {
      File file = classInfo.javaFile.toFile();
      int count = classInfo.packageName.split("\\Q.\\E").length;
      for (int i = 0; i <= count; i++) {
        file = file.getParentFile();
      }
      classUrl = file.toURI().toURL();
    }
    URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] {classUrl});
    Class<?> clazz = Class.forName(className, true, classLoader);
    TestNG testNG = new TestNG();
    testNG.setTestClasses(new Class[] {clazz});
    testNG.setVerbose(2);
    testNG.run();
  }

  public static ClassInfo parse(String sourcePath, String className) throws FileNotFoundException {
    InputStream stream = new FileInputStream(sourcePath);
    String separator = System.getProperty("line.separator");
    BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
    ClassInfo info = new ClassInfo();
    info.className = className;
    info.sourceCode = reader.lines().collect(Collectors.joining(separator));
    info.packageName = packageName(info.sourceCode);
    return info;
  }

  private static void compileSource(ClassInfo classInfo) {
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    compiler.run(System.in, System.out, System.err, classInfo.javaFile.toFile().getAbsolutePath());
    classInfo.classFile = classInfo.javaFile.getParent().resolve(classInfo.className + ".class");
  }

  public static void saveSource(ClassInfo classInfo) throws IOException {
    String folder = folderName(classInfo.packageName);
    String tmpProperty = System.getProperty("java.io.tmpdir") + File.separator + folder;
    final boolean success = new File(tmpProperty).mkdirs();
    if (!success) {
      throw new IllegalStateException("Encountered problems when creating the package structure " + tmpProperty);
    }
    classInfo.javaFile = Paths.get(tmpProperty, simpleClassName(classInfo.className) + ".java");
    Files.write(classInfo.javaFile, classInfo.sourceCode.getBytes(UTF_8));
  }

  private static String simpleClassName(String className) {
    String[] parts = className.split("\\Q.\\E");
    if (parts.length == 1) {
      //No package name in the class
      return parts[0];
    }
    int lastButOne = parts.length - 1;
    return parts[lastButOne];
  }

  private static String folderName(String pkg) {
    if (pkg.isEmpty()) {
      return "";
    }
    pkg = pkg.replaceAll("\\Q.\\E", "/");
    return pkg;
  }

  private static String packageName(String source) {
    String separator = System.getProperty("line.separator");
    String pkg =
        Arrays.stream(source.split(separator))
            .filter(each -> each.contains("package"))
            .findAny()
            .orElse("");
    if (pkg.isEmpty()) {
      return "";
    }
    return pkg.replaceAll("package ", "").replaceAll(";", "");
  }
}
于 2020-02-19T03:18:16.237 回答