Reporting on multiple Selenium Webdriver job ran from Jenkins pipeline job - java

I have a pipeline job using Groovy script set up to run multiple tests in "parallel", but I am curious as to how to get the report(s) unified.
I am coding my Selenium tests in Java and using TestNG and Maven.
When I look at the report in target/surefire-reports, the only thing there is the "last" test ran of "suite".
How can I get a report that combines all of the tests within the Pipeline parallel job?
Example Groovy code:
node() {
try {
parallel 'exampleScripts':{
node(){
stage('ExampleScripts') {
def mvnHome
mvnHome = tool 'MAVEN_HOME'
env.JAVA_HOME = tool 'JDK-1.8'
bat(/"${mvnHome}\bin\mvn" -f "C:\workspace\Company\pom.xml" test -DsuiteXmlFile=ExampleScripts.xml -DenvironmentParam="$ENVIRONMENTPARAM" -DbrowserParam="$BROWSERPARAM" -DdebugParam="false"/)
} // end stage
} // end node
}, // end parallel
'exampleScripts2':{
node(){
stage('ExampleScripts2') {
def mvnHome
mvnHome = tool 'MAVEN_HOME'
env.JAVA_HOME = tool 'JDK-1.8'
bat(/"${mvnHome}\bin\mvn" -f "C:\workspace\Company\pom.xml" test -DsuiteXmlFile=ExampleScripts2.xml -DenvironmentParam="$ENVIRONMENTPARAM" -DbrowserParam="$BROWSERPARAM" -DdebugParam="false"/)
} // end stage
} // end node
step([$class: 'Publisher', reportFilenamePattern: 'C:/workspace/Company/target/surefire-reports/testng-results.xml'])
} // end parallel
There is a little more to this code after this in terms of emailing the test runner the result of the test and such.
This works great, other than the reporting aspect.

I prefer to use ExtentReports because it has a ExtentX server that allows to you report on multiple different test reports.
I used to use ReportNG but development on that stalled and so I don't recommend it any more. It doesn't allow you combine reports anyway.
Other than that, you could use CouchBase or similar JSON database to store test results and then generate your own report from that information.

Related

How to parallelize a Jenkins job?

I want to speed up the Jenkins job through parallelizing the test stages. The idea is to move each test stage to a separate node. What I've found is the parallel keyword. When I used this I ran into several problems:
The timing seems to be different. I had to adapt several tests.
Mocking seems to have issues in parallel mode.
For me it seems that the parallel stages are running on the same machine/node. Is there an opportunity to force the different stages to run on different nodes so that they don't influence each other?
One of the errors I get:
org.mockito.exceptions.misusing.UnfinishedMockingSessionException:
Unfinished mocking session detected.
Previous MockitoSession was not concluded with 'finishMocking()'.
For examples of correct usage see javadoc for MockitoSession class.
The Jenkins file:
pipeline {
options {
timeout(time: 120, unit: 'MINUTES')
buildDiscarder(logRotator(numToKeepStr: env.BRANCH_NAME == 'master' ? '30' : '5'))
skipDefaultCheckout()
}
agent {
label 'win10'
}
stages {
stage('cleanWs and checkoutCode') {
steps {
cleanWs()
script {
checkoutCode()
}
}
}
stage('build') {
steps {
bat 'gradlew showJavaVersion'
bat 'gradlew printVersion'
bat 'gradlew compileKotlin compileTestKotlin compileJava compileTestJava compileIntTestJava --parallel'
bat 'git status'
}
}
stage('tests') {
parallel {
stage("unit tests without ui") {
environment {
// give each build testing its own random port
BDP_HTTP_MOCK_PORT = 0
}
steps {
bat 'gradlew test -x :ui:test -x :bdp-ui:test -x :bdp-mock:test -P headless=true -P maxParallelIntegrationTests=3 -P os=win --parallel'
}
}
stage("mock tests") {
environment {
// give each build testing its own random port
BDP_HTTP_MOCK_PORT = 0
}
steps {
bat 'gradlew :bdp-mock:test -P headless=true -P maxParallelIntegrationTests=3 -P os=win --parallel'
}
}
stage("unit tests with ui") {
environment {
// give each build testing its own random port
BDP_HTTP_MOCK_PORT = 0
}
steps {
bat 'gradlew :ui:test :bdp-ui:test -P headless=true -P maxParallelIntegrationTests=3 -P os=win --parallel'
}
}
} // parallel
} // stage('tests')
}
}
Several ways of fixing this:
Use only a single slot on the test machines:
Pros: Very simple, foolproof way of avoiding interference between tests
Cons: Using a single slot might be wasteful if the machine could actually handle more
use locks, make sure you have the NODE_NAME be part of the lock's name
Pros: Fine-grained control over which parts of the pipeline need locking
Cons: locks won't influence where the stage will be scheduled, just make processes wait who want the lock
Apply a different scheduling strategy, for example Least Load, or round robbin. This will distribute load better and make clashes less likely.
Pros: Better load balancing
Cons: Doesn't actually prevent clashes
In my opinion, I would say a combination of using locks, and changing the scheduler, is the right way to do this (unless someone comes up with a better way I don't know). Locks guarantee that no tests will interfere, and round-robbin scheduling / Least Load will make it less likely a process needs to wait for the lock to be released.

jenkins pipeline using java.io.file always references the master

I have a Jenkins pipeline;
#Library('sharedLib#master')
import org.foo.point
pipeline {
agent { label 'slaveone' }
// agent { label 'master' }
stages {
stage('Data Build'){
steps{
script{
def Point = new point()
Point.hello("mememe")
}
}
}
}
}
which runs a small bit of code in a library called 'jenkins-shared-library/src/sharedLib';
package org.foo
import java.io.File
class point{
def hello(name){
File saveFile = new File("c:/temp/jenkins_log.txt")
saveFile.write "hello"
}
}
It runs fine on both 'master' and 'slaveone', but in both cases the 'jenkins_log.txt' file appears on the master. The log file contains this;
Running on slaveone in d:\Jenkins_WorkDir\workspace\mypipeline
How is this code running on slaveone and writing files to master?
Edit: I should also mention that this is my third attempt at doing this. The first one was with Groovy code direct in the pipeline, and the second was using a 'def' type call in the vars directory. Both produced the same behaviour, seemingly oblivious to the agent it was being run on.
I think everything inside the script runs on master, but here I found a workaround: Jenkins Declarative Pipeline, run groovy script on slave agent
Jenkins stores all logs on master only, that's why you cannot find any log on nodes.

How to debug the selenium java code in eclipse when scripting testcases with large number of test steps

How to perform dry run or debug my selenium java code in Eclipse? If am writing script for the testcase consisting 25 steps , my script failed at 21st step. So I am adjusting my script at 21st step, for this do i need rerun from first that is all the 20 steps on each time adjusting the script ?
Please help me.
Thanks in advance!!!
Yes, if your steps are connected you will have to run from the beginning every time. That is why it is recommended to keep test cases for automation small and independent, simply because it is hard and costly to maintain and make the really stable. As a suggestion try to split it into multiple independent test cases.
For example, if your test case looks like
action 1:
check 1
action 2:
check 2
action 3:
check 3
You can have 3 automation tests looking like (pseudo code):
Test 1.
beforeTest1() {
makeSystemForTest1();
}
test1() {
action1();
check1();
}
Test 2.
beforeTest2() {
makeSystemForTest2();
}
test2() {
action2();
check2();
}
Test 3.
beforeTest3() {
makeSystemForTest3();
}
test3() {
action3();
check3();
}

count of executors in Jenkins cluster

I have Jenkins cluster, has 1-Master with 2-Executor and 1-Agent with 2-Executor and now how to get the total number of executors in my Jenkins cluster using java or groovy script?
If you have access to the script console, you can run something like this:
final jenkins = Jenkins.instance
jenkins.computers.inject(0) { acc, item ->
acc + item.numExecutors
}
If you are running this in a sandboxed pipeline, you will have to have the methods whitelisted by an administrator in the In-Process Script Approval (or through a plugin using whitelists) at http://jenkinsUrl/scriptApproval/. You won't be able to use inject right now because of JENKINS-26481, but your pipeline script might look like:
final jenkins = Jenkins.instance
int executorCount = 0
for (def computer in jenkins.computers) {
executorCount += computer.numExecutors
}
// Rest of pipeline
If your pipeline does not run in sandbox, you may have access to those objects without whitelisting.

Jenkins: Is there any API to see test reports remotely?

I'm using jenkins as CI tool. I used restful api to build a job remotely but I don't know how to get test result remotely as well.
I can't be more thankful if anybody know a solution
Use the XML or Json API. At most pages on Jenkins you can add /api/ to the url and get data in xml, json and similar formats. So for a job you can go to <Jenkins URL>/job/<Job Name>/api/xml and get informaiton about the job, builds, etc. For a build you can go to <Jenkins URL>/job/<Job Name>/<build number>/api/xml and you will get a summary for the build. Note that you can use the latestXXXBuild in order to get the latest successful, stable, failing, complete build, like this; <Jenkins URL>/job/<Job Name>/lastCompletedBuild/api/xml.
Additionally if youre using any plugin which publishes test results to the build, then for a given job you can go to <Jenkins URL>/job/<Job Name>/lastCompletedBuild/testReport/api/xml and you will get an xml report with results.
There is a lot more to it, you can control what is exported with the tree parameter and depth parameter. For a summary go to <Jenkins URL>/api/
Well, if you are using a jenkins shared library or decided to permit the security exceptions (a less good approach) then you can access them via a job and send them out to whatever you like - push vs pull
def getCurrentBuildFailedTests() {
def failedTests = []
def build = currentBuild.build()
def action = build.getActions(hudson.tasks.junit.TestResultAction.class)
if (action) {
def failures = build.getAction(hudson.tasks.junit.TestResultAction.class).getFailedTests()
println "${failures.size()} Test Results Found"
for (def failure in failures) {
failedTests.add(['name': failure.name, 'url': failure.url, 'details': failure.errorDetails])
}
}
return failedTests
}

Categories

Resources