Testng how to get all the log steps in aftermethod for post issue on some bug tracking tools - selenium

I am working on a project where if test case is failed I have to post a bug on their bug tracking tools through the tools. But they want in a bug report all the steps should mentioned properly with error.
Like in the description they want like this
Open Url
List item
Click the submit button Dashboard title is not match properly
In My automation code, I have written log
public class logtest {
WebDriver driver;
#BeforeMethod
public void Before(){
driver=new ChromeDriver();
}
#Test
public void test1(){
Log.info("Open URl");
//Opened url
Log.info("Click on the submit button");
// Submit button Clicked
Log.info("Open Dashboard");
Log.info("Dashboard Title match");
}
#AfterMethod
public void AfterMethod(ITestResult result){
if (result.getStatus() == ITestResult.FAILURE) {
PostIssue_to_Somewhere();
}
}
}
Is there any want I can get all the steps that I print inside #Test in the after method
so I can post bugs to their board through API
I think I can save the result somewhere and print it the end of the test case but I don't think it's an ideal solution. If you have any suggestion or way that I can manage it using testing that will really helpful

You cannot get the result in after test method. you should use TestNG listener for get the results
Steps to get them :
First create your own class with extend listener class
public class Listener implements ITestListener
Then use the override method to get the results
#Override
public void onTestSuccess(ITestResult iTestResult) {
}
there are several method to get the exact data,
OnStart- OnStart method is called when any Test starts.
onTestSuccess- onTestSuccess method is called on the success of any test
onTestFailure- onTestFailure method is called on the failureof any Test.
onTestSkipped- onTestSkipped method is called on
skipped of any Test
onTestFailedButWithinSuccessPercentage- method
is called each time Test fails but is within success percentage.
onFinish- onFinish method is called after all Tests are executed.

