如何告诉 Gradle 使用我的 testng.xml 文件进行测试类和排序?

发布于 2024-10-13 11:14:01 字数 1207 浏览 9 评论 0原文

我试图让 Gradle 执行一些使用 testng.xml 文件定义的测试。我的 testng.xml 文件如下所示:

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="mySuite" verbose="1">

  <listeners>
    <listener class-name="mypackage.MyListener" />
    <listener class-name="mypackage.TestOrderer" />
  </listeners>

  <test name="Tests">
    <classes>
      <class name="mytestpackage.CrazyTest1"/>
      <class name="mytestpackage.CrazyTest2"/>
      <class name="mytestpackage.CrazyTest3"/>
    </classes>
  </test>
</suite>

那么为什么我需要这个?我想确保我的测试以类似于注释定义的方式组织 此处。正如您可能猜到的,TestOrderer 是一个 IMethodInterceptor。

问题是,Gradle 似乎正在接管我的 testng.xml 文件并抓取测试目录以查找它想要执行的测试。即使我禁用此功能,它也无法正确执行这些方法。这是我认为应该有效的方法,但事实并非如此。

test {
  useTestNG()
  options.suites("src/test/resources/crazyTestNG.xml") 
  # Adding 
  # scanForTestClasses = false 
  # causes zero tests to be executed, since the class names don't end in Test
}

看起来这应该是理所当然的...分叉 TestNG 进程并让它运行,但我不知道如何告诉 Gradle 让开并只执行我的测试。

I am attempting to have Gradle execute some tests defined using a testng.xml file. My testng.xml file looks like this:

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="mySuite" verbose="1">

  <listeners>
    <listener class-name="mypackage.MyListener" />
    <listener class-name="mypackage.TestOrderer" />
  </listeners>

  <test name="Tests">
    <classes>
      <class name="mytestpackage.CrazyTest1"/>
      <class name="mytestpackage.CrazyTest2"/>
      <class name="mytestpackage.CrazyTest3"/>
    </classes>
  </test>
</suite>

So why do I need this? I want to ensure that my tests are organized in a way that's defined by annotations similar to that which was listed here. As you might guess, TestOrderer is an IMethodInterceptor.

Here's the problem, Gradle seems to be taking over my testng.xml file and scraping the test directory to find the tests it wants to execute. Even if I disable this, it fails to execute the methods appropriately. Here's what I think should work, but just, doesn't.

test {
  useTestNG()
  options.suites("src/test/resources/crazyTestNG.xml") 
  # Adding 
  # scanForTestClasses = false 
  # causes zero tests to be executed, since the class names don't end in Test
}

It seems like it should be a no-brainer...fork the TestNG process and let it run, but I can't figure out how to tell Gradle to get out of the way and just execute my tests.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

沉默的熊 2024-10-20 11:14:01

以下是如何配置要在 Gradle 任务中执行的测试套件 (xml):

apply plugin: 'java'

repositories {
    mavenCentral()
}
dependencies {
    // add the dependencies as needed
    testCompile group: 'org.testng', name: 'testng', version:'6.8.8'
    testCompile fileTree('lib')
}
test {
    useTestNG() {
        // runlist to executed. path is relative to current folder
        suites 'src/test/resources/runlist/my_test.xml'
    }
}

Here's how you can configure a test suite (xml) to be executed in a Gradle task:

apply plugin: 'java'

repositories {
    mavenCentral()
}
dependencies {
    // add the dependencies as needed
    testCompile group: 'org.testng', name: 'testng', version:'6.8.8'
    testCompile fileTree('lib')
}
test {
    useTestNG() {
        // runlist to executed. path is relative to current folder
        suites 'src/test/resources/runlist/my_test.xml'
    }
}
開玄 2024-10-20 11:14:01

我讨厌 gradle 中的 TestNG 支持...发现与使用原始 TestNG 相比,它最不灵活。我厌倦了摆弄 gradle。 Gradle 任务直接运行 TestNG

task runTests(type: JavaExec, dependsOn: 'classes') {
    main = 'org.testng.TestNG'
    classpath = files("./src/test/resources",
                      project.sourceSets.main.compileClasspath,
                      project.sourceSets.test.compileClasspath,
                      project.sourceSets.main.runtimeClasspath,
                      project.sourceSets.test.runtimeClasspath)
    args = ["-parallel",  "methods", "-threadcount", "1", "-d", "./build/test-output", "./src/test/resources/test.xml"]
}

我的解决方案..使用我从命令行运行的

: gradle runTests

I hated the TestNG support in gradle... Found it to be most un-flexable compared to using raw TestNG. And I was tired of fiddling with gradle. My solution.. Run TestNG directly using a Gradle task

task runTests(type: JavaExec, dependsOn: 'classes') {
    main = 'org.testng.TestNG'
    classpath = files("./src/test/resources",
                      project.sourceSets.main.compileClasspath,
                      project.sourceSets.test.compileClasspath,
                      project.sourceSets.main.runtimeClasspath,
                      project.sourceSets.test.runtimeClasspath)
    args = ["-parallel",  "methods", "-threadcount", "1", "-d", "./build/test-output", "./src/test/resources/test.xml"]
}

Which I run from the command line:

gradle runTests

挽手叙旧 2024-10-20 11:14:01

正如另一个答案指出的那样:解决方案是使用suites命令。< /strong> 虽然我更喜欢参数化该命令的参数,以便从命令行我可以选择我想要运行的任何 TestNG 套件。

