在Gradle中,如何在每次执行JUnit测试类之前设置唯一的系统属性? [英] In Gradle, how to set unique system property before each execution of JUnit test class?

查看:269
本文介绍了在Gradle中,如何在每次执行JUnit测试类之前设置唯一的系统属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的gradle脚本中,每个Junit测试类,maxParallelForksforkEvery将使用新的JVM启动新进程. 是否可以为每个测试进程/JVM/Junit类赋予其自己的独特系统属性?

In the gradle script below, maxParallelForks and forkEvery will start a new process with a new JVM per Junit test class. Is there a way to give each test process/JVM/Junit class its own unique system property?

我尝试了一个实验,在该实验中,我在beforeSuite方法中将UUID值作为系统属性传递.

I tried an experiment where I passed a UUID value as a system property in the beforeSuite method.

apply plugin:'java'
test {
    ignoreFailures = true
    maxParallelForks = 8
    forkEvery = 1
    systemProperty 'some.prop', 'value'

   beforeSuite { descriptor ->
    logger.lifecycle("Before suite: " + descriptor)
    def theuuid = UUID.randomUUID().toString()
    println "beforeSuite uuid =" + theuuid
    systemProperty 'some.uuid', theuuid
   }
   beforeTest { descriptor ->
      logger.lifecycle("Running test: " + descriptor)
   }
}
repositories {
    mavenCentral()
}
dependencies {
    testCompile 'junit:junit:4.12'
}

JUnit测试类LoginTest1LoginTest2在测试方法中打印出系统属性.

The JUnit test classes, LoginTest1 and LoginTest2 print out the system property in a test method.

public class LoginTest1 {
    private String userName="Gradle";
@Test
    public void testUserName() throws Exception {
        System.out.println("LoginTest1: Testing Login ");

        System.out.println("LoginTest1: Testing Login some.prop -> " 
           + System.getProperty("some.prop"));
        System.out.println("LoginTest1: Testing Login some.uuid -> " 
           + System.getProperty("some.uuid"));

    assertTrue(userName.equals("Gradle"));
    }
}


public class LoginTest2 {
    private String userName="Gradle";

@Test
    public void testUserName() throws Exception {
        System.out.println("LoginTest2: Testing Login ");

        System.out.println("LoginTest2: Testing Login some.prop -> " 
           + System.getProperty("some.prop"));
        System.out.println("LoginTest2: Testing Login some.uuid -> " 
           + System.getProperty("some.uuid"));

    assertTrue(userName.equals("Gradle"));
        }
}


从下面的gradle输出中可以看到,

在运行各个JUnit测试方法之前,将调用beforeSuite方法.两个测试类都具有6a006689-474f-47d5-9649-a88c92b45095


As you can see from the gradle output below, the beforeSuite method is called before running individual JUnit test methods. Both test classes get the same system property of 6a006689-474f-47d5-9649-a88c92b45095

 $ gradle clean test

> Task :test 
Before suite: Gradle Test Run :test
beforeSuite uuid =6a006689-474f-47d5-9649-a88c92b45095
Before suite: Gradle Test Executor 1
beforeSuite uuid =39edb608-3027-4ad8-bd15-f52f50175582
Before suite: Test class ch6.login.LoginTest1
beforeSuite uuid =c0ce55e0-924c-4319-becb-bc27229c9cf3
Before suite: Gradle Test Executor 2
beforeSuite uuid =c15eaac0-7ea7-46d2-8235-8dc49b3f7a39
Running test: Test testUserNameNotNull(ch6.login.LoginTest1)
Before suite: Test class ch6.login.LoginTest2
beforeSuite uuid =73abbe24-5b78-4935-867a-445ac4ac20ef
Running test: Test testUserName(ch6.login.LoginTest1)
Running test: Test testUserName(ch6.login.LoginTest2)


JUnit测试类输出:


JUnit test class output:

LoginTest1: Testing Login 
LoginTest1: Testing Login some.prop -> value
LoginTest1: Testing Login some.uuid -> 6a006689-474f-47d5-9649-a88c92b45095

LoginTest2: Testing Login 
LoginTest2: Testing Login some.prop -> value
LoginTest2: Testing Login some.uuid -> 6a006689-474f-47d5-9649-a88c92b45095

