ExtentReports generation from Cucumber JSON report using Maven plugin

NEW Posts – Generating Spark and Pdf Extent Report for “Rest Assured with Maven plugin” and “Rest Assured and Cucumber with Maven plugin”

Introduction

This article deals with generating ExtentReports reports for Cucumber-JVM using a Maven Plugin. The Cucumber JSON report is used as the basis for creating the reports. The plugin can be used to create Spark, JSON, PDF and HTML reports. The artifact supports JSON report created with Cucumber-JVM 4.3.0 and above.

IMPORTANT – ExtentReports has been updated to version 5, which has resulted in multiple reporters getting deprecated. Currently this supports only Spark and Json reports. Due to this, in the latest plugin version (2.x) only these reports will be generated, along with the custom PDF and HTML reports.. To work with ExtentReports version 4, use the 1.6.0 adapter version. Refer to the ‘POM Dependencies’ section for more details.

The plugin is independent of Cucumber version and switching to a new adapter will not be required for latest version. Also reports can be generated from the command line for existing json reports.

Articles for creating Extent Report using the Cucumber adapter plugin can be found at the following locations – Cucumber 7, Cucumber 6, Cucumber 5, Cucumber 4.

Source

The source code for the article is located here. The source code for plugin is located here. The artifact can be found in Maven at this location.

Cucumber JSON Formatter Setup

The JSON report needs to be generated which can be done by setting up the below setting on the Cucumber runner. The report folder and the name of the report can be customized as desired.

@CucumberOptions(plugin = { "json:target/json-report/cucumber.json"})

Plugin Configuration

The extentreports-cucumberjson-plugin declaration needs to be added to the build section of the POM. The plugin is executed in the post-integration-test phase. The cucumberJsonReportDirectory property defines the directory path of the JSON report created by the runner. This property is mandatory. The extentPropertiesDirectory property defines the directory path of the project extent.properties file. This property is optional. If this property is not defined, then the default extent.properties location is used. The displayAllHooks property determines if all hooks are to be displayed in the report. The default value is false and this property is optional. Extent reports by default only include hooks which include an attachment or write a message in the report. The strictCucumber6Behavior property determines if undefined step status are set to failed. The default value is true and this property is optional. This is only available in version 2.0.0 onwards.

<plugin>
	<groupId>tech.grasshopper</groupId>
	<artifactId>extentreports-cucumberjson-plugin</artifactId>
	<version>2.16.0</version>
	<executions>
		<execution>
			<id>report</id>
			<phase>post-integration-test</phase>
			<goals>
				<goal>extentreport</goal>
			</goals>
		</execution>
	</executions>
	<configuration>
		<cucumberJsonReportDirectory>${project.build.directory}/json-report</cucumberJsonReportDirectory>
		<extentPropertiesDirectory>${project.build.testResources[0].directory}</extentPropertiesDirectory>
                <displayAllHooks>false</displayAllHooks>
                <strictCucumber6Behavior>true</strictCucumber6Behavior>
	</configuration>
</plugin>

Use the plugin version 1.6.0 for working with ExtentReports version 4.

ExtentReport Settings

The extent.properties file which is located here, contains the default values for the start, out and screenshot settings. The project extent.properties file whose location is defined in the extentPropertiesDirectory property can be used to override these settings. This file can also include the config property, which defines the location of the extent-config.xml file. This can be used to override the default user interface settings of the reports.

Extent Pdf Reporter

The PDF reporter summarizes the test run results in a dashboard and other sections with feature, scenario and step details. The PDF report is enabled by default. Below is a image of the dashboard. The documentation for this feature is available in this article. A sample PDF report can be found here.

Ported HTML Extent Report

The original HTML Extent Reporter was deprecated in 4.1.3 and removed in 5.0.0. The HTML report available in the adapter is based on the same code base and is similar in appearance. The major changes are in the Freemarker template code which have been modified to work with the Extent Reports version 5. The report code can be found at this location. The HTML report is enabled by default.

Report Attachments

To add attachments, like screen images, two settings need to be added to the extent.properties. First property, named screenshot.dir, is the directory where the attachments are stored. Second is screenshot.rel.path, which is the relative path from the report file to the screenshot directory. In the below setting, the Spark report (named index.html by default) will navigate to the saved attachments by using the relative path setting.

extent.reporter.spark.out=test-output/SparkReport/

screenshot.dir=test-output/
screenshot.rel.path=../

A more expanded scenario could be storing the images in a folder named ‘screenshots’ and the reports generated in the ‘test-output’ folder. The ‘screenshots‘ and the ‘test-output‘ folders are at the same level. The report will need to step down two folder levels and then move to the required directory.

