TestNG Dataprovider closing driver after each iteration - java

I am trying to run a dataprovider based test using ANT. My main class points to testNG file
XmlSuite suite=new XmlSuite();
suite.setName("Test Results");
suite.setPreserveOrder(true);
List<XmlSuite> suits=new ArrayList<XmlSuite>();
suits.add(suite);
List<XmlPackage> xpackage=new ArrayList<XmlPackage>();
xpackage.add(new XmlPackage(TestProperties.TESTNG_PACKAGE.toString()));
XmlTest test=new XmlTest(suite);
test.setPackages(xpackage);
String groups=TestProperties.TESTNG_GROUP.toString();
System.out.println("groups are:"+groups);
String groupArray[]=groups.split(",");
List<String> includedGroups=new ArrayList<String>();
includedGroups.addAll(Arrays.asList(groupArray));
test.setIncludedGroups(includedGroups);
TestNG tng=new TestNG();
tng.setOutputDirectory("test-output");
tng.setXmlSuites(suits);
tng.run();
System.exit(0);
Now, in my Testcase file, I have
#BeforeClass(alwaysRun = true)
public void pretest() throws IOException, GeneralSecurityException {
Pretest
}
#Test(groups= {"indicatorGroup","",""},description = "Validate indicator uploaded", dataProvider = "getIndicatorData")
public void indicatorUpload(String txt){
test
}
#DataProvider
public Object[] getIndicatorData() throws IOException, GeneralSecurityException
{
bla bla
for(int i=0; i<contents.length; i++) {
System.out.println(contents[i]);
if(!contents[i].contains("README")) {
blah blah
System.out.println(path);
names.add(path);
}
}
String[] myArray = new String[names.size()];
names.toArray(myArray);
return myArray;
}
#AfterClass(alwaysRun = true)
public void afterMethod() throws IOException {
System.out.println("Deleting all files after operation.....");
}
The problem is, they run without any issues, if i run from Testng. ie if i right click on the file, click on run, click on Run as Testng Test.
But if I run from my build file, after the first iteration, the driver I bring up in before class, closes and the rest of the tests fail. This causes my tests to fail in jenkins.
Can someone please help me out?

After many trials, I found out that the testng xml created By my trigger file had
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="IndicatorSuite" data-provider-thread-count="1">
<test name="Test Basics 1">
<groups>
<run>
<include name="indicatorUpload" />
</run>
</groups>
<classes>
<class name="Uploads.IndicatorFileUpload">
<class name="Uploads.IndicatorFileUpload1">
<class name="Uploads.IndicatorFileUpload2">
</methods>
</class>
</classes>
</test>
</suite>
Even though my test group was correct, I had given test package, because of which all my testcase files had been added as classes. All of these had a listener which would close the driver after testrun. I dont know much about testng, but I think it mixed up the listeners. In my Trigger file, when I added just
TestNG tng=new TestNG();
tng.setOutputDirectory("test-output");
//tng.setXmlSuites(suits);
tng.setTestClasses(new Class[] { IndicatorFileUpload.class });
tng.run();
it worked!

Related

TestNG: Test Method In Second Class of Test Suite Being Called Only Once

I have two test methods in different classes. The first method, let's say "createCustomer" is using dataProvider to get the inputs from an excel file and creates three customers.
#Test(dataProvider = "createCustomerTestData", dataProviderClass = createCustomerDataProvider.class)
public void addStockAccountWithAllInput(ITestContext context) throws JsonProcessingException {
//Rest-Assured code goes here
ISuite suite = context.getSuite();
suite.setAttribute("customerID", js.get("customerID"));
}
The second method, let's say "getCustomer" is supposed to get the id of the customers from output of "createCustomer" method and use them as input, using ITestContext and ISuite.
#Test
public void testGetCustomer(ITestContext context) {
ISuite suite = context.getSuite();
//Rest-Assured code goes here
Assert.assertEquals(js.getString("customerID"), suite.getAttribute("customerID"));
}
When I run the test suite from the testng xml file, only the id of the third created customer will be passed to "getCustomer" method.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="All Test Suite">
<test verbose="2" preserve-order="true"
<classes>
<class name="addCustomer">
<methods>
<include name="testAddCustomer"/>
</methods>
</class>
</classes>
</test>
<test verbose="2" preserve-order="true"
<classes>
<class name="getCustomer">
<methods>
<include name="testGetCustomer"/>
</methods>
</class>
</classes>
</test>
</suite>
How can I change the settings or the code so that the "getCustomer" method gets called every time createCustomer is called and a customer created?
This would work for you.
//Create a temp list of String to save ID
static List<String> ids = new ArrayList<>();
#Test(dataProvider = "createCustomerTestData", dataProviderClass = createCustomerDataProvider.class)
public void addStockAccountWithAllInput(ITestContext context) throws JsonProcessingException {
//Rest-Assured code goes here
ISuite suite = context.getSuite();
String id = js.get("customerID");
ids.add(id);
suite.setAttribute("customerIDs", ids);
}
#Test
public void testGetCustomer(ITestContext context) {
ISuite suite = context.getSuite();
//Make api call based on the list IDs from above test
for (int i = 0; i < suite.getAttribute("customerIDs").size(); i++){
//Rest-Assured code goes here
Assert.assertEquals(js.getString("customerID"), suite.getAttribute("customerIDs").get(i));
}
}

