13

I'm testing Jenkins to see if it will fit our build and testing framework. I found that Jenkins and its available plugins fit most of our needs. Except that I can't seem to find help on how to do one particular type of task.

We are creating application for embedded devices. We have 100s of tests that need to be run on these devices. If we run all the tests on one device after a build then it will take several hours to get the results. However, if we run the tests on 100 of the devices in parallel then we can get results in much shorter time.

All the tests will have very similar starting point. A test script is called with IP address of device to run the test on and user name/pw. The script would do the necessary test on the device and report back pass/fail for each test item.

I think the long/painful way of doing this is writing 100 jobs in Jenkins, each will be a different test script directly (with above parameters) and run these in parallel using available plugins. However, maintaining all these jobs will be very difficult in the long run.

So, the better way to do this would be to create a Job (let's call it child_tester) that can take parameters such as: test script name, IP address of device, user name/pw, etc. Then use another job (let's call it mother_tester) to call child_tester job 100 times with different IP addresses and run them in parallel. I would need some way of accumulating all the test results of each individual run of the child_tester jobs and report them back to mother_tester.

My question is there a plugin or any way of accomplishing this in Jenkins? I have looked into the information of the plugins called "Build Flow", "Parallel Test Executor", and "Parameterized Trigger". However, they don't seem to fit my needs.

Alex Kulinkovich
  • 4,408
  • 15
  • 46
  • 50
Ash
  • 133
  • 1
  • 1
  • 6
  • In case of someone needs, I similar problem recently. [the answer is here](https://stackoverflow.com/a/66366599/2069549) – Thiago Feb 25 '21 at 10:28

2 Answers2

15

I understand you've looked into the Build Flow plugin, but I'm not sure why you've dismissed it. Perhaps you can point out the holes in my proposal.

Assuming you have enough executors in your system to run jobs in parallel, I think that the Build Flow plugin and Build Flow Test Aggregator plugin can do what you want.

  • The Build Flow plugin supports running jobs in parallel. I don't see any reason why Build Flow could not schedule your "child" job to run in parallel with different parameters.

  • The Build Flow Test Aggregator grabs test results from the scheduled builds of a Build Flow job, so your "child" job will need to publish its own test results.

  • You will need to configure your "child" job so that it can run in parallel by checking the "Execute concurrent builds if necessary" in the job configuration.

  • Whatever set of slaves provide the connection to the embedded devices will need enough executors to run your jobs in parallel.


Update: with the simple Build Flow definition:

parallel (
  { build("dbacher flow child", VALUE: 1) },
  { build("dbacher flow child", VALUE: 2) },
  { build("dbacher flow child", VALUE: 3) },
  { build("dbacher flow child", VALUE: 4) }
)

I get the output:

parallel {
    Schedule job dbacher flow child
    Schedule job dbacher flow child
    Schedule job dbacher flow child
    Schedule job dbacher flow child
    Build dbacher flow child #5 started
    Build dbacher flow child #6 started
    Build dbacher flow child #7 started
    Build dbacher flow child #8 started
    dbacher flow child #6 completed 
    dbacher flow child #7 completed 
    dbacher flow child #5 completed 
    dbacher flow child #8 completed 
}

The job history shows that all four jobs are scheduled within seconds of each other. But the job build step contains an artificial delay (sleep) that would prevent any single build from completing that quickly.


Update 2: Here is an example of generating the list of parallel tasks dynamically from another data structure:

// create a closure for the deploy job for each server 
def paramValues = (1..4)
def testJobs = [] 
for (param in paramValues) { 
  def jobParams = [VALUE: param] 
  def testJob = { 
    // call build 
    build(jobParams, "dbacher flow child") 
  } 
  println jobParams
  testJobs.add(testJob) 
} 

parallel(testJobs)

The list passed to parallel is a list of closures that call the build with unique parameters. I had to make sure to define the job parameters outside of the closure function to ensure the jobs would be scheduled separately.

I cribbed the syntax from another answer and this thread on the Jenkins mailing list.

Community
  • 1
  • 1
Dave Bacher
  • 15,652
  • 3
  • 63
  • 86
  • The build flow plug in does not work when the same job name is run in parallel. For example, my build flow looks like this: parallel ( {build ("FreestyleTest1")}, {build ("FreestyleTest1")} ) However, in this case the output looks like: parallel { Schedule job FreestyleTest1 Schedule job FreestyleTest1 Build FreestyleTest1 #29 started Build FreestyleTest1 #29 started FreestyleTest1 #29 completed FreestyleTest1 #29 completed } The job runs only once. If I were to change one of the jobs to another one, then they both run in parallel. – Ash Feb 24 '15 at 23:22
  • @Ash, Interesting. In Jenkins 1.580.2 with Build Flow 0.16, I can schedule the same child job with different parameters 4 times and the child job runs 4 separate times in parallel. – Dave Bacher Feb 25 '15 at 00:08
  • Thank you for the example and details. I found out that if i provide different parameters/values to the child jobs then multiple child jobs are actually executed. It could be a plugin bug. However, jobs still do not run in parallel. Ex output: parallel { Schedule job FreestyleTest1 Schedule job FreestyleTest1 Build FreestyleTest1 #36 started FreestyleTest1 #36 completed Build FreestyleTest1 #37 started FreestyleTest1 #37 completed }.....Jenkins status board showed that 37 is waiting on 36 to finish, even though the node has more than 2 executors idling. – Ash Feb 25 '15 at 00:58
  • Oh also, I am running Jenkins 1.599 and Build Flow Plugin 0.17 – Ash Feb 25 '15 at 01:00
  • 2
    @Ash, can you verify that your Freestyle Test1 job is configured to "Execute concurrent builds"? It looks like the job is executed in parallel for me, so all I can do is guess at what's different for you. – Dave Bacher Feb 25 '15 at 01:18
  • That did it! Checking the concurrent build option and assigning different parameters allowed the two instances to run at the same time. Thank you. Now, next step is how can I call to run the child jobs in a loop with parameters passed to them rather than writing 100 lines of hard coded calls with fixed parameter values. The Build Flow plugin commands does not seem to have an options for looping. – Ash Feb 25 '15 at 02:03
  • @Ash the build flow definition language is Groovy, which definitely supports common data structures and iteration. – Dave Bacher Feb 25 '15 at 03:08
  • Thank you for the code reference. This worked very well! I can continue with my project. Thank you again! – Ash Feb 26 '15 at 22:39
  • @DaveBacher I am trying to configure in following way, where it should run bunch parallel test and then Individual job need to be executed, but i only see parallel jobs are run. parallel ( // job 1, 2 and 3 will be scheduled in parallel. { build("job1") }, { build("job2") }, { build("job3") } ) // job4,5,6 will be triggered after jobs 1, 2 and 3 complete build("job4") build("job5") build("job6") But i see job4, job5 and job6 are not even triggered. Your help would be greatly appreciated. – Nick Dec 13 '16 at 18:41
  • I tried the same approach but getting this error. java.lang.IllegalArgumentException: Expected named arguments but got [org.jenkinsci.plugins.workflow.cps.CpsClosure2@598ac18e, org.jenkinsci.plugins.workflow.cps.CpsClosure2@238eaf6c, org.jenkinsci.plugins.workflow.cps.CpsClosure2@200d849d, org.jenkinsci.plugins.workflow.cps.CpsClosure2@6ddfc97b] – Bhavik Joshi Jan 06 '21 at 12:16
3

Please make sure that the number of executors in the Manage Jenkins -> Manage Nodes settings is more than the number of individual jobs in MultiJob project. By default I guess it is 2. Hence we need to increase it.