test {
    
    // Detect if suite param was passed in
    def runSuite = project.hasProperty("suite")
    
    useTestNG() {
        if (runSuite) {
            // If parameter was passed in, use it in the 'suites' command
            def suiteToRun = project.getProperty("suite")
            suites "src/test/resources/"+suiteToRun
        } else {
            // Handle non-command line executions e.g. running tests from IDE
            parallel 'methods'
            threadCount 2
        }
    }
}

然后,我可以从命令行运行类似的命令:

gradle test -Psuite=mysuite.xml

我更喜欢这样定义一堆自定义 Gradle 任务,因为这种方法会导致混乱的 build.gradle 文件,并且对于添加新套件来说灵活性稍差。

As another answer points out: the solution is to use the suites command. Though I prefer parameterizing the argument for that command so that from the command line I can choose any TestNG suite I want to run.

test {
    
    // Detect if suite param was passed in
    def runSuite = project.hasProperty("suite")
    
    useTestNG() {
        if (runSuite) {
            // If parameter was passed in, use it in the 'suites' command
            def suiteToRun = project.getProperty("suite")
            suites "src/test/resources/"+suiteToRun
        } else {
            // Handle non-command line executions e.g. running tests from IDE
            parallel 'methods'
            threadCount 2
        }
    }
}

Then from the command line I can run something like:

gradle test -Psuite=mysuite.xml

I prefer this to defining a bunch of custom Gradle tasks since that approach results in a messy build.gradle file and is slightly less flexible to new suites being added.

落在眉间の轻吻 2024-10-20 11:14:01

Gradle TestNG 运行程序假设,如果没有指定测试类(通过扫描它们或对名称进行模式匹配),那么它应该完全跳过测试执行。

相反,它还应该考虑是否提供了套件 xml。您能为这个问题添加一个 jira 问题吗?

一种可能的解决方法是使用 options.listener 来指定侦听器,而根本不使用套件 xml 文件:

test {
   options.listeners << 'mypackage.MyListener'
   options.listeners << 'mypackage.TestOrderer'
}

这样您就不需要指定测试类,而只需让扫描为您找到它们即可。

The Gradle TestNG runner assumes that if no test classes are specified, either by scanning for them, or pattern matching on the name, then it should skip test execution entirely.

Instead, it should consider whether a suite xml has been provided or not as well. Could you add a jira issue for this problem?

One possible work around is to use options.listener to specify the listeners, and not use a suite xml file at all:

test {
   options.listeners << 'mypackage.MyListener'
   options.listeners << 'mypackage.TestOrderer'
}

This way you don't need to specify the test classes, and you can just let the scanning find them for you.

水中月 2024-10-20 11:14:01

此方法不使用您的 testng.xml 文件,但您还可以通过将 JUnit 测试组创建为 Gradle 任务来模拟 testNG 测试组和顺序,然后通过在执行构建时对任务执行进行排序来手动对它们进行排序:

// in build.gradle
task testGroupOne(type: Test) {
   //include '**/*SuiteOne.*'
   include '**/SuiteOne.class'
   testReportDir = file("${reportsDir}/SuiteOne")
   testResultsDir = file("${buildDir}/test-results/SuiteOne")
}

task testGroupTwo(type: Test) {
   //include '**/*SuiteTwo.*'
   include '**/SuiteTwo.class'
   testReportDir = file("${reportsDir}/SuiteTwo")
   testResultsDir = file("${buildDir}/test-results/SuiteTwo")
}

然后,运行您的构建例如:gradle testGroupTwo testGroupOne

This method doesn't use your testng.xml file but you could also emulate testNG test groups and order by creating JUnit test groups as Gradle tasks and then order them manually by ordering the task execution when you execute your build:

// in build.gradle
task testGroupOne(type: Test) {
   //include '**/*SuiteOne.*'
   include '**/SuiteOne.class'
   testReportDir = file("${reportsDir}/SuiteOne")
   testResultsDir = file("${buildDir}/test-results/SuiteOne")
}

task testGroupTwo(type: Test) {
   //include '**/*SuiteTwo.*'
   include '**/SuiteTwo.class'
   testReportDir = file("${reportsDir}/SuiteTwo")
   testResultsDir = file("${buildDir}/test-results/SuiteTwo")
}

Then, run your build like: gradle testGroupTwo testGroupOne

绳情 2024-10-20 11:14:01
task runTests(type: JavaExec, dependsOn: 'classes') {
    main = 'org.testng.TestNG'
    classpath = files("./src/test/resources",
                      project.sourceSets.main.compileClasspath,
                      project.sourceSets.test.compileClasspath,
                      project.sourceSets.main.runtimeClasspath,
                      project.sourceSets.test.runtimeClasspath)
    args = ["-parallel",  "methods", "-threadcount", "1", "-d", "./build/test-output", "./src/test/resoenter code hereurces/test.xml"]
}

How to pass VM arguments in args [] ?
task runTests(type: JavaExec, dependsOn: 'classes') {
    main = 'org.testng.TestNG'
    classpath = files("./src/test/resources",
                      project.sourceSets.main.compileClasspath,
                      project.sourceSets.test.compileClasspath,
                      project.sourceSets.main.runtimeClasspath,
                      project.sourceSets.test.runtimeClasspath)
    args = ["-parallel",  "methods", "-threadcount", "1", "-d", "./build/test-output", "./src/test/resoenter code hereurces/test.xml"]
}

How to pass VM arguments in args [] ?
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文