Java Selenium Testng - Factory not working on Windows

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>

DataProvider parallel text input - multithreading issue

I want to realize parallel test run with DataProvider for testing an input field.
Expected Result:
Parallel tests for each text in DataProvider
Open page
Write "Text1" (or "Text2" or "Text3")
Press "Search" button
Actual Result:
One test with every strings in DataProvider as one
Open page
Write "Text1Text2Text3" (why so?)
Press "Search" button
How I can solve this problem where every string in DataProvider inputing into the field?
Here is my code bellow.
TestNG.xml:
<suite name="TestParallel" parallel="tests" thread-count="2" data-provider-thread-count="2" preserve-order="false" >
<test name="ChromeTest">
<parameter name="browser" value="Chrome" />
<classes>
<class name="com.test.DataProviderTestParallel"/>
</classes>
</test>
<test name="FirefoxTest">
<parameter name="browser" value="Firefox" />
<classes>
<class name="com.test.DataProviderTestParallel"/>
</classes>
</test>
<test name="EdgeTest">
<parameter name="browser" value="Edge" />
<classes>
<class name="com.test.DataProviderTestParallel"/>
</class>
</classes>
</test>
</suite>
Test:
#BeforeTest
#Parameters("browser")
public static void initSelenium(String browser) throws Exception {
// Check if parameter passed from TestNG is 'firefox'
if(browser.equalsIgnoreCase("firefox")){
// Create firefox instance
FirefoxDriverManager.getInstance().setup();
driver = new FirefoxDriver();
}
// Check if parameter passed as 'chrome'
else if(browser.equalsIgnoreCase("chrome")){
ChromeDriverManager.getInstance().setup();
driver = new ChromeDriver();
}
// Check if parameter passed as 'Edge'
else if(browser.equalsIgnoreCase("Edge")){
EdgeDriverManager.getInstance().setup();
driver = new EdgeDriver();
}
else{
// If no browser passed throw exception
throw new Exception("Browser is not correct");
}
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
#DataProvider(name = "forSearch", parallel = true)
public Object[] forSearch() {
return new Object[]{
"Text1",
"Text2",
"Text3"
};
}
#Test(description = "Search text", dataProvider = "forSearch")
public void searchWithButton(String searchText) {
SupportPageObject supportPage = new SupportPageObject();
SearchResultPageObject searchResultPage = new SearchResultPageObject();
supportPage.open();
supportPage.isOpen();
// Input text into field
supportPage.writeQuestion(searchText);
// Press "search" button
supportPage.searchWithButton();
searchResultPage.isOpen();
}
UPD: I've found that this issue reproducing when i have data-provider-thread-count is bigger than 1.
In that case it opens thread-count number of windows and then on the last one input data-provider-thread-count times text from DataProvider.
But still has no idea how to fix it and enter the DataProvider text into each opened window separately.
You need to return an Object[][].
#DataProvider(name = "forSearch", parallel = true)
public Object[][] forSearch() {
return new Object[][]{
new Object[] { "Text1"},
new Object[] { "Text2"},
new Object[] { "Text3"}
};
}

TestNG does not continue execute tests after failure

I have test automation framework with a page object model.
All my test are located in separate classes in same package.
In testng.xml i have
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Smoke Test">
<test name="SmokeTest">
<classes>
<class name="name.test1"/>
<class name="name.test2"/>
<class name="name.test3"/>
</classes>
</test>
</suite>
Problem is that after running TestNG.xml if the 1st test will fail, it will stop test execution. But i want to continue executing of all test cases.
I use Jenkins on my project and if one of the tests are failed it stops execution immediately.
Example of test
public class LoginTestTest {
public AndroidDriver<AndroidElement> driver;
public AOWebClient aoWebClient;
AOWebClient aoWeb;
public LoginTestTest(AndroidDriver<AndroidElement> driver, AOWebClient aoWeb){
this.driver = driver;
this.aoWeb = aoWeb;
PageFactory.initElements(new AppiumFieldDecorator(driver), this);
}
public LoginTestTest() {
}
SoftAssert softAssert = new SoftAssert();
#BeforeClass
public void setUp() throws Exception {
driver = DesiredCapabilitiesSetup.startAppiumServer();
aoWebClient = DesiredCapabilitiesSetup.getAOWeb();
LogIn logIn = new LogIn(driver,aoWebClient);
logIn.logIn();
}
#org.testng.annotations.Test
public void goToSettings() throws InterruptedException {
HeaderMenu header = new HeaderMenu(driver,aoWeb);
HamburgerMenuList ham = new HamburgerMenuList(driver);
header.clickHamburgerButton();
header.clickHamburgerButton();
header.editButtonClick();
softAssert.assertAll();
}
#AfterClass
public void tearDown(ITestResult result) throws Exception {
if (result.getStatus() == ITestResult.FAILURE) {
TakeScreenshot screenshot = new TakeScreenshot();
screenshot.TakeScreenshot("screenshots/");
}
LogOut logOut = new LogOut(driver,aoWeb);
logOut.logOut();
}
}
If my test will fail in #Test it will never continue to #AfterClass method.
And I want that if #Test fail it will continue to #AfterClass method and After This Class continue executes test from other classes from testng.xml.
Your suite tag in your xml should include configfailurepolicy="continue". This tells testng that even though a config failed in one class, you still want to run other classes in that suite. See "configfailurepolicy" in the documentation.
So your xml would become:
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Smoke Test" configfailurepolicy="continue">
<test name="SmokeTest">
<classes>
<class name="name.test1"/>
<class name="name.test2"/>
<class name="name.test3"/>
</classes>
</test>
</suite>
From the documentation:
alwaysRun: For after methods (afterSuite, afterClass, ...): If set to
true, this configuration method will be run even if one or more
methods invoked previously failed or was skipped.
Then, just replace your #AfterClass by #AfterClass(alwaysRun = true).
Add below attribute in testng.xml file under Suite syntax
<suite thread-count="25" name="Smoke" parallel="classes" skipfailedinvocationcounts="true">
Work for me, hope it will work for you as well :)

