How to attach SOFTASSERT screenshots to Allure report? - java

I am a manual tester learning Selenium+Java at the moment. Thanks to a lot of brilliant answers at Stack Overflow, I managed to take screenshot when SoftAssert fails, but I'm now struggling with attaching these screenshot on Allure report. Can someone tell me what to add to my code to have these screenshot attached to the Allure report? Many thanks!!
//Override my onAssertFailure:**
public class CustomSoftAssert extends SoftAssert{
#Override
public void onAssertFailure(IAssert<?> assertCommand, AssertionError ex)
{
WebDriver driver = TestBase.getDriver1();
Reporting.takeScreenshot(driver);
}
//takeScreenshot method:
public static void takeScreenshot(WebDriver driver) {
try
{
TakesScreenshot ts=(TakesScreenshot) driver;
File source=ts.getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(source, new File("./screenshots/"+System.currentTimeMillis()+".png"));
System.out.println("Screenshot taken");
}
catch (Exception e)
{
System.out.println("Exception while taking screenshot "+e.getMessage());
}
}
//onTestFailure method in AllureTestListener**
#Override
public void onTestFailure(ITestResult iTestResult) {
System.out.println("I am in onTestFailure method " + getTestMethodName(iTestResult) + " failed");
Object testClass = iTestResult.getInstance();
WebDriver driver = TestBase.getDriver1();
// Allure ScreenShotRobot and SaveTestLog
if (driver instanceof WebDriver) {
System.out.println("Screenshot captured for test case:" + getTestMethodName(iTestResult));
saveScreenshotPNG(driver);
}
// Save a log on allure.
saveTextLog(getTestMethodName(iTestResult) + " failed and screenshot taken.");
}```

Related

#After and #Before annotation is not executing second method

I have declared 2 methods #after annotation but it will execute only the first method, it does not allow me to execute the second method. Please have a look at the below code
I want to execute 1 method every time for the exit of the browser.
I want to execute the second method for failed test cases.
#Before
public void databaseLoading(Scenario scenario) {
//System.out.println("Test Environment Set Up");
System.out.println("\n------------------------------------------------ TEST ENVIRONMENT SET UP ------------------------------------------------------------------------------\n");
System.out.println("Executing Scenario :-> " + scenario.getName());
}
#After
public void browserTearDown()
{
System.out.println("End the browser");
driver.close();
}
public void Screenshot(Scenario scenario) {
// take the screenshot at the end of every test
String location = ".\\target\\TakeScreenshot";
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy hh-mm-ss", Locale.ENGLISH);
Date date = new Date();
File scrFile =
((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
// now save the screenshto to a file some place
if (scenario.isFailed()) {
try {
FileUtils.copyFile(scrFile, new File(location + "\\" + dateFormat.format(date) + ".png"));
System.out.println("Screenshot saved");
} catch (IOException e) {
System.out.println("Error in taking Screenshot --> " + e);
}
}
}
Method 'Screenshot(cucumber.api.Scenario)' is never used. This error message comes for the second method.
You only tagged browserTearDown() method.
Add the #After tag to the Screenshot() method, as well:
#After
public void browserTearDown()
{
System.out.println("End the browser");
driver.close();
}
#After
public void Screenshot(Scenario scenario) {
...
}

Getting java.lang.NullPointerException in POM uisng page Factory

I've posted below some sample code which I've done so far and I'm getting an Exception java.lang.NullPointerException.
Base Class:
public class TestBase {
public static WebDriver driver= null;
#BeforeSuite
public void initialize(){
System.setProperty("webdriver.chrome.driver","...chromedriver_win32\\chromedriver.exe");
WebDriver driver=new ChromeDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.get("abcd.com");
}
#AfterSuite
public void TearDownTest()
{
TestBase.driver.quit();
}
}
Login Page:
public class LoginPage {
WebDriver driver;
public LoginPage(WebDriver driver)
{
this.driver= driver;
}
#FindBy(how=How.XPATH, using="//*[#id='email_id']") WebElement EmailTextBox;
#FindBy(how=How.XPATH, using="//*[#id='password']")WebElement PassworTextBox;
#FindBy(how=How.XPATH, using="//*[#id='frm_login']/div[4]/input") WebElement LoginButton;
public void setemail(String strmail)
{
EmailTextBox.sendKeys(strmail);
}
public void setpwd(String strpwd)
{
try
{
PassworTextBox.sendKeys(strpwd);
}
catch (TimeoutException e)
{
System.out.println("Time out exception " + e);
}
catch (ElementNotSelectableException e) {
System.out.println("Element not selectable exception " + e);
} catch (NoSuchElementException e) {
System.out.println("No such element found " + e);
} catch (ElementNotVisibleException e) {
e.printStackTrace();
} catch (Exception e) {
System.out.println("Something Wrong " + e);
}
}
public void ClickLoginBtn()
{
LoginButton.click();
}
}
LoginTest class:
public class LoginTest extends TestBase{
#Test
public void init()
{
System.out.println("In the init method");
LoginPage lg=PageFactory.initElements(driver, LoginPage.class);
lg.setpwd("123123");
lg.setemail("abc#gmail.com");
lg.ClickLoginBtn();
}
}
I am getting the NullPointerException while setting the username and password. Could you please help me?
I am new to the POM with PageFactory so I dont have any idea How to resolve it but If anyone can help me with that it would be big help to me.
You shouldn't initialise the WebDriver instance i.e. driver twice as follows:
public static WebDriver driver= null;
and
WebDriver driver=new ChromeDriver();
Keep the global declaration as:
public static WebDriver driver= null;
And channge the line as:
driver=new ChromeDriver();
Try to add a timeout after driver.get("abcd.com"); to be sure page has finished to load, and can find WebElements defining EmailTextBox and PassworTextBox.
Or use a WebDriverWait like this
new WebDriverWait(driver, 10))
.until(ExpectedConditions.visibilityOf(By.id("someid")));
I hope you have initialized the page factory elements like so
public LoginPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
In your Test class,
I would place
LoginPage lg = new LoginPage(driver);
Read more here:
https://www.seleniumeasy.com/selenium-tutorials/page-factory-pattern-in-selenium-webdriver

I've installed Gecko driver but still getting an error

I've installed the Gecko driver because i was getting this error : "java.lang.IllegalStateException: The path to the driver executable must be set by the webdriver.gecko.driver system property;"
But after applying the code still i'm getting error for Gecko driver.
Below is my complete code. please let me know what I'm missing.
public class Pawan {
public static WebDriver driver;
public static void main(String[] args){
System.setProperty("webdriver.firefox.marionette","C:\\Users\\Lalit-pc\\Desktop\\geckodriver-v0.21.0-win64\\geckodriver.exe");
driver = new FirefoxDriver();
}
#Test
public void test() {
WebDriver driver = new FirefoxDriver();
driver.manage().window().maximize();
driver.get("https://www.google.com/");
driver.findElement(By.linkText("Find a Physician")).click();
driver.findElement(By.id("searchZip")).sendKeys("32806");
driver.findElement(By.linkText("Mile Radius")).click();
try{
Thread.sleep(6000);
}catch (InterruptedException ie1) {
ie1.printStackTrace();
}
driver.findElement(By.linkText("20")).click();
driver.findElement(By.linkText("Specialty")).click();
try{
Thread.sleep(6000);
}catch (InterruptedException ie1) {
ie1.printStackTrace();
}
driver.findElement(By.linkText("Anesthesiology")).click();
driver.findElement(By.cssSelector("input[type='submit'][value='Search Now']")).click();
String str= driver.findElement(By.xpath(".//*[#id='finderListView']/div[3]/div[1]/div/div[1]/p")).getText();
if("Anesthesiology".equals(str))
System.out.println("Physician Search Successful");
else
System.out.println("Physician Search NOT Successful");
driver.findElement(By.linkText("Browse Locations")).click();
try{
Thread.sleep(6000);
}catch (InterruptedException ie1) {
ie1.printStackTrace();
}
driver.findElement(By.xpath(".//*[#id='sidebarMenu']/div[1]/form/div/input")).sendKeys("32806");
driver.findElement(By.xpath(".//*[#id='sidebarMenu']/div[1]/form/input")).click();
try{
Thread.sleep(6000);
}catch (InterruptedException ie1) {
ie1.printStackTrace();
}
driver.findElement(By.xpath(".//*[#id='sidebarMenu']/div[2]/section/div/ul/li[1]/a")).click();
try{
Thread.sleep(6000);
}catch (InterruptedException ie1) {
ie1.printStackTrace();
}
WebElement divElement = driver.findElement(By.xpath(".//*[#id='overflow-autoScroll']/li[1]/ul/li/a/div[2]/span[3]"));
String stri = divElement.getText();
if(stri.contains("32806"))
System.out.println("Location Search successful");
else
System.out.println("Location Search not successful");
driver.findElement(By.xpath("html/body/header/div[1]/div[2]/a[3]")).click();
driver.findElement(By.linkText("Health Topics")).click();
try{
Thread.sleep(6000);
}catch (InterruptedException ie1) {
ie1.printStackTrace();
}
driver.findElement(By.linkText("Diabetes")).click();
WebElement divElementtwo = driver.findElement(By.xpath("html/body/div[4]/div/div[1]/div[1]/h2"));
String strn = divElementtwo.getText();
if(strn.contains("Diabetes"))
System.out.println("Blog Search successful");
else
System.out.println("Blog Search not successful");
}
}
To verify gecko driver is compatible with your current firefox & selenium version, do the following:
Keep downloaded gecko driver at System32 if you are on Windows OS & /usr/local/bin if you are on Mac OSX
Run the Selenium Standalone server by this command: java -jar selenium-server-standalone-3.13.0.jar
Open this url in Firefox browser: http://localhost:4444/wd/hub
Create Session and Select Firefox browser
If browser starts then there is no issue with the compatibility of geckodriver with Firefox & Selenium version.
small setup change requied: (latest firefox browser)
public class Pawan {
public static WebDriver driver;
#BeforeClass
public static setup() {
System.setProperty("webdriver.gecko.driver","C:\\Users\\Lalit-pc\\Desktop\\geckodriver-v0.21.0-win64\\geckodriver.exe");
driver = new FirefoxDriver();
}
// Urs test here
JUnit uses a different main entry point than the public static void main(String[] args) method you've defined there, so if you execute the tests, System#setProperty won't be executed.
To add the system property once for all tests in the class, you need to define a #BeforeClass method:
public class Pawan {
public static WebDriver driver;
#BeforeClass
static void init() {
System.setProperty("webdriver.firefox.marionette","C:\\Users\\Lalit-pc\\Desktop\\geckodriver-v0.21.0-win64\\geckodriver.exe");
}
//test cases here...
}
Now, for development purposes, I recommend setting this variable as a constant accessible by your PATH environment variable (OS dependent) rather than setting it as a system property.
You can also define geckodriver in #Test if you do not want #BeforeClass annotation :
#Test
public void test() {
System.setProperty("webdriver.firefox.marionette","C:\\Users\\Lalit-pc\\Desktop\\geckodriver-v0.21.0-win64\\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
driver.manage().window().maximize();
driver.get("https://www.google.com/");
This will also work:)

Webdriver not closing after driver.quit has been called

I am running tests with WebDriver, when a test fails, the browser does not close. On a Windows machine this is a huge problem because I then have several instances of the Firefox still running in the background. Kindly advise
Here's the code :
public static WebDriver driver;
private String sTestCaseName;
#BeforeMethod
public void beforeMethod() throws Exception {
DOMConfigurator.configure("log4j.xml");
sTestCaseName = Constant.Login_Name;
Log.startTestCase(sTestCaseName);
new BaseClass(driver);
}
#Test(description = "Login", enabled = true)
public void TestLogin_Success() throws Exception {
try {
driver = new FirefoxDriver();
LoginBuilder.Execute(driver);
Log.info("Successfully Login!");
} catch (Exception e) {
Log.error(e.getMessage());
throw (e);
}
}
#Test(description = "Login_Failed", enabled = true)
public void TestLogin_Failed() throws Exception {
try {
driver = new FirefoxDriver();
LoginBuilder.Execute_Failed(driver);
Log.info("Unsuccessfully Login!");
} catch (Exception e) {
Log.error(e.getMessage());
throw (e);
}
}
#AfterMethod
public void afterMethod() {
Log.endTestCase(sTestCaseName);
driver.close();
}
Add finally block to your try catch block.
Close the WebDriver there.
Sample code snippet
try {
....
....
} catch(Exception e) {
....
....
} finally {
....
driver.close();
}
More info on Dispose, Close and Quit - Difference between webdriver.Dispose(), .Close() and .Quit()
Call driver.quit() instead of driver.close()
#AfterMethod
public void afterMethod() {
Log.endTestCase(sTestCaseName);
driver.quit();
}
Why don't you try to use #AfterClass

Fail to take screenshots with Selenium WebDriver using Java when a JUnit test fails

I am using Java with Webdriver, and I am having problem with taking screenshots with failed test.
My jUnit test:
....
public class TestGoogleHomePage extends Browser {
....
#Test
public void testLoadGoogle() {
//this test will fail
}
}
My Browser class:
public class Browser {
protected static WebDriver driver;
public Browser() {
driver = new FirefoxDriver();
}
.....
#Rule
public TestWatcher watchman = new TestWatcher() {
#Override
protected void failed(Throwable e, Description description) {
File scrFile = ((TakesScreenshot) driver)
.getScreenshotAs(OutputType.FILE);
try {
FileUtils.copyFile(scrFile, new File(
"C:\\screenshot.png"));
} catch (IOException e1) {
System.out.println("Fail to take screen shot");
}
// this won't work
// driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
#Override
protected void succeeded(Description description) {
....
}
};
#After
public void closeBrowser() {
driver.quit();
}
}
The execution of the test will result in the following error message (part of the error message):
org.openqa.selenium.remote.SessionNotFoundException: The FirefoxDriver cannot be used after quit() was called.
Looks like it is complaining about my #After method.
I have tried to change the Browser class to be:
public class Browser {
protected static WebDriver driver;
public Browser() {
driver = new FirefoxDriver();
}
.....
#Rule
public TestWatcher watchman = new TestWatcher() {
#Override
protected void failed(Throwable e, Description description) {
File scrFile = ((TakesScreenshot) driver)
.getScreenshotAs(OutputType.FILE);
try {
FileUtils.copyFile(scrFile, new File(
"C:\\screenshot.png"));
} catch (IOException e1) {
System.out.println("Fail to take screen shot");
}
driver.quit();
}
#Override
protected void succeeded(Description description) {
....
driver.quit();
}
};
}
And the above codes work fine. But I don't want to quit the driver there because there might be something else I want to clean up after each test run, and I want to close the browser in the #After method.
Is there a way I can do that?
The problem is because of the following code:
#After
public void closeBrowser() {
driver.quit();
}
The driver.quit() is attempting to close the browser after EVERY test; and it is getting executed before the call-back methods of your TestWatcher. This is preventing TestWatcher from getting a handle of the driver. Try using a more restrictive life-cycle annotation like #AfterClass or #AfterSuite.

Categories