how to get a screenshot for failure tests with method name of failure test - selenium

With the listeners how can we solve it.Give me a better solution.I tried using with Listners but it is not giving the method name of failure test, it giving the screenshot name with current method name.for example if a test is failed in one class i want that class method name only.but it is giving execution method as screen shot name
public class Invoke {
public static WebDriver driver;
public static void invoking() throws Exception {
System.setProperty("webdriver.chrome.driver",
"E:\\AK\\Selenium files\\chromedriver_win32 (1)\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().window().maximize();
driver.get("facebook.com/");
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
driver.findElement(By.xpath("akdhd")).click();
}
}
public class Excecution {
#Test public static void m() throws Exception {
Invoke.invoking();
String val=ExcelDynamic.r("C:\\Users\\PC\\Desktop\\facebook.xlsx", "Sheet1", 1, 1);
System.out.println(val);
}
This code is in another class
public static void screen(String Filepath) throws Exception {
TakesScreenshot ts = ((TakesScreenshot) driver);
File fi = ts.getScreenshotAs(OutputType.FILE);
String img = Thread.currentThread().getStackTrace()[2].getMethodName() + ".jpg";
FileUtils.copyFile(fi, new File(Filepath + img));
}
}
i'm calling this method in execution class so it is printing screenshot name m. But i want output name as invoking for screen shot

Below is a utility method that returns the calling method name.
public static String get_calling_method_name() {
return Thread.currentThread().getStackTrace()[2].getMethodName();
}
Hope this solves the issue.

You may try By this,
To change with first index,
String img = Thread.currentThread().getStackTrace()[1].getMethodName() + ".jpg";
Hope it will work.

Related

dataProvider with #Before testng

I am working with one TestNG script with SauceLab and Jenkins. I stuck with one problem. When I run my project from Jenkins I will select browsers from there, so I can use it with "dataProvider", but dataProvider is only working with #Test annotations, I want to use dataProvider with #before.
Steps:
#Before will initialize the driver (Webdriver) object.
#Test with execute first test case with driver object.
#Test (2nd) with execute second test case with same driver object.
public class test
{
Webdriver driver;
// Over here I want to use #Before
#Test(dataProvider = "dynamicParameters", priority = 0, alwaysRun = true)
public void init(String browser, String version, String os, Method method) throws Exception
{
System.out.println("Init Method");
String BASE_URL = System.getProperty("baseUrl");
PCRUtils pcrUtils = new PCRUtils();
driver = pcrUtils.createDriver(browser, version, os, method.getName());
driver.get(BASE_URL);
driver.manage().window().maximize();
Thread.sleep(50000);
}
#Test(priority = 1)
public void verifyTitle() throws InterruptedException
{
AccountPage accountPage = new AccountPage();
accountPage.verifyTitle(driver);
}
}
TestNG "#before" methods cannot be used directly with a #DataProvider.
A #BeforeMethod can access the list of parameters (TestNG - 5.18.1 - Native dependency injection):
Any #BeforeMethod can declare a parameter of type Object[]. This parameter will receive the list of parameters that are about to be fed to the upcoming test method, which could be either injected by TestNG, such as java.lang.reflect.Method or come from a #DataProvider
But a #BeforeMethod "will be run before each test method" and what you want is something more like #BeforeClass which "will be run before the first test method in the current class is invoked" (TestNG - 2 - Annotations). Unfortunately #BeforeClass cannot access the list of parameters via TestNG's native dependency injection like a #BeforeMethod can.
A #Factory however can be used to accomplish the initial, data-driven setup with a #DataProvider. e.g.:
public class test
{
WebDriver driver;
#Factory(dataProvider = "dynamicParameters")
public test(String browser, String version, String os, Method method) throws Exception
{
System.out.println("Init Method");
String BASE_URL = System.getProperty("baseUrl");
PCRUtils pcrUtils = new PCRUtils();
driver = pcrUtils.createDriver(browser, version, os, method.getName());
driver.get(BASE_URL);
driver.manage().window().maximize();
Thread.sleep(50000);
}
#Test(priority = 1)
public void verifyTitle() throws InterruptedException
{
AccountPage accountPage = new AccountPage();
accountPage.verifyTitle(driver);
}
#Test(priority = 2)
public void verifySomethingElse() throws InterruptedException
{
// execute second test case with same driver object.
}
}
See TestNG - 5.8 - Factories for more details.

Wait for page loading using PageFactory C#

