Test Case breaking when running the application as a TestNG test - selenium-webdriver

I wrote a java application to use the selenium webdriver to automate few web application tasks. They all worked fine when run as a Java application.
To use the TestNG reporting feature, I ran the application as a TestNG test instead of JAVA application. The same test which was working as JAVA application is failing when I run as testNG.
However, I'm guessing I've setup the TestNG properly since the first testcase which is used to login to the webapp is passing (webLogin method in the code below)
I'm using chromeDriver. I tried removing the main method to run it as testNG application. But it did not work. I made sure that the element path locators I'm using are still valid while using testNG.
package myPackage;
import java.util.NoSuchElementException;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.*;
import com.google.common.base.Function;
public class checkNavigation {
public static WebDriver driver;
public static WebDriverWait wait;
public static void main(String args[]) throws InterruptedException{
Configure();
wait = new WebDriverWait(driver, 30);
webLogin();
addClient();
addGoal();
addInsurance();
validateInputs();
endSession();
}
#BeforeTest
public static void Configure() {
System.setProperty("webdriver.chrome.driver", "/Users/divyakapa/Desktop/automation/chromedriver");
driver = new ChromeDriver();
driver.manage().window().maximize();
driver.manage().deleteAllCookies();
driver.manage().timeouts().pageLoadTimeout(40, TimeUnit.SECONDS);
driver.get("https://example.com");
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
#Test
public static void webLogin() {
getElement(By.xpath("//*[#id=\"id\"]")).sendKeys("admin");
getElement(By.xpath("//*[#id=\"pw\"]")).sendKeys("password");
getElement(By.xpath("//*[#id=\"ember383\"]/div/div/form/button/span")).click();
}
#Test
public static void addClient() {
getElement(By.xpath("//*[#id=\"ember744\"]/button/div")).click();
getElement(By.xpath("//*[#id=\"ember744\"]/div/button[1]/div[2]/div")).click();
getElement(By.xpath("//*[#id=\"newInputFirst\"]")).sendKeys("firstName");
getElement(By.xpath("//*[#id=\"newInputLast\"]")).sendKeys("lastName");
getElement(By.xpath("//*[#id=\"newPersonInputBirthday\"]")).sendKeys("1991");
Select location = new Select(driver.findElement(By.xpath("//*[#id=\"newUserInputProvince\"]")));
location.selectByVisibleText("Place1");
Select isRetired = new Select(driver.findElement(By.xpath("//*[#id=\"alreadyRetiredDropdown\"]")));
isRetired.selectByVisibleText("No");
Select age = new Select(driver.findElement(By.xpath("//*[#id=\"newRetirementAge\"]")));
age.selectByVisibleText("60");
getElement(By.xpath("//*[#id=\"data-entry-modal\"]/div[2]/div/div[1]/div[2]/button[2]")).click();
}
#Test
public static void addGoal() {
getElement(By.xpath("//*[#id=\"ember2328\"]/button/div")).click();
getElement(By.xpath("//*[#id=\"ember2328\"]/div/div[1]/div[2]/button[3]")).click();
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//*[#id=\"ember2464\"]/ul/li[1]/div/div/div[2]/div/span"))).click();
getElement(By.xpath("//*[#id=\"basicExpenseInputAmount\"]")).clear();
getElement(By.xpath("//*[#id=\"basicExpenseInputAmount\"]")).sendKeys("90000");
getElement(By.xpath("//*[#id=\"ember2563\"]/div/div[2]/div[2]/button[2]")).click();
// Add income
getElement(By.xpath("//*[#class=\"add-button \"]")).click();
getElement(By.xpath("//*[#data-test-model-type=\"income\"]")).click();
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//*[#class=\"list-group\"]/li[1]"))).click();
getElement(By.xpath("//*[#id=\"employmentInputName\"]")).clear();
getElement(By.xpath("//*[#id=\"employmentInputName\"]")).sendKeys("Company");
getElement(By.xpath("//*[#id=\"employmentInputSalary\"]")).sendKeys("95000");
getElement(By.xpath("//*[#id=\"employmentInputBonus\"]")).sendKeys("5000");
getElement(By.xpath("//*[#id=\"employmentInputBenefitsInKind\"]")).sendKeys("1000");
getElement(By.xpath("//*[#aria-label=\"Save\"]")).click();
}
#Test
public static void addInsurance() {
getElement(By.xpath("//*[#class=\"add-button \"]")).click();
getElement(By.xpath("//*[#data-test-model-type=\"protection\"]")).click();
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//*[#class=\"list-group\"]/li[1]"))).click();
getElement(By.xpath("//*[#id=\"termLifeName\"]")).clear();
getElement(By.xpath("//*[#id=\"termLifeName\"]")).sendKeys("BlueCrossBlueShield");
getElement(By.xpath("//*[#id=\"ukTermProtectionSalaryMultiplier\"]")).clear();
getElement(By.xpath("//*[#id=\"ukTermProtectionSalaryMultiplier\"]")).sendKeys("5");
Select empId = new Select(driver.findElement(By.xpath("//*[#id=\"termLifeInsuranceEmploymentId\"]")));
empId.selectByVisibleText("Company");
getElement(By.xpath("//*[#aria-label=\"Save\"]")).click();
}
#Test
public static void validateInputs() {
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
if(!(driver.findElements(By.xpath("//*[#data-test-accordion-header=\"goals\"]")).size() > 0)) throw new NullPointerException("Income Failed to ADD");
if(!(driver.findElements(By.xpath("//*[#data-test-accordion-header=\"income\"]")).size() > 0)) throw new NullPointerException("Income Failed to ADD");
if(!(driver.findElements(By.xpath("//*[#data-test-accordion-header=\"protection\"]")).size() > 0)) throw new NullPointerException("Income Failed to ADD");
}
public static WebElement getElement(final By locator) {
FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver).ignoring(NoSuchElementException.class);
WebElement element = wait.until(new Function<WebDriver, WebElement>() {
#Override
public WebElement apply(WebDriver arg0) {
return arg0.findElement(locator);
}
});
return element;
}
#AfterTest
public static void endSession() {
driver.close();
driver.quit();
}
}
Running the above code, the get the following error :
Default suite
Total tests run: 5, Failures: 4, Skips: 0
I also see that it takes a lot of time (about 10 seconds) before the page is logged in even though that test passes. This does not happen when I run the code as a Java application

