I have a java class that opens up two Chrome browsers, searches for "test 1" and "test 2", respectively. However, once both browsers open, only one browser with the google page will search for "test 1 test 2".
I believe this issue may be because I am calling the driver = new WebDriver from a parent class. However, I am not sure how to resolve the issue.
Here are my two methods that I am trying to run in parallel.
package webDrivertests;
public class googleTestClass extends Methods{
#Test
public void test1() throws InterruptedException {
googleTestClass object1;
object1 = new googleTestClass();
object1.launchBrowser();
object1.goToURL("https://www.google.com");
object1.enterValue("name","q","google test 1");
driver.quit();
}
#Test
public void test2() throws InterruptedException {
googleTestClass object2;
object2 = new googleTestClass();
object2.launchBrowser();
object2.goToURL("https://www.google.com");
object2.enterValue("name","q","google test 2");
driver.quit();
}
}
This is my xml file I use to call them.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="methods">
<test thread-count="2" name="Test" parallel="methods">
<classes>
<class name="webDrivertests.googleTestClass"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
The parent method that includes the driver
package webDrivertests;
// import statements
public class Methods {
public static WebDriver driver;
public void launchBrowser() {
System.setProperty("webdriver.chrome.driver","C:\\chromedriver_win32\\chromedriver.exe");
System.setProperty("webdriver.chrome.args", "--disable-logging");
System.setProperty("webdriver.chrome.silentOutput", "true");
driver = new ChromeDriver();
}
public void goToURL(String url) {
driver.get(url);
}
public void enterValue(String htmltype, String identifier, String value) throws InterruptedException {
if (htmltype == "id") {
WebElement element = driver.findElement(By.id(identifier));
element.clear();
element.sendKeys(value);
element.submit();
}
if (htmltype =="name") {
WebElement element = driver.findElement(By.name(identifier));
element.clear();
element.sendKeys(value);
element.submit();
}
Thread.sleep(3000);
}
}
Current Result: Two browsers are opened and each go to google.com. However only one browser will search for "test 1 test 2". Any help is appreciated! If possible, I would still like to use my parent class "Methods" as it contains a lot of methods I am using for my other real test cases.
Thanks in advance.
The problem lies in your test code. WebDriver object is being declared as a static object.
So this causes every test method to share the same instance.
To fix the problem remove the static keyword from the WebDriver declaration in your Methods class and try again.
Because of static declaration of the driver object in the class, it get's overridden parallel execution when second test called launchBrowser().
Obviously removing static will fix this issue but still you will fall in different issues of managing driver while your test bed and methods increase.
I would recommend to use any of TestNG extension that takes care of such requirement. We are using QAF which is built upon TestNG and provides driver management, resource management and many more features which are crucial for web/mobile/webservices testing.
Related
I have a Base class with a method to open my URL that is called as #BeforeMethod in my test cases. The method takes a string argument for browser type which determines which browser is called. I am attempting to set a parameter in my xml launch file that can be inputted in my #BeforeMethod as argument for the openURL method.
Here is my XML file:
<?xml version="1.0" encoding="UTF-8"?>
<suite name="FullRegressionSuite" parallel="false">
<listeners>
<listener class-name="reporting.CustomReporter"></listener>
</listeners>
<test name="Test">
<parameter name ="browserType" value="Chrome"/>
<classes>
<class name="reporting.reporterTest"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
Here are my tests:
#Listeners(CustomListener.class)
public class reporterTest extends Base {
#Test
public void testOne() {
Assert.assertTrue(true);
}
#Test
public void testTwo() {
Assert.assertTrue(false);
}
#Parameters({ "browserType" })
#BeforeMethod
public void setUp(String browserType) throws InterruptedException {
System.out.println(browserType);
openURL(browserType);
}
#AfterMethod
public void tearDown() {
driver.quit();
}
}
Here is my base class:
public class Base {
public static WebDriver driver = null;
//CALL WEB BROWSER AND OPEN WEBSITE
public static void openURL(String browser) throws InterruptedException {
//launches browser based on argument given
try{
if (browser == "Chrome") {
System.setProperty("webdriver.chrome.driver", "/Users/rossdonohoe/Desktop/SeleniumJava/Drivers/chromedriver");
driver = new ChromeDriver();
}
else if (browser == "Firefox") {
System.setProperty("webdriver.gecko.driver", "/Users/rossdonohoe/Desktop/SeleniumJava/Drivers/geckodriver");
driver = new FirefoxDriver();
}
else {
System.out.println("Error: browser request not recognized");
}
driver.manage().deleteAllCookies();
driver.manage().window().maximize();
driver.get("https://www.google.com");
}
catch(Exception E) {
E.printStackTrace();
}
}
}
My #BeforeMethod is definitely receiving the parameter, as I'm printing its value to check and I'm getting "Chrome" in the console. However, openURL is failing at the 'delete all cookies' line with a null pointer exception (and my line "Error: browser request not recognized' is being printed in console), indicating that the string is not reaching openURL as an argument. Can anyone see what I'm doing wrong?
As the browser is a String variable , you need to use equals or contains or equalsIgnoreCase to check if the browser that you are fetching is "Chrome" or "Firefox".
So you need to use: if(browser.equals("Chrome")) and if(browser.equals("Firefox")) as the conditions instead of the conditions that you have used.
I want to log name of the test suite before running it. I succeed on logging method names but couldn't figure out how I can do the same thing with suites. My code:
EDIT: I found the solution. Here is the code for those who need it.
public class TestCase {
private Logger logger = LogManager.getLogger(this.getClass());
protected static WebDriver driver;
private String url = PropertyManager.getUrl();
private String browser = PropertyManager.getBrowser();
#BeforeSuite
protected void setUp(ITestContext tes) {
System.setProperty("webdriver.chrome.driver","chromedriver.exe");
System.setProperty("webdriver.chrome.logfile", "chromedriver.log");
System.setProperty("webdriver.chrome.verboseLogging", "true");
driver = new ChromeDriver();
driver.get(url);
driver.manage().window().maximize();
logger.info("Starting up {} driver.", browser);
logger.info(tes.getSuite().getName());
}
This can be done by adding Listener in the project. Use IInvokedMethodListener to perform activities before invocation of intended method.
Steps:
Create a class lets say ListenerClass and implement IInvokedMethodListener interface in it.
public class ListenerClass implements IInvokedMethodListener
Add all unimplemented method and add below code in beforeInvocation method :
#SuppressWarnings("deprecation")
#Override
public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
try {
if (method.getTestMethod().getMethod().getAnnotation(org.testng.annotations.BeforeSuite.class)
.toString() != null) {
System.out.println("Before suite annoted method name - " + method.getTestMethod().getMethodName());
System.out.println("Test suite name - " + testResult.getTestContext().getSuite().getName());
}
} catch (Exception e) {
}
}
Add the listener class in your testng.xml file
<listeners>
<listener class-name="ListenerClass"></listener>
</listeners>
<test name="Test_Name">
<classes>
<class name="Test_Class_Name" />
</classes>
</test> <!-- Test -->
Run testng.xml as TestNGSuite you will get the expected result. Let me know if any thing is there
I set up a project using Intellij on Linux using Selenium and Testng using the factory method with dataProviders. On Linux the process runs as the following:
**Data 1:**
initialize
second
AfterTest
**Data 2**
initialize
second
AfterTest
But when I transferred the project onto a Windows machine, installed all of the libraries (still using intellij) I get the following output:
Initialize
Initialize(1)
second
second (1)
AfterTest
I'm not too sure why I'm getting differences since it's the same code. Please see the code below:
#DataProvider(name = "data")
public static Object[][] data() {
// This is where I get the data from
}
#Factory(dataProvider = "data")
public TestSuite1(Data data)
{
super();
this.data = data;
}
#Test(priority = 1, description = "First test")
public void initialize()
{
System.out.println("DO THIS FIRST");
}
#Test(priority = 2, description = "Do this after")
public void second()
{
System.out.println("DO THIS AFTER");
}
#AfterClass
public void AfterTest() throws InterruptedException
{
System.out.println("I HAVE FINISHED THE TEST");
}
I see here :https://howtodoinjava.com/testng/testng-factory-annotation-tutorial/ That "#Factory" must be used with "#DataProvider" to test ...
I didn't see "#DataProvider" in your code ... and it seem to not use a correct form of code for TestNG...
That could be why there is a difference ...
You have to check your testNg xml file as well. since I cannot see your any test steps use data from data provider. Your second script is similar to parallel test execution. please make sure your suite details like below.
<suite name="Suite" parallel="false" thread-count="0" verbose="2">
<test name="TestName"> <!--Do not add any other unless its necessary-->
<classes>
<class name="className"/>
</classes>
</test>
I'm trying to automate a website testing using testNG.
Let assume I have created 3 test cases one for each webpage(although there are more than 50 test cases in my case but just for simplifying the issue I have considered 3 only).
Now, my starting 2 test cases are passing but my 3rd test case is getting failed. I am making the code change to that 3rd page and I want just to run that 3rd test case but when I am running my code, everytime new IE driver instance is getting created and testing starts from beginning.
How to use existing driver instance and test the 3rd webpage only. I tried googling this out but couldn't find anything useful.
Any help would be appreciated.
If you want to ignore particular test, you can use this snippet:
import org.testng.Assert;
import org.testng.annotations.Test;
public class IgnoreTest {
#Test(enabled = false) // this test will be ignored
public void testPrintMessage() {
System.out.println("This test is ignored");
}
#Test
public void testSalutationMessage() { // this will be executed
System.out.println("Test works");
}
}
When you execute this class, it will be only second test executed. I don't know if you have stored all 50 tests in one class(hopefully not), but if yes, there is a possibility to group your tests. To be able to do this you can use this sample:
import org.testng.Assert;
import org.testng.annotations.Test;
public class GroupTestExample {
#Test(groups = { "functest", "checkintest" })
public void testPrintMessage() {
System.out.println("Inside testPrintMessage()");
}
#Test(groups = { "checkintest" })
public void testSalutationMessage() {
System.out.println("Inside testSalutationMessage()");
}
#Test(groups = { "functest" })
public void testingExitMessage() {
System.out.println("Inside testExitMessage()");
}
}
then xml file would be like this:
<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name = "Suite1">
<test name = "test1">
<groups>
<run>
<include name = "functest" />
</run>
</groups>
<classes>
<class name = "GroupTestExample" />
</classes>
</test>
</suite>
then after compiling your test classes, use this command:
C:\TestNG_WORKSPACE>java -cp "C:\TestNG_WORKSPACE" org.testng.TestNG testng.xml
More explained information you will get in this tutorials:
ignore tests
group tests
I have two test cases need to be executed.
Login as admin
Do some action
I'm using TestNG and Cucumber BDD for executing the test cases. Now I execute the project as TestNG and from testng.xml it will run the two test cases one by one. First it will login and then do the action.
I'm using Page Factory method for page objects.
So, when I execute my project, the login test case is executed but it cannot find the element in that logged in screen/page, because it cannot find whether the browser is open or the webdriver instance is running.
This is my testng.xml code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Super admin">
<test name="Login as Admin">
<classes>
<class name="adminlogin"/>
</classes>
</test>
<test name="admin disable">
<classes>
<class name="admindisable"/>
</classes>
For adminlogin I have separate class and for admindisable I've separate class. So, when the admindisable is executed it cannot find the element on the page.
This is my login class code:
public class adminLoginTest {
/**
* Initialize the webdriver.
*/
private WebDriver driver = new FirefoxDriver();
/**
* Initialize
*/
private adminloginpage adminLoginDetails;
#When("login super admin")
public final void adminLogin(List<adminlogindetails> loginInfo) throws InterruptedException {
driver.get("site url");
adminLoginDetails = new adminloginpage(driver);
adminlogindetails loginInformation = loginInfo.get(0);
adminLoginDetails.getUserName().sendKeys(loginInformation.getUserName());
adminLoginDetails.getPassword().sendKeys(loginInformation.getPassword());
adminLoginDetails.getLoginBtn().click();
}
}
After this the admin is logged in.
Do some action code:
#When("Login for disable")
public void disableDeleteEditUserId(List<admindisabledeleteeditnfpadminuseriddetail> nfpDetails) {
nfpObjects = new admindisabledeleteeditnfpadminuseridpage(driver);
admindisabledeleteeditnfpadminuseriddetail nfpDetailInfo = nfpDetails.get(0);
nfpObjects.getNfpMenuLink().click();
nfpObjects.getNfpOrgLink().click();
nfpObjects.getAllTablink().click();
nfpObjects.getSearchBox().sendKeys(nfpDetailInfo.getSearchBox());
nfpObjects.getSearchButton().click();
}
In the do some action code, I don't know how to instantiate the webdriver or how to check the condition that the webdriver is already running? Because the problem is, it cannot find the link 'getNfpMenuLink' in the already logged in browser.
This is my page objects code:
/**
* Initialize web driver.
*/
private WebDriver driver;
/**
* Find the nfpMenuLink.
*/
#FindBy(xpath = "html/body/div[1]/div/div/div/div[2]/div[2]/div/div/ul/li[2]/a")
private WebElement nfpMenuLink;
/**
* #return nfpMenuLink.
*/
public WebElement getNfpMenuLink() {
return nfpMenuLink;
}
/**
* #param nfpMenuLink the nfpMenuLink.
*/
public void setNfpMenuLink(WebElement nfpMenuLink) {
this.nfpMenuLink = nfpMenuLink;
}
/**
* #param driver the driver.
*/
public Superadmindisabledeleteeditnfpadminuseridpage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
Any help is greatly appreciated. Thanks in advance.