I have a requirement to capture the code coverage of my selenium tests to the amount of source code in the server code (web application source code) covered .
For example the tests for login functionality should capture the amount of code covered in web application for the login function.
Else need to know which package or class it has touched in web application code for a scenario done . Eg a login
I couldn't find a suitable solution , although i came to know about Jacoco code coverage tool and tried some samples with the use of Jacoco Jenkins plugin , but there is no success .
I am not aware of the possiblity. Please provide me a suggestion on how to achieve this , Thanks in advance
Make sure you do this. Note sure if you are using Gradle, Maven or ANT. But the following concept is very similar to any build system.
tasks.withType(Compile) {
options.debug = true
options.compilerArgs = ["-g"]
}
For ex: I start my Tomcat script with the following parameter passed to Tomcat (-Dxxxx=value way)
PROJ_EXTRA_JVM_OPTS=-javaagent:tomcat/jacocoagent.jar=destfile=build/jacoco/ST/jacocoST.exec,append=false
Basically, Tomcat start script would have -Dparameter=value, you can pass the above parameter (Linux/Unix export the variable) to Tomcat/Target JVM's scope.
The above parameter line when sent to Tomcat, will attach JACOCO agent .jar file to the "TARGET" (aka Tomcat JVM). Here you are telling Tomcat that go look for jacocoagent.jar file from a director called "tomcat" under your workspace. It's gonna create a jacoco .exec file named "jacocoST.exec" (aka jacoco exec file for Selenium Test) under build/jacoco/ST folder (I'm using Gradle so Gradle creates "build" folder anytime you run a build/compile/test/integrationTest/customSeleniumTaskThatYouMightHaveCreated).
NOTE: This means, that you DON'T have to specify jacoco section in the test task (as that'll run in your BUILD systems' JVM either Gradle or Maven or ANT whatever you have).
//We don't need jacoco for non-unit tests type of tasks as Jacoco won't be able to find any coverage if done this way. Jacoco agent file needs to be attached/visible to the TARGET's JVM (where you run your application via a .war / .ear etc).
jacoco {
// ... As Gradle runs Unit tests (while doing build), they run free, in the same JVM where Gradle runs the build so Unit test have visibility to the main classes in the same JVM (which Gradle is using to run the build). Thus, you can use jacoco section in Gradle for running unit tests. BUT,
// ... Don't use this section for running Integration, Acceptance, Selenium tests which run on a target JVM. Instead attach jacocoagent.jar and specify jacoco parameters to the target JVM.
}
Once you have your Tomcat up and running, now you run your Selenium tests. NOTE: -- I'm using Jenkins on Linux/Unix machine and "xvfb" plugin is very handy i.e. now I can run Selenium GUI tests in HEADLESS mode and I won't bug any user on a machine where the tests are running by popping up the tests pages while the GUI tests are running.
-- if you end up using "xvfb" plugin in Jenkins, you FIRST need to start "Xvfb" service on the server (Linux/Unix) where you are running the tests.
-- If you are running your non-units tests (aka Integration/Selenium etc) on a Windows machine, then you can see the GUI tests pop up when you run your tests. If you don't want to see the popup windows, then your Jenkins instance can run the slave (your windows machine) process as a service ("Install as a Service"). If you create your windows machine as a slave, when you run the JLNP installation on your machine, You'll see a popup that Jenkins has successfully started a slave process, clicking File > Install as a service will run your slave on a windows machine as "HEADLESS".
While your tests are running, you'll notice that this time, jacoco will create a folder structure/exec file as per your defined value for destfile parameter but it'll still be 0 or some small size.
Once your Selenium/non-unit tests are complete, you have to "STOP" Tomcat / target JVM. This will FLUSH all jacoco coverage info to this jacocoST.exec file (custom file that you wanted jacoco to create). -- Note: If you want jacocoST.exec file to be flushed on the fly (without requiring the Tomcat JVM/session to stop, then you can look into jacoco documentation how to do that, there is one topic there which tells about this, this way your application can continue to run and you dont have to stop your application/webservice).
Run jacocoTestReport task and you'll see jacoco code coverage.
for ex:
jacocoTestReport {
group = "Reporting"
description = "Generate Jacoco coverage reports after running tests."
ignoreFailures = true
//UT=is for Unit tests, IT=integrationTest, AT=acceptanceTest, ST=Selenium GUI tests.
//executionData = files('build/jacoco/UT/jacocoUT.exec')
//executionData = files('build/jacoco/IT/jacocoIT.exec')
//executionData = files('build/jacoco/UT/jacocoUT.exec', 'build/jacoco/IT/jacocoIT.exec')
//executionData = files(['build/jacoco/UT/jacocoUT.exec', 'build/jacoco/IT/jacocoIT.exec'])
//OR use the following way for all.
executionData = fileTree(dir: 'build/jacoco', include: '**/*.exec')
reports {
xml{
enabled true
//Following value is a file
destination "${buildDir}/reports/jacoco/xml/jacoco.xml"
}
csv.enabled false
html{
enabled true
//Following value is a folder
destination "${buildDir}/reports/jacoco/html"
}
}
//sourceDirectories = files(sourceSets.main.allJava.srcDirs)
sourceDirectories = files('src/java')
//sourceDirectories = files(['src/java','src/groovy'])
classDirectories = files('build/classes/main')
//------------------------------------------
//additionalSourceDirs = files(['test/java','test/groovy','src/java-test', 'src/groovy-test'])
//additionalSourceDirs += files('src/java-test')
}
Feel free to ping me if you still see any issues. You can also see few of my posts here on stackoverflow on how I achieved this and also publishing the same coverage to SonarQube.