问题
I"m trying to build selenium with extent report but i could not get the save screenshot function working because i cannot reference the WebDriver object in the ITestListener class. Below is my sample code:
Test Runner.java:
@Listeners({com.peterwkc.Listener.TestListener.class})
public class ChromeTestManager {
private WebDriverManager webDriverManager = new WebDriverManager();
private WebDriver driver;
private LoginPages loginPages;
private AdminPages adminPages;
@BeforeClass
//@Parameters({"browser"})
public void setupTest(/*String browser*/) throws MalformedURLException {
System.out.println("BeforeMethod is started. " + Thread.currentThread().getId());
// Set & Get ThreadLocal Driver with Browser
webDriverManager.createDriver("chrome");
driver = webDriverManager.getDriver();
// Pages Object Initialization
loginPages = PageFactory.initElements(driver, LoginPages.class);
logoutPages = PageFactory.initElements(driver, LogoutPages.class);
adminPages = PageFactory.initElements(driver, AdminPages.class);
}
@DataProvider(name = "loginCredentials")
public static Object[][] getLoginCredentials() {
return new Object [][] {{ "Admin123", "admin123" }, {"testUser", "test"}, {"test", "test"}};
}
@Test(groups= {"Login"}, description="Invalid Login", priority = 0, dataProvider = "loginCredentials", invocationCount = 3)
public void login_invalid(String username, String password) {
loginPages.login_invalid(driver, username, password);
}
}
TestListener.java public class TestListener implements ITestListener {
//Extent Report Declarations
private static ExtentReports extent = ExtentManager.createInstance();
private static ThreadLocal<ExtentTest> test = new ThreadLocal<>();
public TestListener() {
}
@Override
public synchronized void onTestFailure(ITestResult result) {
System.out.println((result.getMethod().getMethodName() + " failed!"));
test.get().fail("Exception Error : \n" + result.getThrowable());
/*String feature = getClass().getName();
String screenShot;
try {
screenShot = CaptureScreenshot.captureScreen(driver, CaptureScreenshot.generateFileName(feature));
test.get().addScreenCaptureFromPath(screenShot);
test.get().log(Status.FAIL, screenShot);
} catch (IOException ex) {
LogManager.logger.log(Level.INFO, "Exception: " + ex.getMessage());
}*/
}
}
Questions:
How to pass the WebDriver object from TestRunner.java to TestListener class?
How to save screenshot in extent report 3?
Anything wrong with my code?
please help, thanks in advance!
回答1:
Below are the steps to do this :
1 : Passing WebDriver object to Listener class
First create below method in ChromeTestManager class or at any another location from where you can call it, here suppose that it is present in ChromeTestManager class:
public static ITestContext setContext(ITestContext iTestContext, WebDriver driver) {
iTestContext.setAttribute("driver", driver);
return iTestContext;
}
It will set the driver object to the TestContext.
Now change your @BeforeClass setUp method to accept parameter ITestContext, below is the code :
public class ChromeTestManager {
private WebDriverManager webDriverManager = new WebDriverManager();
private WebDriver driver;
private LoginPages loginPages;
private AdminPages adminPages;
private static ITestContext context; // creating a ITestContext variable
@BeforeClass
//@Parameters({"browser"})
public void setupTest(ITestContext iTestContext) throws MalformedURLException {
System.out.println("BeforeMethod is started. " + Thread.currentThread().getId());
// Set & Get ThreadLocal Driver with Browser
webDriverManager.createDriver("chrome");
driver = webDriverManager.getDriver();
this.context = setContext(iTestContext, driver); // setting the driver into context
// Pages Object Initialization
loginPages = PageFactory.initElements(driver, LoginPages.class);
logoutPages = PageFactory.initElements(driver, LogoutPages.class);
adminPages = PageFactory.initElements(driver, AdminPages.class);
}
When you run this, it will run smoothly and will not produce an error (If you are thinking that how I will pass ITestcontext context, It is handled internally)
Now the driver has been added as an object to the ITestcontext ;
Now Accessing the driver in Listener :
@Override
public synchronized void onTestFailure(ITestResult result) {
WebDriver driver = (WebDriver) result.getTestContext().getAttribute("driver"); // here we are accessing the driver object that we added in Test class
}
2. Saving ScreenShot in extent report 3 (I am using dependency 3.1.5 in maven)
@Override
public synchronized void onTestFailure(ITestResult result) {
System.out.println("!!!!!!!!!!!!!!!!!!!! Test Failed !!!!!!!!!!!!!!!!!!!!");
WebDriver driver = (WebDriver) result.getTestContext().getAttribute("driver"); // accessing driver here
String feature = getClass().getName();
String screenShot;
try {
screenShot = CaptureScreenshot.captureScreen(driver, CaptureScreenshot.generateFileName(feature));
test.addScreenCaptureFromPath(screenShotPath); // I am assuming that the "screenShot" is fully qualified path with extension e.g "C:\Users\12345\Desktop\sfgfdh.PNG"
} catch (IOException ex) {
LogManager.logger.log(Level.INFO, "Exception: " + ex.getMessage());
}
}
3. Is there anything wrong with your code ?
No
You just need driver in Listener class and while adding screenshot in extent report , make sure that the path to screenshot is correct and is fully qualified path with extension.
Please let me know if you face an issue in this.
回答2:
First of all don't instantiate Your webDriver in @BeforeClass
, because this is called only once as annotation say before class, try using interface ITestListener
and using beforeInvocation
implementation for initialisation of WebDriver.
Second, You can't call PageFactory for all PageObjects at once, how do You think all 3 pages are initialised at once, this should be achieved in constructor for each page object, and when You init you page object (new Login) the elements are initialised as well, so this is not ok:
// Pages Object Initialization
loginPages = PageFactory.initElements(driver, LoginPages.class);
logoutPages = PageFactory.initElements(driver, LogoutPages.class);
adminPages = PageFactory.initElements(driver, AdminPages.class);
Third I don't see initialisation of ExtentReport test. It should looks something like this:
ExtentTest extentTest = ExtentTestManager.startTest(method.getName(), "");
Here is an example part of code from my implementation of calling screenshot, I'am calling it from afterInvocation
, because I'm using concurrent driver initialisation, and so it had to be from here, but also can be achived via onTestFailure
implementation:
public synchronized void afterInvocation(IInvokedMethod method, ITestResult testResult){
if (method.isTestMethod() && testResult.getStatus()==2) {
File scrFile = (dataMethod.getAndroidDriver()).getScreenshotAs(OutputType.FILE);
String dest = System.getProperty("user.dir") + "/resources/screenshots/" + dataMethod.getDriver().getSessionId() + ".png";
File destination = new File(dest);
try {
FileUtils.copyFile(scrFile, destination);
dataMethod.setScreenshotPath(destination.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
System.err.println("Path:" + dataMethod.getScreenshotPath());
}
You have to think more about structure,
Hope this helps...
来源:https://stackoverflow.com/questions/50923373/extent-report-3-add-screenshot