Java 如何计算与 Web 应用程序代码相关的 selenium 测试的代码覆盖率

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20904131/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 05:11:14  来源:igfitidea点击:

How to calculate code coverage of selenium tests with respect to web application code

javajavascriptseleniumcode-coveragejacoco

提问by Vigneshwaran

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 .

我需要将我的 selenium 测试的代码覆盖率捕获到所覆盖的服务器代码(Web 应用程序源代码)中的源代码量。

For example the tests for login functionality should capture the amount of code covered in web application for the login function.

例如,登录功能的测试应该捕获 Web 应用程序中用于登录功能的代码量。

Else need to know which package or class it has touched in web application code for a scenario done . Eg a login

否则需要知道它在 web 应用程序代码中为完成的场景触及了哪个包或类。例如登录

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 .

我找不到合适的解决方案,虽然我开始了解 Jacoco 代码覆盖工具并使用 Jacoco Jenkins 插件尝试了一些示例,但没有成功。

I am not aware of the possiblity. Please provide me a suggestion on how to achieve this , Thanks in advance

我不知道这种可能性。请为我提供有关如何实现这一目标的建议,提前致谢

回答by Bobby Marinoff

Blanket can work.

毯子可以工作。

This is a JavaScript library.

这是一个 JavaScript 库。

You annotate the imports in your HTML page with the 'data-cover' attribute:

您可以使用 'data-cover' 属性在 HTML 页面中注释导入:

<script src="sourceScript.js" data-cover></script>

...and blanket replaces your JS files with an annotated copies which report statistics to itself.

...和毯子用带注释的副本替换您的 JS 文件,这些副本向自己报告统计信息。

The non-trivial step is getting the code-coverage statistics from blanket, but if I am not mistaken Selenium has an interface that allows you to execute JavaScript functions in the browser engine. The API is here:

重要的一步是从毯子上获取代码覆盖率统计信息,但如果我没记错的话,Selenium 有一个接口,允许您在浏览器引擎中执行 JavaScript 函数。API 在这里:

https://github.com/alex-seville/blanket/blob/master/docs/advanced_browser.md

https://github.com/alex-seville/blanket/blob/master/docs/advanced_browser.md

回答by AKS

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.

确保你这样做。请注意您使用的是 Gradle、Maven 还是 ANT。但是以下概念与任何构建系统都非常相似。

  1. You must be having a .war/.ear app artifact that you need to run behind Tomcat / similar.
    • You also need to make sure that you compiled your main code in debug mode, or jacoco will not be happy.
    • For ex: -g option in Java and similar debug option (if you are using groovy).
  1. 您必须有一个 .war/.ear 应用程序工件,需要在 Tomcat / 类似的后面运行。
    • 你还需要确保你在调试模式下编译了你的主代码,否则 jacoco 会不高兴。
    • 例如:Java 中的 -g 选项和类似的调试选项(如果您使用的是 groovy)。



tasks.withType(Compile) {
    options.debug = true
    options.compilerArgs = ["-g"]
}



  1. Lets say you have the .war and using Tomcat. Then while starting Tomcat.
    • In Tomcat start script, make sure you are telling Tomcat's JVM where's jacocoagent.jar file and passing other parameters. THIS is the MAIN missing point sometime we see (aka not attaching jacoco to target JVM's session and trying to get code coverage).
  1. 假设您拥有 .war 并使用 Tomcat。然后在启动Tomcat时。
    • 在 Tomcat 启动脚本中,确保您告诉 Tomcat 的 JVM jacocoagent.jar 文件在哪里并传递其他参数。这是我们有时看到的主要缺失点(也就是没有将 jacoco 附加到目标 JVM 的会话并试图获得代码覆盖率)。

For ex: I start my Tomcat script with the following parameter passed to Tomcat (-Dxxxx=value way)

例如:我使用传递给 Tomcat 的以下参数启动我的 Tomcat 脚本(-Dxxxx=value 方式)

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 exportthe variable) to Tomcat/Target JVM's scope.

基本上,Tomcat 启动脚本会有 -Dparameter=value,您可以将上述参数(Linux/Unix导出变量)传递给 Tomcat/Target JVM 的作用域。

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

上面的参数行发送到 Tomcat 时,会将 JACOCO 代理 .jar 文件附加到“TARGET”(又名 Tomcat JVM)。在这里,您告诉 Tomcat 从您的工作区下名为“tomcat”的目录中查找 jacocoagent.jar 文件。它会在 build/jacoco/ST 文件夹下创建一个名为“jacocoST.exec”的 jacoco .exec 文件(也就是 Selenium 测试的 jacoco exec 文件)(我使用的是 Gradle,所以 Gradle 会在你运行构建/编译时创建“build”文件夹/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).

注意:这意味着,您不必在测试任务中指定 jacoco 部分(因为它会在您的 BUILD 系统的 JVM 中运行,无论您拥有的是 Gradle、Maven 还是 ANT)。

//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.
}
  1. 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 FIRSTneed 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".

  2. 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 destfileparameter but it'll still be 0 or some small size.

  3. 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).

  4. Run jacocoTestReport task and you'll see jacoco code coverage.

    • Make sure you specify where are your sources/classes for main code.
  1. 一旦您的 Tomcat 启动并运行,现在您可以运行 Selenium 测试。注意:--我在 Linux/Unix 机器上使用 Jenkins 并且“xvfb”插件非常方便,即现在我可以在 HEADLESS 模式下运行 Selenium GUI 测试,并且我不会在运行测试的机器上打扰任何用户在 GUI 测试运行时弹出测试页面。

    -如果你最终使用“ xvfb的”在詹金斯插件,你第一需要启动“的Xvfb,你正在运行测试服务器(的Linux / Unix)”服务。

    -- 如果您在 Windows 机器上运行非单元测试(又名集成/Selenium 等),那么您可以在运行测试时看到弹出的 GUI 测试。如果您不想看到弹出窗口,那么您的 Jenkins 实例可以将从属(您的 Windows 机器)进程作为服务运行(“安装为服务”)。如果你创建你的windows机器作为slave,当你在你的机器上运行JLNP安装时,你会看到Jenkins已经成功启动了一个slave进程的弹窗,点击File > Install as a service将在windows机器上运行你的slave作为“无头”。

  2. 当您的测试正在运行时,您会注意到这一次,jacoco 将根据您为destfile参数定义的值创建一个文件夹结构/exec 文件,但它仍然是 0 或一些小尺寸。

  3. 一旦您的 Selenium/非单元测试完成,您必须“停止”Tomcat/目标 JVM。这会将所有 jacoco 覆盖信息刷新到此 jacocoST.exec 文件(您希望 jacoco 创建的自定义文件)。-- 注意:如果您希望即时刷新 jacocoST.exec 文件(无需停止 Tomcat JVM/会话,那么您可以查看 jacoco 文档如何执行此操作,那里有一个主题说明了这一点,这样您的应用程序就可以继续运行,而不必停止您的应用程序/网络服务)。

  4. 运行 jacocoTestReport 任务,您将看到 jacoco 代码覆盖率。

    • 确保指定主代码的源/类在哪里。

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.

如果您仍然看到任何问题,请随时 ping 我。您还可以在这里看到我在 stackoverflow 上的一些关于我如何实现这一目标的帖子,并将相同的报道发布到 SonarQube。