Can you show which tests are actually failing? if you are looking for order in testng test execution, it doesn't come by default , so if you have to run test2 after test1 and test3 after test2 etc then you have to use priority(lower the number higher the priority) for ex,
#Test(priority=1)
public void Test1() {
}
#Test(priority=2)
public void Test2() {
}
#Test(priority=3)
public void Test3() {
}
hope this helps
No, testng never guarantees ordering by default
TestNG relies on reflection. The Java Reflection APIs does not guarantee the method order when we use it to introspect a class to find out what are the test methods that are available in it. So the order of independent methods (Methods that dont have either soft or hard dependency) execution is never guaranteed.
Soft dependency - This is usually achieved in TestNG by using the priority attribute for the #Test annotation. Its called a soft dependency because TestNG will continue to execute all the methods even though a previous method with a higher priority failed.
Hard dependency - This is usually achieved in TestNG by using either dependsOnMethods (or) dependsOnGroups attribute for the #Test annotation. It's called a hard dependency because TestNG will continue to execute a downstream method if and only if an upstream method ran successfully.

By default testng executes methods in alphabetical order of the method names. Typically you would not be using main method for testng. Annotations along with priority are used to set the sequence of executions

Testng framework will run the test methods in alphabetical order. I could see your test methods are dependent and it should in the order. You can set the priorities for your test methods the way you want it to run.
You can refer the below link to set the priority.
TestNG priority set

Related

cucumber feature file not picking up Step Definition in Java class but there are no error in the console after running Junit

Project Structure-image Structure I am writing some cucumber tests for my java project. When running cucumber class there are no error occurred in the console but as per the step definition script i have given the script to invoke browser so as per my assumption the step definition class or the glue is not called by the cucumber class.
Can you please check and do let me know why it is not invoked.
Code:
#RunWith(Cucumber.class)
#CucumberOptions(
features={"F:/Selinium/practise-cucumber/practise1/features/login.feature"},
glue={"F:/Selinium/practise-cucumber/practise1/src/Stepdefinition/loginmethod.java"})
public class Runcucumber {
}
Step Definition code:
public class loginmethod {
public WebDriver driver ;
#Given("^User is on Home Page$")
public void user_is_on_home_page() throws Throwable{
System.out.println("homepagre");
System.setProperty("webdriver.chrome.driver",
"F:/Selinium/practise-cucumber/practise1/driver/chromedriver1.exe");
WebDriver driver = new ChromeDriver();
driver.get("https://www.google.com/");
System.out.println("lUNCHED homepagre");
}
Browser should be invoked
Console output
Structure
Can you please change your Runcucumber class name to RuncucumberTest then try again. It happened me one time.
#RunWith(Cucumber.class)
#CucumberOptions(
features={"F:/Selinium/practise-cucumber/practise1/features/login.feature"},
glue={"F:/Selinium/practise-cucumber/practise1/src/Stepdefinition/loginmethod.java"})
public class RuncucumberTest {
}

How to handle browser invocation in parallel tests using TestNG