I'm using PageFactory in my selenium tests. And I've faced a problem in waiting for loading page. I'm not talking about an element on a page I'm talking about timeout of page loading.
So, I have a method like the following:
public MyProjectsPage ClickSaveAndCloseButton()
{
//Do something and click a button
SaveAndCloseButton.Click();
return new MyProjectsPage(Driver); //return new page
}
And when I'm waiting for returning new PageObject (in my case it is "MyProjectsPage") I got a timeout exception. So, where can I set a page loading timeout?
Actual mistake looks like this:
AutomatedTests.FrontEnd.SouvenirProduct.SouvenirTestExecution.OrderSouvenirWithAuthorization(ByCash,Pickup,True,Cup):
OpenQA.Selenium.WebDriverException : The HTTP request to the remote WebDriver server for URL http://localhost:7585/session/b68c04d1ead1fc78fe083e06cbece38f/element/0.46564483968541026-14/click timed out after 60 seconds.
----> System.Net.WebException : The operation has timed out
I have:
The latest version of WebDriver
And the latest version of ChromeDriver and the latest version of Chrome Browser
The mistake that is above apears int the next line:
return new MyProjectsPage(Driver); //return new page
I create my ChromeDriver the next way:
public DriverCover(IWebDriver driver)
{
_driver = driver;
_driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
}
private readonly IWebDriver _driver;
1 note considering wait mechanisms on the page:
Take a couple of webElements and apply for them fluentWait() . That'll be explicit wait webdriver approach.
Another approach is to try out implicit wait like:
int timeToWait=10;
driver.manage().timeouts().implicitlyWait(timeToWait, TimeUnit.SECONDS);
Considering you pageObject code:
I would recommed you the following:
MyPage myPageInstance= PageFactory.initElements(driver, MyPage.class);
then you write the following method :
public MyPage clickSaveAndOtherActions(MyPage testPageToClick)
{
testPageToClick.clickFirstButton();
testPageToClick.clickSecondButton();
testPageToClick.closePoPup();
return testPageToClick; //return page in a new state
}
and if you wanna continue working (I mean update your page state) you do the following:
myPageInstance = clickSaveAndOtherActions(myPageInstance );
Hope this helps you. Thanks.
UPD : as I see from the log something looks wrong with remoteWebdriver server:
OpenQA.Selenium.WebDriverException : The HTTP request to the remote
WebDriver server for URL
http://localhost:7585/session/b68c04d1ead1fc78fe083e06cbece38f/element/0.46564483968541026-14/click
timed out after 60 seconds. ----> System.Net.WebException : The
operation has timed out
Also, I'd recommend you to double check you driver method init. I'm using the following piece of java code for driver init (UI , chrome instance, selenium grid+ hub nodes test architecture):
public static WebDriver driverSetUp(WebDriver driver) throws MalformedURLException {
DesiredCapabilities capability = DesiredCapabilities.chrome();
log.info("Google chrome is selected");
//System.setProperty("webdriver.chrome.driver", System.getProperty("user.home")+"/Documents/Tanjarine/chromedriver");
System.setProperty("webdriver.chrome.driver", "chromedriver.exe");
capability.setBrowserName("chrome");
capability.setPlatform(org.openqa.selenium.Platform.WINDOWS);
String webDriverURL = "http://" + environmentData.getHubIP() + ":" + environmentData.getHubPort() + "/wd/hub";
driver = new RemoteWebDriver(new URL(webDriverURL), capability);
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
driver.manage().window().setSize(new Dimension(1920, 1080));
return driver;
}
What you should really be doing when using the PageFactory pattern is when initialising your Page you should be using a constructor to initialise the elements.
public MyProjectsPage ClickSaveAndCloseButton()
{
//Do something and click a button
//I am guessing this is taking you to the MyProjectsPage
SaveAndCloseButton.Click();
return new MyProjectsPage(Driver); //return new page
}
public class MyProjectsPage
{
[FindsBy(How = How.Id, Using = "yourId")]
public IWebElement AWebElement { get; set; }
private IWebDriver WebDriver;
public MyProjectsPage (IWebDriver webDriver)
{
WebDriver = webDriver;
PageFactory.InitElements(WebDriver, this);
}
}
When you return the page, all elements using the FindsBy attribute will be initialised.
Update:
set this property on the driver when you initialise it:
WebDriver.Manage().Timeouts().SetPageLoadTimeout(timespan)
// Wait Until Object is Clickable
public static void WaitUntilClickable(IWebElement elementLocator, int timeout)
{
try
{
WebDriverWait waitForElement = new WebDriverWait(DriverUtil.driver, TimeSpan.FromSeconds(10));
waitForElement.Until(ExpectedConditions.ElementToBeClickable(elementLocator));
}
catch (NoSuchElementException)
{
Console.WriteLine("Element with locator: '" + elementLocator + "' was not found in current context page.");
throw;
}
}
// Wait For Page To Load
public static void WaitForPage()
{
new WebDriverWait(DriverUtil.driver, MyDefaultTimeout).Until(
d => ((IJavaScriptExecutor)d).ExecuteScript("return document.readyState").Equals("complete"));
}

Selenium NullPointerException while trying to find WebElement