extent.reporter.spark.out=test-output/SparkReport/

screenshot.dir=screenshot/
screenshot.rel.path=../../screenshot/

Customized Report Name

To enable report folder name with date and\or time details, two settings need to be added to the extent.properties. These are basefolder.name and basefolder.datetimepattern. These will be merged to create the base folder name, inside which the reports will be generated. The basefolder.datetimepattern value should be a valid date time formatter pattern.

extent.reporter.spark.out=test-output/SparkReport/

screenshot.dir=test-output/
screenshot.rel.path=../

basefolder.name=reports
basefolder.datetimepattern=d-MMM-YY HH-mm-ss

With the above settings, a base folder with the name reports 10-Aug-20 10-25-50 will contain the reports. Screenshots if any, will be located inside the reports 10-Aug-20 10-25-50/test-output folder structure. Similarly the report will be created in the reports 10-Aug-20 10-25-50/test-output/SparkReport folder structure. The point to remember is that the generated folder name should be valid for the underlying file system.

When the basefolder settings are not provided, the reports and related files are generated without any additional folder.

POM Execution

The report can be generated by a Maven command which includes the post-integration phase like ‘mvn install‘ or similar.

CLI Execution

The report can also be generated from the command line by using the command ‘mvn extentreports-cucumberjson:extentreport‘.

