Skip to content

Attachment is not working when TestListener is in testng.xml #444

Closed

Description

@works-of-nestor

Attachment annotation and addAttachment helper method are not working when the TestListener class is added in testng.xml and not in a Test class - i.e.

  • Attachment works when this is added in each Test class: @Listeners({base.TestListener.class})
  • Attachment does not work when this is added in testng.xml:
<listeners>
     <listener class-name="base.TestListener" />
</listeners>

Steps to reproduce the behavior:

  1. Create a TestListener class that implements ITestListener
  2. Add either of these 2 methods:
private void takeScreenshot(WebDriver driver) {
     Allure.addAttachment("Screenshot of failed step", new ByteArrayInputStream(((TakesScreenshot)driver).getScreenshotAs(OutputType.BYTES))); }

@Attachment(value = "Page screenshot", type = "image/png")
private byte[] saveScreenshot(WebDriver driver) {
     byte[] screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
     return screenshot; }
  1. Use the attachment method in onTestFailure as:
@Override
public void onTestFailure(ITestResult result) {
     Object testClass = result.getInstance();
     WebDriver driver = ((BaseTest) testClass).getDriver();
     if(driver instanceof WebDriver) {
          takeScreenshot(driver);}}
  1. Add listener tag in testng.xml
<listeners>
     <listener class-name="base.TestListener" />
</listeners>
  1. Right click on testng.xml then Run as > TestNG Suite

Expected behavior
Attachment is not added in a failed test step

Screenshots
Screenshot when @Listeners({base.TestListener.class}) is implemented
image

Screenshot when @Listeners({base.TestListener.class}) is NOT implemented
image

Environment:
IDE: Eclipse

Allure version 2.9.0
Test framework testng@7.1.0
Allure adaptor allure-testng@2.13.3
Generate report using allure-maven@2.10.0

Additional context
This issue is also encountered when running the pom.xml with goal as clean test site

Activity

  1. baev commented on May 22, 2020

    @baev
    Member

    Thats because of TestNG listeners order. Allure TestNG integration implements listener as well, so if Allure listener invoked first you'll get no attachment (as Allure test context will be closed before your custom listener execution). As far as I know there is no guarantee on listeners order for TestNG.

    At this point I can suggest you to use Allure Lifecycle listeners

    https://github.com/allure-framework/allure-java/tree/master/allure-java-commons/src/main/java/io/qameta/allure/listener

    https://github.com/allure-framework/allure-java/blob/master/allure-java-commons/src/main/java/io/qameta/allure/listener/TestLifecycleListener.java

    TestLifecycleListener.beforeTestStop hook will be invoked for each test result just before Allure context closes. So you'll be able to check the status of result and in case of failure add screenshot to it.

    PS Allure listeners can be added via Java SPI

  2. works-of-nestor commented on May 23, 2020

    @works-of-nestor
    Author

    Thanks for this prompt response. While I managed to implement the Allure TestLifecycleListener I can't seem to get the instance of my BaseTest that contains the WebDriver and therefore I can't take screenshot. Any idea how I can accomplish this as there is no getInstance() in io.qameta.allure.model.TestResult.

    image

    In the screenshot above of Debug view, it was mentioned in Labels the testClass involved but it returns a string.

    @SuppressWarnings("deprecation")
    	@Override
    	public void beforeTestStop(TestResult result) {
    		Object testClass = null;
    		for(Label label : result.getLabels()) {
    			if(label.getName().equalsIgnoreCase("testClass")) {
    				testClass = label.getValue();  //exception thrown here
    				break;
    			}
    		}
    		
    		WebDriver driver = ((BaseTest) testClass).getDriver();
    		if(result.getStatus().name().equalsIgnoreCase("FAILED")) {
    			if(driver instanceof WebDriver) {
    				takeScreenshot(driver);
    			}	
    		}
    	}
    
  3. baev commented on May 23, 2020

    @baev
    Member

    the best option would be to use ThreadLocal to store reference to WebDriver

  4. works-of-nestor commented on May 24, 2020

    @works-of-nestor
    Author

    I was able to attach screenshot now using ThreadLocal. Thank you.

  5. ZuhayrMerchant110 commented on Aug 9, 2023

    @ZuhayrMerchant110

    Can you guid me that how you use ThreadLocal to store current test's driver to get the screenshot? @works-of-nestor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions