How do I detect my test is running on a Jenkins environment?

10,275

Solution 1

Since they are easy to test for and passed to every program that gets executed by the build, I opted to base the check on environment variables.

Though rohit answer shows one way of setting variables on Jenkinsfile, I'd rather rely on things that Jenkins itself does, so I checked the environment variables set on my Jenkins jobs, and there's many options to pick from:

General Jenkins Information

These seem to be constant on a Jenkins instance.

  • HUDSON_URL
  • JENKINS_URL

Not Jenkins-specific, but the following is also useful:

  • USER

Our Jenkins runs under user jenkins, so testing that value is also a possibility.

Job Information

These have constant values across builds for the same job.

  • JOB_URL
  • JOB_NAME
  • JOB_BASE_NAME
  • JOB_DISPLAY_URL

Build Information

These have constant values across the same build (that is, for different sh invocations).

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

Node Information

These are related to the node on which the current command is being executed.

  • JENKINS_HOME
  • JENKINS_NODE_COOKIE
  • NODE_LABELS
  • NODE_NAME

Special

This one changes with each build, may change from node to node, and may even change with Jenkinsfile configuration:

  • WORKSPACE

Miscellaneous

I'm not sure about these. They are definitely from Jenkins, but I don't know what their lifecycle is.

  • HUDSON_SERVER_COOKIE
  • JENKINS_SERVER_COOKIE
  • HUDSON_COOKIE

Final Considerations

For my own purposes, I decided to go with JENKINS_HOME. The name is very Jenkins-specific, and it seems more fundamental than, say, JENKINS_URL. While it doesn't imply the build is being run by Jenkins, it will always be set in that case. I don't mind false positives, as long as I don't get false negatives.

Solution 2

Couple of ways you can achieve this:

  1. You can make you application accept arguments and then pass a TRUE/FALSE value indicating it is running from Jenkins or not.

  2. You can also read the system properties of os

e.g. System.getProperty("os.arch");

But this will not work if your Jenkins environment and your workspace are on the same machine

  1. You can just set an env variable in your pipeline(exists only in pipeline) and in the application you can read that value

Like so :

Pipeline- option1

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

                   sh "mvn test"
             }
        }

Pipeline- option2

     pipeline {
            stage('test'){ 

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

Application

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);

Hope it helps :)

Share:
10,275
Daniel C. Sobral
Author by

Daniel C. Sobral

I have been programming for more than 20 years now, starting with 8 bits computers, assembler and BASIC. My passion for languages meant that, by the time I entered college, I had already programmed for fun or profit in more than 20 languages, including odd ones like Forth, MUMPS and APL, as well as theoretically important ones like Lisp and Prolog. Some of my code ended up in FreeBSD, of which I was a committer for some years, while I got my masters degree in the field of distributed algorithms. I also contributed to Scala, with small amounts of code, some reasonable amount of documentation, and a couple of years of a lot of attention to the Scala questions on Stack Overflow.

Updated on June 11, 2022

Comments

  • Daniel C. Sobral
    Daniel C. Sobral almost 2 years

    I have a JUnit test using Assumption to skip the test if the developer's computer doesn't have the pre-requisite software for running it. Despite being "junit", it's an integration test. Something like this:

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

    However, at one point I realized the test had stopped running on the automated build on Jenkins, due to that assumption, and eventually a regression was introduced which the test was supposed to stop.

    To put in other words, the required software went missing from Jenkins slave environment, which caused the test to be skipped.

    The automated test is run by maven with the FailSafe plugin, on a Jenkins Pipeline build plan. How can I detect that my environment is Jenkins so that I can make the assumption condition more strict?

    That is, I want the condition to be something like this:

    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);
    

    Or even,

    @Test
    void testJenkinsEnvironment() {
        ...
        Assume.assumeTrue(isJenkinsBuild);
        Assert.assertTrue(isSoftwarePresent);
    }
    
    @Test
    void testFeature() {
        ...
        Assume.assumeTrue(isSoftwarePresent);
        ...
    }
    
  • Roland
    Roland over 4 years
    I would be great if you included the actual code that performed the check.
  • Roland
    Roland over 4 years
    if (System.getenv("JENKINS_HOME") != null) {...
  • Denis Howe
    Denis Howe about 2 years
    Great answer! Some of these are documented on jenkins.io/doc/book/pipeline/jenkinsfile/….