似乎先调用了beforeSuite(称为:test"),然后每个Test Executor调用了一次.在所有JVM中都设置了第一个uuid值("6a006689"). 我可以使用简单的beforeClass方法吗?

It looks like there's an initial call to beforeSuite (seen as ":test") and then once per Test Executor. The first uuid value ("6a006689") is set across all JVMs. Is there anything like a simple beforeClass method I could use?

在下面的调试日志中,看起来给Test Executors的jvm参数是-Dsome.uuid=6a006689-474f-47d5-9649-a88c92b45095,它仅用于创建新的JVM(根据forkEvery配置).这使我认为我想做的事情在Gradle中是不可能的.

In the debug log below,it looks like the Test Executors are given the jvm argument -Dsome.uuid=6a006689-474f-47d5-9649-a88c92b45095 and that is used soley to create new JVMs (as per the forkEvery config). This makes me think that what I want to do is impossible in Gradle.

20:23:42.466 [INFO] [org.gradle.process.internal.DefaultExecHandle] Starting process 'Gradle Test Executor 1'. Working directory: /a/b/ Command: /usr/lib/jvm/java-8-openjdk-amd64/bin/java -Djava.security.manager=worker.org.gradle.process.internal.worker.child.BootstrapSecurityManager -Dorg.g
radle.native=false -Dsome.prop=value -Dsome.uuid=6a006689-474f-47d5-9649-a88c92b45095 -Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en -Duser.variant -ea -cp /data/.gradle/caches/4.3.1/workerMain/gradle-worker.jar worker.org.gradle.process.internal.worker.GradleWorkerMain 'Gradle Test Executor 1'

20:23:42.466 [INFO] [org.gradle.process.internal.DefaultExecHandle] Starting process 'Gradle Test Executor 2'. Working directory: /a/b/ Command: /usr/lib/jvm/java-8-openjdk-amd64/bin/java -Djava.security.manager=worker.org.gradle.process.internal.worker.child.BootstrapSecurityManager -Dorg.g
radle.native=false -Dsome.prop=value -Dsome.uuid=6a006689-474f-47d5-9649-a88c92b45095 -Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en -Duser.variant -ea -cp /data/.gradle/caches/4.3.1/workerMain/gradle-worker.jar worker.org.gradle.process.internal.worker.GradleWorkerMain 'Gradle Test Executor 2'

更新8/2018

以下解决方案在Gradle 4.9及更高版本中不起作用

相反,有一个org.gradle.test.worker系统属性,可用于区分工作程序,计算显示名称,临时目录等.此test.worker只是一个递增的long值. Gradle团队没有使测试人员可配置的计划.遗憾的是,为了升级Gradle,我不得不在测试代码中进行一些重大的重构. JUnit 5中的"@BeforeAllCallback"可能对您有用.

Update 8/2018

The following solution does not work in Gradle 4.9 and greater

Instead, there is a org.gradle.test.worker system property which you can use to distinguish between workers, calculate display names, temporary directories, etc. This test.worker is simply an increasing long value. The Gradle team has no plans on making Test Workers configurable. A pity because I had to do some major refactoring in my test code in order to upgrade Gradle. The "@BeforeAllCallback" in JUnit 5 might be useful to you.

此代码演示了lance-java的建议,并成功回答了我的问题. .我有以下build.gradle脚本,该脚本使用MyTestTask扩展Test并添加一个称为my_uuid的唯一值.请注意,构建脚本必须具有forkEvery = 1,以确保每个JUnit测试都调用一次copyTo:

This code demonstrates lance-java 's suggestion and succeeds in answering my question. I have the following build.gradle script which uses MyTestTask to extend Test and add a unique value called my_uuid. Note that the build script must have forkEvery = 1 to ensure copyTo is called once per JUnit test:

class MyTestTask extends Test {

 public Test copyTo(JavaForkOptions target) {
        super.copyTo(target);
      String uuid = UUID.randomUUID().toString();
        System.out.println("MyTestTask copyTo:\n my_uuid=" +  uuid);
        System.out.println("\t before getJvmArgs:" +  target.getJvmArgs());
        System.out.println("\t before getSystemProperties:" +  target.getSystemProperties());

        target.systemProperty("my_uuid", uuid);

        System.out.println("\t after getJvmArgs:" +  target.getJvmArgs());
        System.out.println("\t after getSystemProperties:" +  target.getSystemProperties());

        return this;
    }

}
///

subprojects {
    apply plugin: 'java'

    repositories {
        mavenCentral()
    }

    dependencies {
        testCompile 'junit:junit:4.12'
    }


    test {
        enabled false // This doesn't seem to matter.

    }

    task my_test(type: MyTestTask) {

        forkEvery 1 // need this so copyTo called each JUnit test

        testLogging.showStandardStreams = true

        doFirst {
            def uuid = UUID.randomUUID().toString()
            println "TEST:Task name is $name. In doFirst. uuid is " + uuid

            jvmArgs '-Dcommon_uuid='+ uuid

        }
    }
}

执行的Junit测试非常简单,只需打印出System.getProperty("my_uuid")和System.getProperty("common_uuid").

The Junit tests that are executed are trivial and simply print out System.getProperty("my_uuid") and System.getProperty("common_uuid").

> Task :CustomCopyToSubProject:my_test 
TEST:Task name is my_test. In doFirst. uuid is eed1ee92-7805-4b8e-a74c-96218d1be6e1
MyTestTask copyTo:
MyTestTask copyTo:
 my_uuid=a7996c20-1085-4397-9e32-fd84467dcb45
 my_uuid=69f6f347-71d0-4e5d-9fad-66bf4468fab3
         before getJvmArgs:[]
         before getJvmArgs:[]
         before getSystemProperties:[common_uuid:eed1ee92-7805-4b8e-a74c-96218d1be6e1]
         before getSystemProperties:[common_uuid:eed1ee92-7805-4b8e-a74c-96218d1be6e1]
         after getJvmArgs:[]
         after getJvmArgs:[]
         after getSystemProperties:[common_uuid:eed1ee92-7805-4b8e-a74c-96218d1be6e1, my_uuid:69f6f347-71d0-4e5d-9fad-66bf4468fab3]
         after getSystemProperties:[common_uuid:eed1ee92-7805-4b8e-a74c-96218d1be6e1, my_uuid:a7996c20-1085-4397-9e32-fd84467dcb45]

ch3.LoginTest2 > testUserName2 STANDARD_OUT
    LoginTest2.java: Testing Login !  >>---> my_uuid=a7996c20-1085-4397-9e32-fd84467dcb45 common_uuid=eed1ee92-7805-4b8e-a74c-96218d1be6e1

ch3.LoginTest1 > testUserName1 STANDARD_OUT
    LoginTest1.java: Testing Login !  >>---> my_uuid=69f6f347-71d0-4e5d-9fad-66bf4468fab3 common_uuid=eed1ee92-7805-4b8e-a74c-96218d1be6e1

task my_testdoFirst中设置common_uuid. MyTestTask.copyTo方法设置其自己的my_uuid. 您可以从输出中看到两次MyTestTask被调用,每个JUnit测试任务(LoginTest1和LoginTest2)被调用一次.这两个JUnit测试在my_uuid中获得了自己独特的系统属性.

The task my_test sets common_uuid in doFirst. The MyTestTask.copyTo method sets its own my_uuid. You can see from the output and MyTestTask is called twice, once per JUnit test task (LoginTest1 and LoginTest2). The two JUnit tests get their own unique system property in my_uuid.

推荐答案

我认为您想拦截Test.copyTo(JavaForkOptions target),不幸的是,我看到的唯一方法是扩展

I think you want to intercept Test.copyTo(JavaForkOptions target), unfortunately the only way I can see to do this is to extend Test

例如

public class Test2 extends org.gradle.api.tasks.testing.Test {
    public Test copyTo(JavaForkOptions target) {
        super.copyTo(target);
        target.systemProperty("uuid", UUID.randomUUID().toString());
        return this;
    }
}

build.gradle

build.gradle

apply plugin: 'java'
test {
    enabled = false
}
task test2(type: Test2) {
    // guessing you'll need to configure a bit of stuff here
}
check.dependsOn test2

这篇关于在Gradle中,如何在每次执行JUnit测试类之前设置唯一的系统属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