NullPointer exception in TestNG while run test using xml

Try to automate my test using TESTNG framework in eclipse.
In Project I use one packet iEDGE and write all test methods in single Class named eLogin.
But when I try to execute the code it shows nullPointer exceptions.
Following is my sample code and xml settings that I use to run my test case.
Can any one help me to resolve my problem.
Package com.iEDGE;
public class eLogIn {
private WebDriver driver;
private String baseUrl;
private boolean acceptNextAlert = true;
private StringBuffer verificationErrors = new StringBuffer();
#Parameters ( { "platform", "browser", "ver" } )
#BeforeMethod (alwaysRun=true )
public void setUp(#Optional String platform , #Optional String browser , #Optional String version ) throws Exception {
baseUrl = "Gmail URL";
DesiredCapabilities mCapability = new DesiredCapabilities();
if (platform.equalsIgnoreCase("WINDOWS")){
mCapability.setPlatform(org.openqa.selenium.Platform.WINDOWS);
}
if (browser.equalsIgnoreCase("Firefox")) {
mCapability = DesiredCapabilities.firefox();
mCapability.setVersion("40");
}
driver = new RemoteWebDriver(new URL(baseUrl), mCapability);
driver.manage().timeouts().implicitlyWait(1000, TimeUnit.MILLISECONDS);
driver.get(baseUrl);
driver.findElement(By.cssSelector("input[name=username]")).clear();
driver.findElement(By.cssSelector("input[name=username]")).sendKeys("username");
driver.findElement(By.cssSelector("input[name=password]")).clear();
driver.findElement(By.cssSelector("input[name=password]")).sendKeys("password");
driver.findElement(By.id("button-1015-btnInnerEl")).click();
}
//OTEHR TEST METHODS ....
}
TESTSuite.xml Settings
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite guice-stage="DEVELOPMENT" name="Default suite">
<test verbose="2" name="Default test">
<parameter name="platform" value="Windows"/>
<parameter name="browser" value="Firefox"/>
<parameter name="ver" value="40.0.3"/>
<classes>
<class name="com.iEDGE.eLogIn"/>
</classes>
</test> <!-- Default test -->
</suite> <!-- Default suite -->
Since all your parameter are annotated with #Optional, you will have to check if they are null before calling their methods. So, for example, you will have to do something like this:
if(platform != null){
if (platform.equalsIgnoreCase("WINDOWS")){
mCapability.setPlatform(org.openqa.selenium.Platform.WINDOWS);
}
}
Do this for all the instructions that involves these optional parameters.
You are passing wrong URL into " RemoteWebDriver(new URL(baseUrl), mCapability); "
You should pass selenium server url like below:
new RemoteWebDriver( new URL("http://localhost:4444/wd/hub"),
mCapability);
For more details follow:
seleniumHq
Let me know if you have any concern
Thanks
Sadik
you are intializing wrong Base url.
is supposed to be
baseUrl = "http://127.0.0.1:4888/wd/hub";
you have to mention which transfer protocol is used in your local host.

Categories

Resources