【问题标题】:How do I detect my test is running on a Jenkins environment?如何检测我的测试是否在 Jenkins 环境中运行?
【发布时间】:2018-12-11 02:32:49
【问题描述】:

如果开发人员的计算机没有运行它的必备软件,我有一个使用Assumption 的 JUnit 测试来跳过测试。尽管是“junit”,但它是一个集成测试。像这样的:

int isSoftwarePresent = new ProcessBuilder("check software presence").start().waitFor();
Assume.assumeThat("Software not present", isSoftwarePresent, is(equalTo(0)));

然而,由于这种假设,我意识到测试已经停止在 Jenkins 上的自动构建上运行,最终引入了回归,测试应该停止。 p>

换句话说,Jenkins从属环境中缺少所需的软件,导致测试被跳过。

自动化测试由 Maven 使用 FailSafe 插件在 Jenkins Pipeline 构建计划中运行。如何检测我的环境是 Jenkins 以便我可以使假设条件更严格?

也就是说,我希望条件是这样的:

boolean isJenkinsBuild = /* true if this is being run inside a Jenkins build, false otherwise */;
boolean isSoftwarePresent = new ProcessBuilder("check software presence").start().waitFor() == 0;
Assume.assumeTrue("Software not present", isSoftwarePresent || isJenkinsBuild);

甚至,

@Test
void testJenkinsEnvironment() {
    ...
    Assume.assumeTrue(isJenkinsBuild);
    Assert.assertTrue(isSoftwarePresent);
}

@Test
void testFeature() {
    ...
    Assume.assumeTrue(isSoftwarePresent);
    ...
}

【问题讨论】:

  • 这听起来像是你过度设计了。将 jenkins 配置为在一段时间后自动使长时间运行的作业失败。此外,让您的 Ops 团队在 CI 服务器上安装所需的软件。编辑:如果您的测试是为了检测其运行时环境而编写的,您打算如何测试测试?
  • @Dave 你的评论太混乱了!构建没有失败,它通过了,因为测试被忽略了。也许这就是为什么你说的对我来说没有意义?我已经用更多细节编辑了这个问题。我不认为那里有任何过度工程,但是,如果有什么,请在代码示例中指出。
  • 我很想对此进行更多辩论,但这更像是一场关于测试设计的哲学辩论,因此不在 StackOverflow 的职权范围内。基本上,我知道你的测试没有失败——它被跳过了。我建议跳过的测试或长时间运行的测试应该使构建失败 - 这将被报告并且不会发生问题回归。过度工程是设计您的测试以检测测试环境(汽车制造商为此遇到了很多麻烦)。
  • @Dave 好吧,没办法。这种特定的软件依赖性不能强加给使用该特定存储库的所有开发人员。
  • 当然,任何没有安装该软件的开发人员都不应该被用作特定构建工作的詹金斯奴隶吗?老实说,我觉得开发者机器会被用作詹金斯奴隶很奇怪,但这是一个完全独立的争论。

标签: java maven jenkins junit maven-failsafe-plugin


【解决方案1】:

有几种方法可以实现这一点:

  1. 您可以让您的应用程序接受参数,然后传递一个 TRUE/FALSE 值表示它是否从 Jenkins 运行。

  2. 还可以读取os的系统属性

例如System.getProperty("os.arch");

但是如果你的 Jenkins 环境和你的 工作区在同一台机器上

  1. 您可以在管道中设置一个环境变量(仅存在于管道中),然后在应用程序中读取该值

像这样:

管道选项1

     pipeline {
            environment {
                FROM_JENKINS= "TRUE" 
            } stage('test'){ 

                   sh "mvn test"
             }
        }

管道选项2

     pipeline {
            stage('test'){ 

                    sh '''FROM_JENKINS="TRUE" // setting the env variable in the same shell where you are running mvn
                        mvn test'''
             }
        }

应用

boolean isJenkinsBuild = Boolean.valueOf(System.getenv("FROM_JENKINS"));
boolean isSoftwarePresent = new ProcessBuilder("check software presence").start().waitFor() == 0;
Assume.assumeTrue("Software not present", isSoftwarePresent || isJenkinsBuild);

希望对你有帮助:)

【讨论】:

    【解决方案2】:

    由于它们很容易测试并传递给构建执行的每个程序,因此我选择基于环境变量进行检查。

    虽然 rohit answer 显示了在 Jenkinsfile 上设置变量的一种方法,但我宁愿依赖 Jenkins 本身所做的事情,所以我检查了在我的 Jenkins 作业中设置的环境变量,并且有很多选项可供选择:

    詹金斯一般信息

    这些在 Jenkins 实例上似乎是不变的。

    • HUDSON_URL
    • JENKINS_URL

    不是 Jenkins 特有的,但以下内容也很有用:

    • USER

    我们的 Jenkins 在用户 jenkins 下运行,因此也可以测试该值。

    工作信息

    这些在同一作业的构建中具有恒定值。

    • JOB_URL
    • JOB_NAME
    • JOB_BASE_NAME
    • JOB_DISPLAY_URL

    构建信息

    它们在同一构建中具有恒定值(即,对于不同的sh 调用)。

    • BUILD_URL
    • BUILD_TAG
    • RUN_CHANGES_DISPLAY
    • RUN_DISPLAY
    • BUILD_DISPLAY_NAME
    • BUILD_ID
    • BUILD_NUMBER

    节点信息

    这些与正在执行当前命令的节点有关。

    • JENKINS_HOME
    • JENKINS_NODE_COOKIE
    • NODE_LABELS
    • NODE_NAME

    特别

    这个随着每次构建而变化,可能会随着节点的变化而变化,甚至可能会随着 Jenkinsfile 配置而变化:

    • WORKSPACE

    杂项

    我不确定这些。它们肯定来自 Jenkins,但我不知道它们的生命周期是什么。

    • HUDSON_SERVER_COOKIE
    • JENKINS_SERVER_COOKIE
    • HUDSON_COOKIE

    最终考虑

    出于我自己的目的,我决定选择JENKINS_HOME。这个名字是 Jenkins 特有的,而且它似乎比 JENKINS_URL 更基础。虽然这并不意味着构建是由 Jenkins 运行的,但在这种情况下总是会设置它。我不介意误报,只要我没有得到误报。

    【讨论】:

    • 如果您包含执行检查的实际代码,那就太好了。
    • if (System.getenv("JENKINS_HOME") != null) {...
    猜你喜欢
    • 2011-05-04
    • 1970-01-01
    • 1970-01-01
    • 2018-12-18
    • 1970-01-01
    • 1970-01-01
    • 2020-07-02
    • 2023-04-05
    • 2010-12-26
    相关资源
    最近更新 更多