While trying to execute below method, I receive NullPointerException:
#Test
public static void test1() {
System.out.print("\nTo find UserName element");
WebElement element =driver.findElement(By.xpath("//input[#name='email']"));
WebElement element = driver.findElement(By.id("email"));
element.sendKeys("abhinav_shankar");
System.out.print("\nElement found");
System.out.print("\njunittest2 class-test1 executed before sleep");
Thread.sleep(15000);
System.out.print("\njunittest2 class-test1 executed after sleep");
}
Below excpetion is caught at line "WebElement element = driver.findElement(By.id("email"));"
Thread [main] (Suspended (exception NullPointerException))
Mytestclass.test1() line: 44
Mytestclass.main(String[]) line: 21
I tried using xpath as written in above code but it also gives same error.
EDIT:
#BeforeClass
public static void openbrowser() {
FirefoxProfile profile = new FirefoxProfile();
System.out.print("\nBrowser open");
WebDriver driver = new FirefoxDriver(profile);
driver.manage().window().maximize();
driver.get("website-url");
}
You seem to have declared driver twice. One in the class level & one in openbrowser method.
You initialize only the openbrowser driver. The class level driver is still null. So, test1 method throws null pointer exception.
So, remove the driver re-declaration in the openbrowser method. Just this will do and it should work.
driver = new FirefoxDriver(profile);
Issue :
Your Webdriver objects seems to be declared inside a function openbrowser() because of which driver object scope is only with that function. So the NullpointerException could be due to driver.
Solution :
Declare the Webdriver globally and initialize within the openbrowser method so that you can use it in test1() or any other methods also.
public WebDriver driver;
#BeforeClass
public static void openbrowser() {
//Driver initialization
}
#Test
public static void test1() {
//Use the driver here
}

How to pass multiple locators in Selenium webdriver to fetch an element on a page

Hi can anyone pls solve this. When i write a code to automate sometimes the elements are not identified and sometimes its not found even they are present, means even if the id is present it says element not found error. So I a trying to create a method where i would pass all the dom objects i find like Ex :
public static void Click(WebDriver driver, String name,Sting linktext,Sting id,Sting Xpath,String css)
{
driver.findElement(new ByAll(By.name(name),
By.linkText(linktext),
By.id(id),
By.xpath(xpath),
By.cssSelector(css))).click();
}
And i would pass what ever value i find in source page like sometimes it will have oly id or it ll have oly link text Ex:(when i import this method in other class)
Click(Webdriver driver, "username",null,"","//[fas].user");
is this the correct way to pass the arguments. can i pass like null and "" (blank). Pls help this would become a one simple effective framework for me.
you can use this 2 methods
public static WebElement findElement(WebDriver driver, By selector, long timeOutInSeconds) {
WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
wait.until(ExpectedConditions.presenceOfElementLocated(selector));
return findElement(driver, selector);
}
public static WebElement findElementSafe(WebDriver driver, By selector, long timeOutInSeconds) {
try {
return findElement(driver, selector, timeOutInSeconds);
} catch (TimeoutException e) {
return null;
}
}
public static void waitForElementToAppear(WebDriver driver, By selector, long timeOutInSeconds, String timeOutMessage) {
try {
WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(selector));
} catch (TimeoutException e) {
throw new IllegalStateException(timeOutMessage);
}
}
----------------
public static void click(WebDriver driver , By ... selector ){
for (By byPath : selector) {
WebElement element = findElementSafe(driver, byPath, 1);
if(element != null){
element.click();
}
}
}

Unable to add screenshot in ReportNG HTML report

I am trying to take a screenshot for failure methods and also want to put the same in my Report, I am able to take the screenshot but unable to show the same in HTML report. Following is my code, friends any clue on this ?
public class SB1 {
private static Logger logger = Logger.getLogger(SB1.class);
WebDriver driver = new FirefoxDriver();
#Test
public void Testone() {
driver.get("http://www.google.com/");
assert false;
}
public void catchExceptions(ITestResult result) {
System.out.println("result" + result);
String methodName = result.getName();
System.out.println(methodName);
if (!result.isSuccess()) {
try {
String failureImageFileName = new SimpleDateFormat("MM-dd-yyyy_HH-ss").format(new GregorianCalendar().getTime())+ ".png";
File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File(failureImageFileName));
String userDirector = System.getProperty("user.dir") + "/";
Reporter.log("<a href=\""+ userDirector + failureImageFileName +"\"><img src=\"file:///" + userDirector
+ failureImageFileName + "\" alt=\"\""+ "height='100' width='100'/> "+"<br />");
Reporter.setCurrentTestResult(null);
} catch (IOException e1) {
e1.printStackTrace();
}
}
Have you set ESCAPE_PROPERTY to false? This is what you will have to do if you want reportng to post the screenshot -
private static final String ESCAPE_PROPERTY = "org.uncommons.reportng.escape-output";
and in your setUp-
System.setProperty(ESCAPE_PROPERTY, "false");
I tried this. It seems like if you set the System Property to false, it removes the escaping from the ENTIRE log... From what I can tell, the report is generated after the test, with whatever the system property is set to at the time. I want to insert the screenshot (which worked with above code) but I do not want to remove the other formatting (br tags).
You can use following code.
Reporter.log("<br>Chrome driver launched for ClassOne</br>");
Or you can use customize method, where you do not need to append the br tag everytime, use following customized method.
public void customLogReport(String testCaseDescription) throws Exception{
try{
Reporter.log("<br>" + testCaseDescription + "</br>");
}catch(Exception e){
e.printStackTrace();
}
}