Use Extent Report and then use its method like (log, pass, fail ) to log your steps in your report, based on your test result, if you still need help let me know :)
You can see the full project demo code at ( below is code for the extent report) https://github.com/0kakarot0/ExtentReportBasic.git
public class MyExtentReport {
private WebDriver driver;
ExtentSparkReporter spark;
ExtentReports extentReports;
ExtentTest extentTest;
public MyExtentReport(WebDriver driver) {
this.driver = driver;
}
//Created Extent Report Html File
public void extentReporter() {
Date date = new Date();
String rightNow = "Spark"+ date.getTime() + ".html" ;
String pathOfFile = "allReports/"+rightNow;
spark = new ExtentSparkReporter(pathOfFile);
extentReports = new ExtentReports();
extentReports.attachReporter(spark);
}
public void logTestNameAndDescription(String name, String description){
extentTest = extentReports.createTest(name, description);
}
public void logTestInfo(String testInfo){
extentTest.log(Status.INFO,testInfo);
}
public void logPassedTestSteps(String logPassMessage){
extentTest.pass(logPassMessage);
}
public void logFailTestSteps(String logFailMessage){
extentTest.fail(logFailMessage);
}
public void logFailTestScreenShot(String reasonOfFailure){
extentTest.fail(reasonOfFailure,MediaEntityBuilder.createScreenCaptureFromPath("utils/failedTestScreenShot/screenshot.png").build());
}
public void flushExtentReport(){
extentReports.flush();
}

Related

How to skip a testNG class based on element visibility and switch to another class

I am using testNG for my selenium suite. There is a class having 35 test cases. But these test cases will execute only if a particular element is visible. If that element is not visible, the compiler goes through all the test cases. Is there any way that I could check that element visibility condition in an #BeforeClass annotation only. If an element is not visible, it should come out from that class and switch to the next one? It will save my time to go through all the test cases?
To achieve it use #Test annotation on class level and #BeforeTest to check element visibility so it will skip all test cases of class if it will not satisfy condition in #BeforeTest. See below code (it's tested and working).
#Test
public class SkipAllTestCases {
boolean elementNotVisible=true;
#BeforeTest
public void setUp() {
if (elementNotVisible) {
throw new SkipException("skipping test cases...");
}
}
public void test1() {
System.out.println("Test1");
}
public void test2() {
System.out.println("Test2");
}
public void test3() {
System.out.println("Test3");
}
}
Hope it will help.
You can use dependsOnMethods of TestNG Test annotation.
#Test
public void elementVisibleTest(){
//Fail or skip here
}
#Test(dependsOnMethods = {"elementVisibleTest"})
public void myOtherTest(){
//Do something
}
...
That means if elementVisibleTest fails or gets skipped all tests which depend on that test will be skipped too. The advantage of that would be that you can still have other tests in that class which will be executed (because they do not depend on elementVisibleTest).
One of the approach is add group to all such tests let say flow-1. Add before group method and throw exception if it doesn't match required condition. For example:
#BeforeGroups(groups="flow-1")
public void flow1() {
if(!requiredCondtionMatch) {
throw new SkipException("Flow not applicable");
}
}
If all tests falls under same class then you can use #BeforeClass as well.

Getting StaleElementReferenceException trying one valid and one invalid login

I am trying to write a test for valid and invalid login in same test class but I am getting StaleElementReferenceException. Below is the code
public class LoginTest {
static{
System.setProperty("webdriver.chrome.driver", "./driver/chromedriver.exe");
}
public static void main(String[] args) throws InterruptedException {
WebDriver driver = new ChromeDriver();
driver.get("http://app.meltwaterbuzz.com/");
driver.manage().window().maximize();
LoginPage login = new LoginPage(driver);
System.out.println(driver.getTitle());
login.setUsername("username");
login.setPassword("password");
login.clickSignIn();
login.setUsername("username");
login.setPassword("password");
login.clickSignIn();
System.out.println(driver.getTitle());
//driver.close();
}
}
Any idea how to handle this?
Generally we will be getting the Stale Exception if the element attributes or something is changed after initiating the webelement. For example, in some cases if user tries to click on the same element on the same page but after page refresh, gets staleelement exception.
To overcome this, we can create the fresh webelement in case if the page is changed or refreshed. Below code can give you some idea.
Example:
webElement element = driver.findElement(by.xpath("//*[#id='StackOverflow']"));
element.click();
//page is refreshed
element.click();//This will obviously throw stale exception
To overcome this, we can store the xpath in some string and use it to create a fresh webelement as we go.
String xpath = "//*[#id='StackOverflow']";
driver.findElement(by.xpath(xpath)).click();
//page has been refreshed. Now create a new element and work on it
driver.fineElement(by.xpath(xpath)).click(); //This works
Hope this helps you. Thanks.
Here is the Answer to your Question:
In your code block you are creating an object login of LoginPage class, filling up username, password and you are clicking on SignIn button. Once you click on SignIn button you are logged in as a registered user and redirected to a new page. Here the page/url have changed and the HTML DOM have also changed.
Next you are again trying to pass username through login.setUsername("username") again and Selenium is unable to find the same locator (id/name/css/xpath) on this new page. Hence Selenium complains of StaleElementReferenceException which essentially means the locator you are looking for is no more present on the HTML DOM or have become stale.
The solution to your issue would be to Logout and come back again to the initial url http://app.meltwaterbuzz.com/.
Let me know if this Answers your question.
I found the way to overcome StaleElementReferenceException, If we use page object model then we can overcome it. Here is the example.
POM Class
public class LoginPage {
//declaration
#FindBy(id="username")
private WebElement usernameTxt;
#FindBy(name = "pwd")
private WebElement passwordTxt;
#FindBy(css="#loginButton")
private WebElement loginBTN;
//Initialization
public LoginPage(WebDriver driver) {
PageFactory.initElements(driver, this);
}
//Utilization
public void setUserName(String un) {
usernameTxt.sendKeys(un);
}
public void setPassword(String pw) {
passwordTxt.sendKeys(pw);
}
public void clickLogin() {
loginBTN.click();
}
}
Test Class
public class LoginTest {
public static void main(String[] args) throws InterruptedException {
System.setProperty("webdriver.chrome.driver", "./driver/chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("http://localhost/login.do");
LoginPage login = new LoginPage(driver);
login.setUserName("zahid");
login.setPassword("manager");
login.clickLogin();
Thread.sleep(2000);
login.setUserName("admin");
login.setPassword("manager");
login.clickLogin();
}
}

Assertion in selenium webdriver -report showing only falied methods, not passed methods

In my selenium TestNG class, there are some
methods, like method1, method2 etc.
I have added fail and success conditions to each method.
public class TestNGClass {
public void method1(String value) throws Exception {
if(value.equals("PASS"){
org.testng.Assert.assertTrue(condition, message);
}
}
//This is another method
public void method2(String value) throws Exception {
if(value.equals("FAIL"){
org.testng.Assert.fail(message);
}
}
But after the TestNG class execution, in the Test-Output folder "Index.html" will be created, which shows only the failed methods. How to display the passed methods also (custom report) .?
Thank you
Convert your test methods using #Test annotation. Modified Code Snippet:
public class TestNGClass {
#Test
public void method1(){
Assert.assertTrue(condition, "Your Message goes here");
}
//This is another method
#Test
public void method2(){
Assert.fail("Your Message goes here");
}
Now, you will have your testcases reported.

Multiple browser windows opening automatically when one class is called in another class

I have created a class in which I am creating all the methods I require for my test automation. Issue which I am facing is that when I run main class, it works fine. But when I call that class in other class it opens 2 browser windows. The test is performed on 1 and other remains ideal. Also when I use close() or quit() method for #After, it closes the ideal window not the one which I am working on.
Below is my code snippet for ref.
Main class
public class ProjectManagement{
WebDriver driver = new FirefoxDriver();
public void navigateCreate(String uid, String pass) throws Throwable {
driver.manage().window().maximize();
driver.get(baseurl);
driver.findElement(By.id("Email")).sendKeys(uid);
driver.findElement(By.id("Password")).sendKeys(pass);
driver.findElement(By.id("loginBtn")).click();
driver.findElement(By.linkText("Projects")).click();
driver.findElement(By.linkText("Create New Project")).click();
}
}
Test Class
public class NewTest extends ProjectManagement{
ProjectManagement project1 = new ProjectManagement();
#Test
public void createPro() throws Throwable {
project1.navigateCreate(UId,Password);
}
#AfterTest
public void afterTest() {
driver.quit();
}
}
If you are extending ProjectManagement, you don't need to instantiate it on the sub-class. By doing so, you're effectively creating two instances of the class and, as such, two instances of WebDriver (which in turn generates two browser windows).
So, remove the following:
ProjectManagement project1 = new ProjectManagement();
And change your createPro() method to:
#Test
public void createPro() throws Throwable {
navigateCreate(UId,Password);
}

Run multiple tests in one class in parallel in multiple instances of browsers using testNG

Please tell me sample code for the fallowing scenario using Web-driver + TestNG framework.
One class having the multiple tests. While running these tests it should run all the tests as parallel in multiple instances of same browser (Ex: Firefox) at a time. So for every test it should open a new instance of a browser.
My solution so far has been something like this:
public MyTestClass {
SupportedBrowser browser;
private static ThreadLocal<WebDriver> threadLocalDriver = new ThreadLocal<WebDriver>();
#DataProvider (name = "getBrowsers")
public Object[][] getBrowsers {
return Object[][] {
{
SupportedBrowser.FIREFOX;
},
{
SupportedBrowser.CHROME;
}
};
}
#Factory (dataProvider = "getBrowsers")
public MyTestClass(SupportedBrowser browser) {
this.browser = browser;
}
#BeforeMethod
public void setup()
{
threadLocalDriver.set(browser.getDriver());
}
#Test
public void test1()
{
WebDriver driver = threadLocalDriver.get();
//do stuff
}
#AfterMethod
public void tearDown()
{
WebDriver driver = threadLocalDriver.get();
driver.quit();
}
}
here is my enum:
public enum SupportedBrowser {
FIREFOX, CHROME; //add more as needed
public getDriver() {
if(this == SupportedBrowser.FIREFOX) {
return new RemoteDriver(hubAddress, DesiredCapabilities.firefox()); //alternatively could be new FirefoxDriver()
}
else {
return new RemoteDriver(hubAddress, DesiredCapabilities.chrome());
}
}
}
Please forgive bad code conventions, I didn't write this in an IDE (though I have used something like this and it works).
The class is run once fore each different browser. Each method has its own independent driver, making sure your test can run concurrently. It also allows each method to take its own DataProvider, in case you need a test method to run multiple times with different arguments. Also make sure that the parallel attribute is set to the "method" level in your testng.xml file.
The only issue with my code is making sure the driver quits if the test fails. Right now, this method leaves closing failed tests up to selenium grid (using -timeout). Please see my question: Sharing driver between #BeforeMethod and #AfterMethod in TestNG.
Edit: I have now added a ThreadLocal variable to the code that shares the driver throughout the thread, so you can call driver.quit() in the #AfterMethod.