I have been using browser invocation in #Beforeclass TestNG method using the parameter passed from testng.xml. Once the browser is invoked, I am using login test in a #BeforeMethod which is required for all the other #Tests to start. But with this setup, I am unable to run the tests in parallel. I am seeing one browser is open and login tests which is required by both tests are run in same browser and fails. All my tests are in single class file. Code structure is as below:
public class MainTest {
WebDriver driver;
BrowserFactory browser;
ReadData crmdatafile;
#BeforeClass(alwaysRun = true)
public void setup(ITestContext context) throws Exception{
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("datafile.txt").getFile());
crmdatafile = new ReadData(file.getAbsolutePath());
browser = new BrowserFactory(context.getCurrentXmlTest().getParameter("Selenium.browser"));
driver = browser.getNewBrowser();
driver.manage().deleteAllCookies();
driver.get(crmdatafile.data.get("enviornment", "url"));
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
}
#BeforeMethod()
public void login(){
System.out.println("contains the code for login which needs to be run before every test");
}
#AfterMethod
public void afterEachTest(ITestResult result) throws IOException {
driver.close();
}
#Test
public void Test1() {
System.out.println("Will run login and next steps");
}
#Test
public void Test2() {
System.out.println("Will run login and next steps");
}
public class BrowserFactory {
private WebDriver driver;
private String browser;
public BrowserFactory(String browser) {
String brow=browser.trim().toLowerCase();
if(!(brow.equals("firefox") || brow.equals("ff") || brow.equals("internetexplorer") || brow.equals("ie") || brow.equals("chrome") || brow.equals("gc"))) {
browser="ie";
}
this.browser = browser;
}
public WebDriver getNewBrowser() {
String brow = browser.trim().toLowerCase();
if(brow.equals("firefox") || brow.equals("ff")) {
System.setProperty("webdriver.gecko.driver", "drivers\\geckodriver.exe");
DesiredCapabilities capabilities = DesiredCapabilities.firefox();
capabilities.setCapability("marionette", true);
driver = new FirefoxDriver(capabilities);
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
return driver;
}else if(brow.equals("internetexplorer") || brow.equals("ie")){
driver = new InternetExplorerDriver();
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
return driver;
}else if(brow.equals("chrome") || brow.equals("gc")){
System.setProperty("webdriver.chrome.driver", "drivers\\chromedriver.exe");
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
ChromeOptions options = new ChromeOptions();
options.addArguments("test-type");
capabilities.setCapability("webdriver.chrome.binary","drivers\\chromedriver.exe");
capabilities.setCapability(ChromeOptions.CAPABILITY, options);
driver = new ChromeDriver(capabilities);
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
return driver;
}
return null;
}
How can I improve the above structure to run tests in parallel and using a different browser for each test?
Your test code has some issues.
You are instantiating a webdriver instance in your #BeforeClass annotated method and that is being shared by all your #Test annotated test methods. You are also invoking driver.close() in an #AfterMethod annotated method.This is a recipe for disaster because AFAIK driver.close() is equivalent to driver.quit() if you are having only one web browser instance. So what this means is that your second test method will not have a valid browser (if you are running sequentially).
If you are running in parallel, then all your test methods are going to be competing for the same browser, which is now going to cause race conditions and test failures.
You should ideally speaking move the logic of your setup() method into a listener which implements IInvokedMethodListener interface and then have this listener inject the webdriver instances into a ThreadLocal variable, which your #Test methods can then query.
You can refer to my blog post which talks in detail on how to do this.
Please check if that helps.
Here is the thing, as far as I can see you're not using annotations right and (probaly) testNG as well.
If you want to create browser instance before each test you may want to use #BeforeTest annotation. Also you may perform your test set up in this method as well. #BeforeClass annotation will be executed only once before this particular class will be executed.
It's a good idea to split tests that do different things into separate test files, case your tests do almost the same, but say params for tests are different - it's a good idea to use #DataProvider. Otherwise maybe you may want to extend your basic test with setup.
If you just want to re-execute same tests, but with different browser - consider relaunching your test job with different params or using #DataProvider as described above.
As far as I remember there are several ways to run testNG in parallel: Methods, Classes, Tests, Instances - figure out which one you need and which one works better with your setup.

One of the #Test code block doesn't execute

The TocheckApproval() code block doesnot get executed
Can someone please suggest why this is happening and what steps do i need to take to execute both the #Test blocks
I'm not sure whether method order is guaranteed by TestNG framework.
If you want the method order like run the test only after some tests ran (and marked as PASS), you can use dependsOnMethods or dependsOnGroups
Eg:
import org.junit.FixMethodOrder;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.testng.asserts.Assertion;
public class TestExample {
#BeforeTest
public void beforetest(){
System.out.println("before test ");
}
#Test
public void Tocheckapproval() {
System.out.println("in the method: Tocheckapproval");
}
#Test(dependsOnMethods = {"Tocheckapproval"})
public void TocheckRequestDecline() {
System.out.println("in the method: TocheckRequestDecline");
}
#AfterTest
public void aftertest() {
System.out.println("after test");
}
}
If you want to define the method order of your choice and the tests should not depend on other tests, then instead of dependecyOn* (methods, groups), you can use method Interceptors.
method Interceptors provides the list of test methods that are going to run as one of the argument, then you can re-arrange as per your needs.
References:
http://testng.org/doc/documentation-main.html#methodinterceptors
http://beust.com/weblog/2008/03/29/test-method-priorities-in-testng/
You haven't set any test priorities, that's why!
This is very easy to do, just stick the priority next to your #Test tag.
#Test (priority=1)
public void ToTestApproval(){
//do some stuff
}
#Test (priority=2)
public void ToCheckRequestDecline(){
//do some more stuff
}
As Naveen, mentioned above you can further refine the desired behaviour by using dependsOnMethods and dependsOnGroups.
PS. If this does not work, then it could be down to the #Test tag itself. Please double check that you are using TestNG annotation instead of Junit!
Best of luck!

When I run a test suite with ChromeDrive Chrome is opened at every test

I'm trying to use the same code with Appium driver and Java , TestNG but with ChromeDriver I changed the configuration by adding that code :
File file = new File("C:/QA/Emna/chromedriver.exe");
System.setProperty("webdriver.chrome.driver", file.getAbsolutePath());
WebDriver driver = new ChromeDriver();
The problem is that any test case the chrome window is opened a new one, even if my tests are in a correct order with Priority (by TestNG).
Is there a way to work in only one window?
WebDriver driver = new ChromeDriver(); is what opens a new browser each time. Move it to #BeforeClass section and use the same instance in all the tests.
You need to move you code snippet in any #Before type of TestNG methods. Lets say your all test cases are in a TestNG class then
Here is how it should look like:
#BeforeClass
public void deSetup(){
File file = new File("C:/QA/Emna/chromedriver.exe");
System.setProperty("webdriver.chrome.driver", file.getAbsolutePath());
WebDriver driver = new ChromeDriver();
}
But if this is not the case, what I mean by this, that your test cases are spread across the multiple TestNG classes then the best way is to have a Singleton class to load and initialize the ChromeDriver. Call method of the Singleton class to instantiate the ChromeDriver in any one of method annotated as #BeforeSuite #BeforeTest or #BeforeGroups. And have a reference variable of WebDriver type in evelry test class and assigne the previously initialized ChromeDriver to this reference variable in #BeforeClass method.
In such a way, ChromeDriver will be instantiated only once when any one of #BeforeSuite #BeforeTest or #BeforeGroups method runs and will be available in every TestNG class once #BeforeClass runs.
This way you can work in only one Chrome window.
I have fixed my problem by this way in #BeforeClass:
#BeforeClass
public static void before() {
// check active session
System.out.println("Becore Test Method");
File file = new File("C:/QA/Emna/chromedriver.exe");
System.setProperty("webdriver.chrome.driver", file.getAbsolutePath());
wd = new ChromeDriver();
}
I made an instance like that:
static WebDriver driver ;
Then in every test I put the following :
#Test
public static void run1() {
//my tests using wd
}
#Test
public static void run2() {
//my tests using wd
}

How to run all cucumber functional automated test cases in single browser

I am new to cucumber testing as well as selenium testing.Please help me to run all cucumber test cases in single browser.As for now i am creating new WebDriver object in each cucumber step_def for feature file.
The solution is, Using / passing the same Web Driver object across your step_def. From your Question i assume, you have multiple Step Def files, If the stories are small and related put all of them in a single step_def file and have a single Web driver object. If it is not the case, invoke every step_def with a predefined Driver object that is globally declared in the configuration loader.
For using one browser to run all test cases use singleton design pattern i.e make class with private constructor and define class instance variable with a private access specifier.Create a method in that class and check that class is null or not and if it is null than create a new instance of class and return that instance to calling method.for example i am posting my code.
class OpenBrowserHelp {
private WebDriver driver;
private static OpenBrowserHelp browserHelp;
private OpenBrowserHelp() {
this.driver = new FirefoxDriver()
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.manage().window().maximize();
}
public static OpenBrowserHelp getOpenBrowserHelp() {
if (null == browserHelp) {
browserHelp = new OpenBrowserHelp();
}
return browserHelp;
}
WebDriver getDriver() {
return driver
}
void setDriver(WebDriver driver) {
this.driver = driver
}
public void printSingleton() {
System.out.println("Inside print Singleton");
}
Now, where ever you need to create browser instance than use
WebDriver driver = OpenBrowserHelp.getOpenBrowserHelp().getDriver();

Resources