title: In Gradle, how to set unique system property before each execution of JUnit test class?
body: <p>In the gradle script below, <code>maxParallelForks</code> and <code>forkEvery</code> will start a new process with a new JVM per Junit test class. <strong>Is there a way to give each test process/JVM/Junit class its own unique system property?</strong></p>
  
  <p>I tried an experiment where I passed a UUID value as a system property in the <code>beforeSuite</code> method.</p>
  
  <pre><code>apply plugin:'java'
  test {
      ignoreFailures = true
      maxParallelForks = 8
      forkEvery = 1
      systemProperty 'some.prop', 'value'
  
     beforeSuite { descriptor -&gt;
      logger.lifecycle("Before suite: " + descriptor)
      def theuuid = UUID.randomUUID().toString()
      println "beforeSuite uuid =" + theuuid
      systemProperty 'some.uuid', theuuid
     }
     beforeTest { descriptor -&gt;
        logger.lifecycle("Running test: " + descriptor)
     }
  }
  repositories {
      mavenCentral()
  }
  dependencies {
      testCompile 'junit:junit:4.12'
  }
  </code></pre>
  
  <p>The JUnit test classes, <code>LoginTest1</code> and <code>LoginTest2</code> print out the system property in a test method.</p>
  
  <pre><code>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 -&gt; " 
             + System.getProperty("some.prop"));
          System.out.println("LoginTest1: Testing Login some.uuid -&gt; " 
             + System.getProperty("some.uuid"));
  
      assertTrue(userName.equals("Gradle"));
      }
  }
  </code></pre>
  
  <hr>
  
  <pre><code>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 -&gt; " 
             + System.getProperty("some.prop"));
          System.out.println("LoginTest2: Testing Login some.uuid -&gt; " 
             + System.getProperty("some.uuid"));
  
      assertTrue(userName.equals("Gradle"));
          }
  }
  </code></pre>
  
  <hr>
  
  <p>As you can see from the gradle output below, the <code>beforeSuite</code> method is called before running individual JUnit test methods.  Both test classes get the same system property of <code>6a006689-474f-47d5-9649-a88c92b45095</code></p>
  
  <pre><code> $ gradle clean test
  
  &gt; 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)
  </code></pre>
  
  <hr>
  
  <p>JUnit test class output:</p>
  
  <pre><code>LoginTest1: Testing Login 
  LoginTest1: Testing Login some.prop -&gt; value
  LoginTest1: Testing Login some.uuid -&gt; 6a006689-474f-47d5-9649-a88c92b45095
  
  LoginTest2: Testing Login 
  LoginTest2: Testing Login some.prop -&gt; value
  LoginTest2: Testing Login some.uuid -&gt; 6a006689-474f-47d5-9649-a88c92b45095
  </code></pre>
  
  <p>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. <strong>Is there anything like a simple beforeClass method I could use?</strong></p>
  
  <hr>
  
  <p>In the debug log below,it looks like the Test Executors are given the jvm argument <code>-Dsome.uuid=6a006689-474f-47d5-9649-a88c92b45095</code> and that is used soley to create new JVMs (as per the <code>forkEvery</code> config). This makes me think that what I want to do is impossible in Gradle.</p>
  
  <pre><code>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'
  </code></pre>
  
  <h2>Update 8/2018</h2>
  
  <h2>The following solution does not work in Gradle 4.9 and greater</h2>
  
  <p>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.</p>
  
  <h2>Trying to solve by intercepting Test.copyTo(JavaForkOptions target)</h2>
  
  <p><strong><em>This code demonstrates lance-java 's suggestion and succeeds in answering my question.</em></strong> I have the following build.gradle script which uses MyTestTask to extend Test and add a unique value called <code>my_uuid</code>. Note that the build script must have forkEvery = 1 to ensure <code>copyTo</code> is called once per JUnit test:</p>
  
  <pre><code>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
  
          }
      }
  }
  </code></pre>
  
  <p>The Junit tests that are executed are trivial and simply print out System.getProperty("my_uuid") and System.getProperty("common_uuid").</p>
  
  <pre><code>&gt; 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 &gt; testUserName2 STANDARD_OUT
      LoginTest2.java: Testing Login !  &gt;&gt;---&gt; my_uuid=a7996c20-1085-4397-9e32-fd84467dcb45 common_uuid=eed1ee92-7805-4b8e-a74c-96218d1be6e1
  
  ch3.LoginTest1 &gt; testUserName1 STANDARD_OUT
      LoginTest1.java: Testing Login !  &gt;&gt;---&gt; my_uuid=69f6f347-71d0-4e5d-9fad-66bf4468fab3 common_uuid=eed1ee92-7805-4b8e-a74c-96218d1be6e1
  </code></pre>
  
  <p>The <code>task my_test</code> sets <code>common_uuid</code> in <code>doFirst</code>. The <code>MyTestTask.copyTo</code> method sets its own <code>my_uuid</code>.
  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 <code>my_uuid</code>.</p>