【问题标题】:How to give System property to my test via Gradle and -D如何通过 Gradle 和 -D 为我的测试提供系统属性
【发布时间】:2014-02-19 18:59:19
【问题描述】:

我有一个读取系统属性的 Java 程序

System.getProperty("cassandra.ip");

我有一个以

开头的 Gradle 构建文件
gradle test -Pcassandra.ip=192.168.33.13

gradle test -Dcassandra.ip=192.168.33.13

但是 System.getProperty 将始终返回 null

我发现的唯一方法是将其添加到我的 Gradle 构建文件中

test {
    systemProperty "cassandra.ip", "192.168.33.13"
}

我如何通过 -D 做到这一点

【问题讨论】:

  • 当您使用gradle -Dcassandra.ip=192.168.33.13 时会发生什么?无论如何,测试任务会派生一个或多个新的 JVM。所以你必须明确地传递属性。不过,没有人强迫你在构建中硬编码他们的价值。

标签: java testing gradle


【解决方案1】:

这对我有用

//in build.gradle file

    tasks.withType(Test) {
        systemProperties = [
           ip: System.getProperty('ip', '192.168.33.13'),
        ]
    }

    task integrationTests(type: Test){
        useTestNG()
    }

假设如果你使用TestNG,可以添加注解@Parameters,如下图

  public class IpAddress {
    @Test
    @Parameters("ip")
    public void printIpAddress(String ip) {
        System.out.println(ip);
    }
 }

现在你可以执行 gradlew 命令了

./gradlew clean -Dip="xx.xx.xx.xx" integrationTests --tests "IpAddress"

如果你想使用@DataProvider传递测试数据,你可以像下面这样传递它,然后执行上面相同的gradle命令来运行测试

 public class IpAddress {
    @DataProvider(name = "GetIP")
    private static Object[][] getIp() {
        return new Object[][]{
                //if -Dip is not provided in command, then by default it gets the value assigned in build.gradle file i.e.'192.168.33.13'
                {System.getProperty("ip")}, 
        };
    }

    @Test(dataProvider = "GetIP")
    public void printIpAddress(String ip) {
        System.out.println(ip);
    }
}

【讨论】:

    【解决方案2】:

    所以我今天也偶然发现了这个问题,对我有用的是以下内容:

    ext.env='prod'
    test {
      systemProperty 'env', System.properties['env'] ?: "${env}"
      println "# test environment: " + systemProperties['env']
      ...
    }
    

    我正在使用 -Penv=dev 调用我的测试任务,并且我在打印中得到了我的 'dev' 值,如果我没有发送任何值,那么我得到了 'prod',这是预期的我的行为。

    值也可以在 java 端访问,使用 System.getProperty("env")

    我对此事的结论是输入值(参数)实际上存储在 System 下,可以通过 System.properties['env'] 访问它em>System.getProperty("env"),而输出(系统属性)存储在 systemProperties 数组中,使其可以通过 systemProperties['env'] em>。

    【讨论】:

      【解决方案3】:

      这是一个将大量项目属性作为系统属性传递给测试 JVM 的变体。我更喜欢项目属性而不是系统属性以增加灵活性。

      task intTest(type: Test) {
          systemProperties project.properties.subMap(["foo", "bar"])
      }
      

      可以在命令行中传递:

       $ gradle intTest -Pfoo=1 -Pbar=2
      

      并在您的测试中检索到:

      String foo = System.getProperty("foo");
      

      【讨论】:

      • 当使用该 subMap 方法运行System.getProperty("someprop") 时,我得到了{someprop=foo} 而不是foo。我不得不在 build.gradle 中使用systemProperty "foo", project.properties.subMap(["foo"]).get("foo")
      • @YngvarKristiansen 您在哪里(如何)使用systemProperty "foo"?即我要求查看使用它的完整代码行?我正在尝试这个问题中建议的所有内容,但 Gradle 仍然没有传递任何参数。希望这可以解决!
      • @HesterLyons 对不起,我没有保留我的代码,所以我不再知道了:\ 我同意它看起来不合适。
      • 谢谢@YngvarKristiansen。从那以后,我发现我的问题是由我的 gradle.build 中包含的 junit gradle 插件引起的。很奇怪。
      【解决方案4】:

      我有一个案例,我需要将 多个 系统属性传递给测试 JVM,而不是 all(不想传递不相关的)。基于上述答案,并使用subMap 过滤我需要的答案,这对我有用:

      task integrationTest(type: Test) {
          // ... Do stuff here ...
          systemProperties System.getProperties().subMap(['PROP1', 'PROP2'])
      }
      

      在这个例子中,只有PROP1PROP2会被传入,如果它们存在于gradle的JVM中的话。

      【讨论】:

        【解决方案5】:

        遇到了这个非常多的问题,除了我不想再次列出 gradle 脚本中命令行上给出的所有属性。因此我将所有系统属性发送给我的测试

        task integrationTest(type: Test) {
            useTestNG()
            options {
                systemProperties(System.getProperties())
            }
        }
        

        【讨论】:

        • 这样做时要小心。当系统属性在调用期间发生变化时,它可能很容易破坏 Gradle 的最新检查。
        • JavaExec 任务相同。 props 存在于任务中,但不在 java 程序中,除非在任务中再次设置。
        【解决方案6】:

        -P 标志用于 gradle 属性,-D 标志用于 JVM 属性。因为测试可能会在新的 JVM 中分叉,所以传递给 gradle 的 -D 参数不会传播到测试 - 听起来这就是您所看到的行为。

        您可以像以前一样在 test 块中使用 systemProperty,但它基于传入的 gradle 属性,方法是通过它传递它 -P:

        test {
            systemProperty "cassandra.ip", project.getProperty("cassandra.ip")
        }
        

        或者,如果你通过 -D 传递它

        test {
            systemProperty "cassandra.ip", System.getProperty("cassandra.ip")
        }
        

        【讨论】:

        • 这对我不起作用(在 Java 代码中使用 System.getProperties().stringPropertyNames().forEach(System.out::println); 测试,它没有出现)
        • 警告:如果未找到属性,getProperty 将抛出 MissingPropertyException。请改用 Eron 的答案:stackoverflow.com/a/43112126/915441
        • gradle.properties 添加默认值将阻止MissingPropertyException
        • 我无法让这两种方法都起作用。无论我做什么 myProperty 始终为空。这也包括下面提到的所有方法。我想知道这是否与更新版本有关,因为所有 cmets 都来自 2018 年? @CLOVIS 你找到解决方案了吗?
        • @HesterLyons 我只想知道如果构建是在测试还是正常运行,所以我使用了 gradle 本身在测试时添加的属性;你可以在这里看到代码:github.com/CLOVIS-AI/wildfyre-java/blob/master/src/main/java/…
        猜你喜欢
        • 2019-10-30
        • 2017-09-24
        • 1970-01-01
        • 1970-01-01
        • 2013-12-27
        • 2010-10-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多