68 thoughts on “ExtentReports generation from Cucumber JSON report using Maven plugin”

  1. Hi,
    I am trying to execute Cucumber Tests with Multiple runners in my TestNG suite xml files. I was able to generate both Spark and PDF report previously with ExtentReports Cucumber7 Adapter » 1.9.2 but when I run the tests for multiple runners, then PDF report is not generated.
    So I read in the threads that you mentioned that You should use the report generation plugin using JSON – https://ghauto.tech/2114/. So I have added the following dependency to my JSON
    https://mvnrepository.com/artifact/tech.grasshopper/extentreports-cucumberjson-plugin/2.15.0

    and in my POM.xml, I added the plugin configuration to my Maven profile where I am running the suite xml file with multiple runners

    Smoke

    org.apache.maven.plugins
    maven-surefire-plugin
    3.0.0-M7

    test-suites/smoke-tests.xml

    tech.grasshopper
    extentreports-cucumberjson-plugin
    2.15.0

    report
    post-integration-test

    extentreport

    ${project.build.directory}/cucumber
    false
    true

    I have tried executing the tests with mvn clean install -PSmoke but the report is not generated neither Spark nor PDF, but when I place the above plugin configuration outside of my Profile then the Spark, PDF and JSON reports are getting generated. But the issue is I need to generate the PDF report for multiple runners which is not working for me.

    Here is link to my POM.xml
    https://github.com/itkhanz/selenium-frameworks/blob/cucumber-BDD-OC/CucumberBDD-OC/pom.xml

    link to my test runner
    https://github.com/itkhanz/selenium-frameworks/blob/cucumber-BDD-OC/CucumberBDD-OC/src/test/java/framework/runners/BaseTestNGRunnerTest.java

    link to my suite xml
    https://github.com/itkhanz/selenium-frameworks/blob/cucumber-BDD-OC/CucumberBDD-OC/test-suites/smoke-tests.xml

    I even tried to comment the ExtentReports Cucumber7 Adapter » 1.9.2 plugin from test runner, and then execute the command mvn clean install -PSmoke but still it does not generate the PDF report.

    I have tried debigging for hours but I am stuck at this problem. Could you please look at this issue and help me solve this error. Thanks

    1. If you use the cucumberjson plugin you do NOT need to add the extentreports adapter in the runner. You need to only add the plugin setting to create the cucumber json file. I will look into the profile issue, though it seems very strange to me. Will get back to you.
      This issue of adapter multiple runners effecting report generation will be fixed in next release. I am currently testing the code.

      1. Thank you for quick reply. It would be great if we could use the adapter for multiple runners running cucumber tests in parallel without needing to use JSON plugin. Please update when the it is released.

        Also I actually already tried with removing the extentreports adapter in the runner, and using only the cucumber json plugin but it does not work for me with multiple runners when I run my tests parallely (from suite xml) with command:
        mvn clean install -PSmoke

        The JSON is getting generated in target folder:
        “json:target/cucumber/cucumber.json”

        and I set the path to JSON in POM.xml as
        ${project.build.directory}/cucumber
        It does not generate neither PDF nor Spark report. Could you have a look at my POM.xml and Test Runner (link in above comment) if I have configured the JSON plugin correctly?

  2. Hi Mounish,

    The first run and rerun failed scenarios are reported in one single JSON output. How can I get separate JSON output using adpater “com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter:”, so that I can merge it by removing failed scenarios at the end of running both test runner and rerun test runner.

    Thanks,
    Manjeet K

      1. Hi Mounish,

        Thanks for your reply.

        I am using Cucumber Json Plugin to produce the Json Output. Here is the plugin = { “json:target/json-report/cucumber.json”}).

        Once the JSON are produced from First run and Rerun, I want to merge using Matching criteria with Matching Scenario Test Strategy Name – passstatus. So that the combined report will produce Extent Spark HTML with failed scnearios replaced with rerun results.

        Thanks for your help!

        1. Got it, you are planning to use this tool – ‘Merging Extent Spark Reports’ (https://ghauto.tech/2882/). You need to use the Extent JSON report and NOT the Cucumber JSON report.
          To generate the Extent JSON report you need to use the adapter plugin. For more details search ‘Merging Rerun Reports’ in this article – https://ghauto.tech/2098/ for cucumber 6 (Same for cucumber 5 also).
          To create separate JSON reports without overwriting, simplest way is to change the ‘extent.reporter.json.out’ property in extent.properties file. Or u can pass the value from the maven command by using – mvn install -Dextent.reporter.json.out=test-output/Json/JsonReport.json” for the rerun execution.

          1. Hi Mounish,

            You got clearly what I am looking for.

            I need 2 JSONs – One from 1st test runner class (Regular run) and 2nd from rerun test runner class (This runs for failed scenarios by reading rerun.txt written by Test Regular Run) I achieved this by using “rerun:target/rerun.txt” in 1st test runner class.

            The problem I am facing is when I run the maven using “mvn clean test -Dsurefire.suiteXmlFiles=testng.xml,testngrerun.xml”, the plugin “”com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter:” is reading the extent.properties file before the start of the execution and the property ‘extent.reporter.json.out’ is unchanged through out the execution of both test runners. I tried to change the Properties between 1st Test runner and Rerun test runner but the adapter is not reading the properties file before executing rerun test runner, instead using the same properties that were read before 1st Test runner.

            Tired using different Suites also.

            Is there a way to make Extent Report Adapter to read the updated properties before every test runner class?

            Thanks,
            Manjeet K

            1. If both the runners are executed with the same maven command then only the initial properties are set. All runners for the execution share the same ExtentReport instance which is initialized in a static block. This ensures that multiple runners will generate a single report for a test run.
              Execute ONLY the regular runner with maven command and copy the reports into a separate location. Then execute the retry runner and you should get a new set of reports.

          2. Hi Mounish,

            I tried running separately the regular runner and rerun runnner. Now I could get the reports for both the runs. And merge is also working fine.

            Thank you for your help! This plugin is really awesome.

            Thank you,
            Manjeet K

  3. text/html embedded in cucumber feature step definition (scenario.attach(byte array, “text/html”, “name”)) not added in extent report

  4. text/html embedded in cucumber feature step-definition (scenario.attach(byte [] data, “text/html”, “name”)) is not added in extent report. I am using cucumber version 6.9.1 and 2.8.3 extentrepot-cucumberjson-plugin.
    Below warning are shown
    [WARNING] Mime type ‘text/html’ not supported.
    [WARNING] Skipping adding embedded file as filepath is empty for step – ‘step name’

    Could you please suggest how to embed custom html in extent report?
    Thanks,
    Santosh

  5. Is there is any way to generate an Extent report on Jenkins without any source code.

    Scenario :
    We copied several run JSON files to one location, and plan to generate Spark, PDF, and JSON reports from there. Any option there to generate.

      1. The workspace only has multiple JSON files. No source code or anything. Is it possible to generate Spark, PDF, and JSON reports with executing shell or any option?

        1. Refer to the end of the article, section named – ‘CLI Execution’. That should work for you.

          1. Note: The Jenkins workspace only has several *.json files, and no pom.xml or selenium codebase.

            It throws an error.
            mvn -s /apps/maven/conf/settings.xml -gs /apps/maven/conf/settings.xml extentreports-cucumberjson:extentreport
            FATAL: command execution failed
            java.io.IOException: error=2, No such file or directory
            at java.lang.UNIXProcess.forkAndExec(Native Method)
            at java.lang.UNIXProcess.(UNIXProcess.java:247)
            at java.lang.ProcessImpl.start(ProcessImpl.java:134)
            at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)

  6. Hi Team,
    While generating the PDF report i am getting below exception. Could anyone please correct me what configuration i am missing here. I am using below extent.property. Also I am using updated pdf-config.yaml and extent-config.xmlfile that is mentioned in this group.
    Exception:
    java.lang.NoSuchFieldError: Justify
    at org.vandeseer.easytable.drawing.cell.ParagraphCellDrawer.(ParagraphCellDrawer.java:27)
    at org.vandeseer.easytable.structure.cell.paragraph.ParagraphCell.createDefaultDrawer(ParagraphCell.java:42)
    at org.vandeseer.easytable.structure.cell.AbstractCell.getDrawer(AbstractCell.java:158)
    at org.vandeseer.easytable.TableDrawer.drawRow(TableDrawer.java:171)
    at org.vandeseer.easytable.TableDrawer.drawWithFunction(TableDrawer.java:153)
    at org.vandeseer.easytable.TableDrawer.lambda$drawPage$1(TableDrawer.java:83)
    at java.base/java.lang.Iterable.forEach(Iterable.java:75)
    at org.vandeseer.easytable.TableDrawer.drawPage(TableDrawer.java:82)
    at org.vandeseer.easytable.TableDrawer.draw(TableDrawer.java:78)
    at tech.grasshopper.pdf.chapter.detailed.DetailedRowComponent.display(DetailedRowComponent.java:90)
    at tech.grasshopper.pdf.chapter.detailed.DetailedPage.lambda$0(DetailedPage.java:42)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at tech.grasshopper.pdf.chapter.detailed.DetailedPage.createPage(DetailedPage.java:39)
    at tech.grasshopper.pdf.chapter.detailed.DetailedChapter.sendToPage(DetailedChapter.java:115)
    at tech.grasshopper.pdf.chapter.detailed.DetailedChapter.createAndSendPageData(DetailedChapter.java:83)
    at tech.grasshopper.pdf.chapter.detailed.DetailedChapter.createChapter(DetailedChapter.java:28)
    at tech.grasshopper.pdf.PDFCucumberReport.lambda$0(PDFCucumberReport.java:100)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at tech.grasshopper.pdf.PDFCucumberReport.createReport(PDFCucumberReport.java:100)
    at tech.grasshopper.pdf.extent.ExtentPDFCucumberReporter.flush(ExtentPDFCucumberReporter.java:66)
    at tech.grasshopper.pdf.extent.ExtentPDFCucumberReporter.access$1(ExtentPDFCucumberReporter.java:57)
    at tech.grasshopper.pdf.extent.ExtentPDFCucumberReporter$1.onNext(ExtentPDFCucumberReporter.java:42)
    at tech.grasshopper.pdf.extent.ExtentPDFCucumberReporter$1.onNext(ExtentPDFCucumberReporter.java:1)
    at io.reactivex.rxjava3.subjects.PublishSubject$PublishDisposable.onNext(PublishSubject.java:310)
    at io.reactivex.rxjava3.subjects.PublishSubject.onNext(PublishSubject.java:226)
    at com.aventstack.extentreports.ReactiveSubject.onFlush(ReactiveSubject.java:83)
    at com.aventstack.extentreports.AbstractProcessor.onFlush(AbstractProcessor.java:85)
    at com.aventstack.extentreports.ExtentReports.flush(ExtentReports.java:284)
    at com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter.finishReport(ExtentCucumberAdapter.java:296)
    at com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter.access$6(ExtentCucumberAdapter.java:295)
    at com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter$8.receive(ExtentCucumberAdapter.java:132)
    at com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter$8.receive(ExtentCucumberAdapter.java:1)
    at io.cucumber.core.eventbus.AbstractEventPublisher.send(AbstractEventPublisher.java:51)
    at io.cucumber.core.eventbus.AbstractEventBus.send(AbstractEventBus.java:12)
    at io.cucumber.core.runtime.CucumberExecutionContext.emitTestRunFinished(CucumberExecutionContext.java:93)
    at io.cucumber.core.runtime.CucumberExecutionContext.finishTestRun(CucumberExecutionContext.java:74)
    at io.cucumber.junit.Cucumber$RunCucumber.evaluate(Cucumber.java:236)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:768)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)

    extent.property:
    extent.reporter.spark.start=true
    extent.reporter.spark.out=test-output/SparkReport/Spark.html
    extent.reporter.spark.config=src/test/resources/extent-config.xml

    extent.reporter.spark.out=test-output/SparkReport/

    screenshot.dir=test-output/
    screenshot.rel.path=../
    extent.reporter.pdf.start=true
    extent.reporter.pdf.out=test output/PdfReport/ExtentPdf.pdf
    #basefolder.name=reports
    #basefolder.datetimepattern=d-MMM-YY HH-mm-ss
    extent.reporter.spark.vieworder=dashboard,test,category,exception,author,device,log

  7. I am getting below error

    Failed to execute goal on project [ProjectName]: Could not resolve dependencies for project JavaCucumberProject:JavaCucumberProject:jar:0.0.1-SNAPSHOT: Could not find artifact com.github.ralfstuckert.pdfbox-layout:pdfbox2-layout:jar:1.0.0 in jitpack.io (https://jitpack.io) -> [Help 1]

    1. Please try with version 2.8.1, which removes this error. I have updated the article accordingly.

  8. Running feature files with “Examples: ” are failing

    [INFO] — extentreports-cucumberjson-plugin:2.7.0:extentreport (report) @ DashRetailBankBDD —
    [INFO] STARTED EXTENT REPORT GENERATION PLUGIN
    java.lang.StringIndexOutOfBoundsException: String index out of range: 1
    at java.lang.String.substring(String.java:1963)
    at tech.grasshopper.test.heirarchy.ExtentTestHeirarchy.lambda$parseTestNameFromId$2(ExtentTestHeirarchy.java:115)
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
    at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
    at tech.grasshopper.test.heirarchy.ExtentTestHeirarchy.parseTestNameFromId(ExtentTestHeirarchy.java:116)
    at tech.grasshopper.test.heirarchy.ExtentTestHeirarchy.createScenarioOutlineExtentNode(ExtentTestHeirarchy.java:101)
    at tech.grasshopper.test.heirarchy.ExtentTestHeirarchy.createScenarioExtentNode(ExtentTestHeirarchy.java:81)
    at tech.grasshopper.test.heirarchy.DefaultExtentTestHeirarchy.lambda$null$1(DefaultExtentTestHeirarchy.java:43)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at tech.grasshopper.test.heirarchy.DefaultExtentTestHeirarchy.lambda$createTestHeirarchy$2(DefaultExtentTestHeirarchy.java:41)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at tech.grasshopper.test.heirarchy.DefaultExtentTestHeirarchy.createTestHeirarchy(DefaultExtentTestHeirarchy.java:37)
    at tech.grasshopper.test.ExtentTestManager.initialize(ExtentTestManager.java:33)
    at tech.grasshopper.ExtentReportsCucumberPlugin.execute(ExtentReportsCucumberPlugin.java:71)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:210)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute(MavenCli.java:957)
    at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:289)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:193)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:347)
    [ERROR] STOPPING EXTENT REPORT GENERATION – String index out of range: 1

    1. Hi, Can u provide the “id” from the generated json file for the relevant scenario outline? It will be something like this – “id”: “scenario-and-scenario-outline;scenario-outline-row-\u003crow-num\u003e;odd-number-prefix;2”.
      Also the name of the Scenario Outline (in front of Scenario Outline:) in the feature file? Is this empty by any chance?

      This would make debugging lot easier. Thanks.

      1. I am able to reproduce this – looks like when the Scenario Outline is text is longer it errors out but works fine with the Scenario

        Please refer to the below feature file

        @both
        Feature: Scenario And Scenario Outline 2

        Background:
        Given ‘Hello’ background

        Scenario Outline: PCI-11166_TC-7805_Customer Migration- Account Info when customer is in bad status in app Portal
        Given Write a ‘given’ step with precondition in ”
        When Complete action in ‘when’ step in ”
        Then Validate the outcome in ‘then’ step in ”

        Examples: Odd number prefix
        | scenario_num | row_num |
        | Scenario Outline One | 300 |
        | Scenario Outline Two | 500 |

        Examples: Even number prefix
        | scenario_num | row_num |
        | Scenario Outline One | 400 |
        | Scenario Outline Two | 600 |

        Scenario: PCI-11166_TC-7805_Customer Migration- Account Info when customer is in bad status in app Portal
        Given Write a ‘given’ step with precondition in ‘Scenario 777’
        When Complete action in ‘when’ step in ‘Scenario 777’
        Then Validate the outcome in ‘then’ step in ‘Scenario 777’

        1. This one more String in Scenario Outline for referance
          Scenario Outline: PCI-11697-Testcase0DetailsPageSimplifiedUpdates & All Products

        2. Thanks for the info. I have fixed it. There was a parsing issue. I found another issue that is stopping the PDF report from being generated. Will try to fix these tomorrow and release a new version.

          1. Thanks for the quick response.

            Used 2.7.1 still failed but this time looks like something is missing.

            [INFO] — extentreports-cucumberjson-plugin:2.7.1:extentreport (report) @ extentreports-cucumberjson-report —
            [INFO] STARTED EXTENT REPORT GENERATION PLUGIN
            Apr 13, 2021 11:01:29 AM tech.grasshopper.pdf.extent.ExtentPDFCucumberReporter flush
            SEVERE: An exception occurred
            Cannot create property=summaryConfig for JavaBean=ReportConfig(passColor=05a167, failColor=ff00ff, skipColor=a89132, displayFeature=true, displayScenario=true, displayDetailed=true, summaryConfig=SummaryConfig(title=Cucumber Report, titleColor=null, dateColor=null, timeColor=null, dial=SummaryConfig.DialConfig(featureRanges=0.60 0.85, scenarioRanges=0.60 0.85, stepRanges=0.60 0.85, badColor=null, averageColor=null, goodColor=null), dataBackgroundColor=null), featureConfig=ReportConfig.FeatureConfig(featureCount=null, totalColor=null, durationColor=null, defaultCount=10), scenarioConfig=ReportConfig.ScenarioConfig(scenarioCount=null, totalColor=null, durationColor=null, defaultCount=10), detailedFeatureConfig=DetailedConfig.DetailedFeatureConfig(featureNameColor=null), detailedScenarioConfig=DetailedConfig.DetailedScenarioConfig(featureNameColor=null, scenarioNameColor=null, stepChartBarColor=null), detailedStepHookConfig=DetailedConfig.DetailedStepHookConfig(stepCount=null, stepTextColor=null, stepBackgroundColor=null, hookTextColor=null, hookBackgroundColor=null, durationColor=null, errorMsgColor=null, logMsgColor=null, defaultCount=15))
            in ‘reader’, line 1, column 1:
            passColor: 05a167
            ^
            Cannot create property=startTimeColor for JavaBean=SummaryConfig(title=Grasshopper PDF Report, titleColor=FF0000, dateColor=969696, timeColor=null, dial=SummaryConfig.DialConfig(featureRanges=0.60 0.85, scenarioRanges=0.60 0.85, stepRanges=0.60 0.85, badColor=null, averageColor=null, goodColor=null), dataBackgroundColor=4F0CC8)
            in ‘reader’, line 9, column 4:
            title: Grasshopper PDF Report
            ^
            Unable to find property ‘startTimeColor’ on class: tech.grasshopper.pdf.config.SummaryConfig
            in ‘reader’, line 13, column 20:
            startTimeColor: 000000
            ^

            in ‘reader’, line 9, column 4:
            title: Grasshopper PDF Report
            ^

            at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.constructJavaBean2ndStep(Constructor.java:291)
            at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.construct(Constructor.java:172)
            at org.yaml.snakeyaml.constructor.Constructor$ConstructYamlObject.construct(Constructor.java:332)
            at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:230)
            at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:220)
            at org.yaml.snakeyaml.constructor.BaseConstructor.constructDocument(BaseConstructor.java:174)
            at org.yaml.snakeyaml.constructor.BaseConstructor.getSingleData(BaseConstructor.java:158)
            at org.yaml.snakeyaml.Yaml.loadFromReader(Yaml.java:490)
            at org.yaml.snakeyaml.Yaml.load(Yaml.java:429)
            at tech.grasshopper.pdf.PDFCucumberReport.collectReportConfiguration(PDFCucumberReport.java:65)
            at tech.grasshopper.pdf.PDFCucumberReport.(PDFCucumberReport.java:49)
            at tech.grasshopper.pdf.extent.ExtentPDFCucumberReporter.flush(ExtentPDFCucumberReporter.java:68)
            at tech.grasshopper.pdf.extent.ExtentPDFCucumberReporter.access$1(ExtentPDFCucumberReporter.java:60)
            at tech.grasshopper.pdf.extent.ExtentPDFCucumberReporter$1.onNext(ExtentPDFCucumberReporter.java:45)
            at tech.grasshopper.pdf.extent.ExtentPDFCucumberReporter$1.onNext(ExtentPDFCucumberReporter.java:1)
            at io.reactivex.rxjava3.subjects.PublishSubject$PublishDisposable.onNext(PublishSubject.java:310)
            at io.reactivex.rxjava3.subjects.PublishSubject.onNext(PublishSubject.java:226)
            at com.aventstack.extentreports.ReactiveSubject.onFlush(ReactiveSubject.java:83)
            at com.aventstack.extentreports.AbstractProcessor.onFlush(AbstractProcessor.java:85)
            at com.aventstack.extentreports.ExtentReports.flush(ExtentReports.java:284)
            at tech.grasshopper.test.ExtentTestManager.flushToReporters(ExtentTestManager.java:42)
            at tech.grasshopper.ExtentReportsCucumberPlugin.execute(ExtentReportsCucumberPlugin.java:72)

  9. I am getting error for dependency resolution when I add this plugin
    Cannot resolve tech.grasshopper:extentreports-cucumberjson-plugin:2.7.0

  10. @mounish
    File path :
    target/JsonReport/Cucumber.json
    src/test/resources/extent.properties

    We update the POM.xml like below.

    tech.grasshopper
    extentreports-cucumberjson-plugin
    2.7.0

    report
    post-integration-test

    extentreport

    ${project.build.directory}/JsonReport/
    ${project.basedir}/src/test/resources/
    false
    true

    and the runner file as below.
    plugin = {
    “json:target/JsonReport/Cucumber.json”,
    “rerun:target/failedRun.txt”
    },

    and PDF and Spark reports are not generating.

    1. is the json file generated? The POM is not clear as the comments section removes the xml tags. Can u upload a minimum version to a git repo?

      1. Two files were generated.
        target/JsonReport/cucumber.json
        target/JsonReport/recucumber.json

        And the configuration part of the plugin like below.
        ${project.build.directory}/JsonReport
        ${project.basedir}/src/test/resources/

        When I run the execution I’m not able to generate spark to pdf reports.

  11. Hello,
    It is an excellent reporting tool.
    But I am facing an unique issue , while integrating with Jenkins Report.
    The attached screenshot is showing as blank is Jenkins report.
    I tried changing the location of the screenshot folder . But it is still giving the error of “http://localhost:8080/job/screenshot/embedded1.png” unable to find.
    But the file is located at “http://localhost:8080/job/USM_Dashboard_Production/ws/screenshot/embedded1.png”

  12. Hi Mounish,

    I was using the above article to setup extent reports and I have done exactly the way it was given in your example code. But I have failure as below –

    [INFO] STARTED EXTENT REPORT GENERATION PLUGIN
    java.lang.NullPointerException
    at tech.grasshopper.json.deserializer.EmbeddedDeserializer.deserialize(EmbeddedDeserializer.java:27)
    at tech.grasshopper.json.deserializer.EmbeddedDeserializer.deserialize(EmbeddedDeserializer.java:13)
    at com.google.gson.internal.bind.TreeTypeAdapter.read(TreeTypeAdapter.java:69)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41)
    at com.google.gson.internal.bind.ArrayTypeAdapter.read(ArrayTypeAdapter.java:72)
    at com.google.gson.Gson.fromJson(Gson.java:932)
    at com.google.gson.Gson.fromJson(Gson.java:870)
    at tech.grasshopper.json.JsonFileConverter.retrieveFeaturesFromReport(JsonFileConverter.java:48)
    at tech.grasshopper.ExtentReportsCucumberPlugin.execute(ExtentReportsCucumberPlugin.java:65)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:210)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute(MavenCli.java:957)
    at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:289)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:193)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:347)
    [ERROR] STOPPING EXTENT REPORT GENERATION – null

      1. Hi Mounish,
        Thank you for fixing it. I was able to progress and its working fine for me. Really appreciate your effort.

        Now I am having another issue. I have to now incorporate your extentreport plugin within my organization using nexus which pulls from Maven. Now there are 1 dependency which I am not able to access through nexus – com/github/ralfstuckert/pdfbox-layout/pdfbox2-layout/1.0.0/pdfbox2-layout-1.0.0.pom

        [INFO] Downloading from : https://repo.maven.apache.org/maven2/com/github/ralfstuckert/pdfbox-layout/pdfbox2-layout/1.0.0/pdfbox2-layout-1.0.0.pom
        [INFO] Downloading from : https://jitpack.io/com/github/ralfstuckert/pdfbox-layout/pdfbox2-layout/1.0.0/pdfbox2-layout-1.0.0.pom

        Can you please guide me how this can be resolved?

        Thanks again and appreciate for your time.

      2. Failed to execute goal tech.grasshopper:extentreports-cucumberjson-plugin:2.6.0:extentreport (report) on project austractestUI: Execution report of goal tech.grasshopper:extentreports-cucumberjson-plugin:2.6.0:extentreport failed: Plugin tech.grasshopper:extentreports-cucumberjson-plugin:2.6.0 or one of its dependencies could not be resolved: Failed to collect dependencies at tech.grasshopper:extentreports-cucumberjson-plugin:jar:2.6.0 -> tech.grasshopper:extent-pdf-report:jar:1.4.0 -> tech.grasshopper:cucumber-pdf-report:jar:1.6.0 -> com.github.ralfstuckert.pdfbox-layout:pdfbox2-layout:jar:1.0.0: Failed to read artifact descriptor for com.github.ralfstuckert.pdfbox-layout:pdfbox2-layout:jar:1.0.0: Could not transfer artifact com.github.ralfstuckert.pdfbox-layout:pdfbox2-layout:pom:1.0.0 from/to central (https://repo.maven.apache.org/maven2): No route to host (Host unreachable)

          1. Thanks Mounish. Again appreciate your time and efforts. I will get in touch with network guys regarding this

          2. Thanks Mounish. I will ask network team to download these particular jar only to nexus.
            Are these the only ones that I would need –
            pdfbox2-layout-1.0.0.jar and pdfbox1-layout-1.0.0-sources.jar

            Also do you think in future versions of extent reports might change, so I should ask them to setup a proxy for jitpack.io, so anything can be accessed?

            1. The rest of the jars should be available in Maven central.
              Cannot commit on any future developments but currently working on improving the PDF report layouts. I only maintain the PDF report, the others are supported by the Extent team so cannot comment on them.

  13. I am also getting the following error:

    Start timestamp data of scenario is essential but is missing in json report. Plugin only generates report for Cucumber-JVM 4.3.0 and above. If Cucumber version is in the valid range, do submit an issue.

    Looking at my cucumber.json file there is no start_timestamp. I am using Cucumber version 6.8.0 via Maven dependency.

    Any ideas?

    Thanks, Bryan

  14. Not sure I understand the issue completely.

    1. U have an “Example:” keyword before the “Scenario Outline:”. What is the logic behind this?

    2. Can u clarify this statement – “Now when I run test and check report, I am not seeing Application Name is Scenario, all I see is “Validating login” is not displaying.”. Which report? Please explain.

    Can u open an issue in https://github.com/grasshopper7/extentreports-cucumberjson-plugin/issues with screenshots and the feature file? Thanks

  15. Hi Mounish,

    I am facing an issue while trying to use Scenario Outline.

    Example:
    Scenario Outline: Validating login
    Given User Opens
    When ..
    Then …

    Examples:
    |Application Name|
    |grasshopper1 |
    |grasshopper2 |
    |grasshopper3 |

    Now when I run test and check report, I am not seeing Application Name is Scenario, all I see is “Validating login” is not displaying.

    When I use scenario.getName() it gives full name including Application Name from Examples table.
    Could you please help.

    Thanks

  16. HI Team,

    Thanks for your lovely work!!

    I tried to integrate but it is giving below error:

    tech.grasshopper.exception.extentreportsCucumberPluginException:Starttimestamp data of scenario is essential but is missing in json report.

    I am using cucumber-testng 4.8.0 version.

    Not sure why it is not working.

    1. That is interesting. I will try it out with the version that u mentioned. Does your json file have the ‘start_timestamp’ key in it?

    2. Hi I just tried it with 4.8.0 and it worked. U can download the sample implementation and switch the version to 4.8.0 and try running it.

    3. I finally figured this out. It fails when a background is present and there are more than one scenario in the feature file. The background details in json report does not have a start timestamp. Fixed it. Thx

  17. Hi Mounish,

    How to write multiple scenario is single feature file?
    Before hook: Browser driver initialisation After Hook: Driver close
    If I used before hooks and after hook they will get called before each scenario but I do not want to execute that while writing single feature file with multiple scenario .
    How to achieve this?

    1. Cucumber does not have ‘before feature’ and ‘after feature’ hooks. But u can try using the plugin system which emits an event when feature is started and also when feature is finished. U can check the various formatter implementations for reference. Never tried to initialize driver using this style and its implications though. Else u can try a shareddriver which is initialized at the beginning and is closed when the JVM shuts down. https://github.com/grasshopper7/junitcuke4sharedwebdriver/blob/master/junitsharedwebdriver/src/test/java/driver/SharedDriver.java some details u can read here – https://ghauto.tech/732/.

  18. Excellent !! …..Big Thanks to you.
    I hope it will reduce the execution time and well though approach.
    Definitely, I am going to explore this.

Leave a Reply

Your email address will not be published. Required fields are marked *