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));
}
}
I built an automation framewoek using maven, java, testng, selenium.
As for now I am running my tests sequential and I would like to run them in parallel, however each time I try to run them in parallel there are several browsers that opens (like intended to) but I pay attention that only one window get the actions and other one opens (navigate to the url needed, but no action is being done beside it), I am using threads in order to initialize my webdriver and that they won't intefere each other in doing the actions.
This is my BaseTest class where I declare my webdriver and init it:
public class BaseUiTest extends BaseApiTest {
private static final Browser BROWSER = Browser.valueOf(EnvConf.getProperty("ui.browser.type"));
protected DriverWrapper driver;
protected LoginPage loginPage;
protected TopBar topBar;
protected CmsPage cmsPage;
#BeforeClass(alwaysRun = true)
public final void BaseUiSetup(ITestContext context) throws IOException {
driver = DriverWrapper.open(BROWSER, TEST_OUTPUT_FOLDER);
DriverFactory.getInstance().setDriver(driver);
driver = DriverFactory.getInstance().getDriver();
System.out.println("HEREREREREFSLKFSKJHFKJSHKJFSHKJFSHKJFSHKJFSHKJ");
loginPage = new LoginPage(driver);
cmsPage = new CmsPage(driver);
}
#AfterClass(alwaysRun = true)
public final void baseTeardown() {
Date testEndTime = new Date();
if (driver != null) {
printBrowserLog();
DriverFactory.getInstance().removeDriver();
}
Log.i("testEndTime=[%s]", testEndTime);
}
}
My DriverWrapper class only wrap the traditional WebDriver interface in this manner:
public class DriverWrapper implements WebDriver {
private final WebDriver driver;
private final static Logger Log = Logger.getLogger(DriverWrapper.class.getName());
private static final Duration WAIT_ELEMENT_TIMEOUT = new Duration(EnvConf.getAsInteger("ui.locator.timeout.sec"), TimeUnit.SECONDS);
private DriverWrapper(WebDriver driver){
this.driver = driver;
}
public static DriverWrapper open(Browser browser, File downloadsFolder) {
Log.info(String.format("Starting new %s browser driver", browser));
switch (browser) {
case FIREFOX:
return createFireFoxInst();
case CHROME:
return createChromeInst(downloadsFolder);
default:
throw new IllegalArgumentException("'" + browser + "'no such browser type");
}
}
private static DriverWrapper createChromeInst(File downloadsFolder){
WebDriverManager.chromedriver().setup();
ChromeOptions options = new ChromeOptions();
options.setHeadless(EnvConf.getAsBoolean("selenium.headless"));
options.setAcceptInsecureCerts(true);
options.addArguments("--lang=" + EnvConf.getProperty("selenium.locale"));
LoggingPreferences logPrefs = new LoggingPreferences();
logPrefs.enable(LogType.BROWSER, Level.SEVERE);
options.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);
options.addArguments("--window-size=" + EnvConf.getProperty("selenium.window_size"));
ChromeDriverService service = ChromeDriverService.createDefaultService();
ChromeDriver driver = new ChromeDriver(service, options);
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
//enabling downloading resources when driver is headless
enableHeadlessDownload(service, driver, downloadsFolder);
return new DriverWrapper(driver);
}
private static void enableHeadlessDownload(ChromeDriverService service, ChromeDriver driver, File downloadsFolder){
try(CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
Map<String, Object> commandParams = new HashMap<>();
commandParams.put("cmd", "Page.setDownloadBehavior");
Map<String, String> params = new HashMap<>();
params.put("behavior", "allow");
params.put("downloadPath", downloadsFolder.getAbsolutePath());
commandParams.put("params", params);
ObjectMapper objectMapper = new ObjectMapper();
String command = objectMapper.writeValueAsString(commandParams);
String u = service.getUrl().toString() + "/session/" + driver.getSessionId() + "/chromium/send_command";
HttpPost request = new HttpPost(u);
request.addHeader("content-type", "application/json");
request.setEntity(new StringEntity(command));
CloseableHttpResponse response = httpClient.execute(request);
Log.info(String.format("enable download, status code=[%d]", response.getCode()));
}catch (Exception e){
Log.error("failed to send command=[age.setDownloadBehavior] to chrome server");
Log.error(e.getMessage());
}
}
}
This is my DriverFactory class (where all the magic happens and where I defined my webdriver threads):
public class DriverFactory {
private DriverFactory() {}
private static DriverFactory instance = new DriverFactory();
public static DriverFactory getInstance() {
return instance;
}
ThreadLocal<DriverWrapper> driver = new ThreadLocal<>(); //thread local driver object for webdriver
public DriverWrapper getDriver() {
return driver.get();
}
public void setDriver(DriverWrapper driverParam){ //call this method to set the driver object
driver.set(driverParam);
}
public void removeDriver(){
driver.get().quit();
driver.remove();
}
}
And this is my testng.xml file:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
<suite name="Automation_Suite" parallel="tests" thread-count="4">
<test name="Critical tests to run after DEV deploy build">
<groups>
<run>
<include name="critical"/>
</run>
</groups>
<classes>
<class name="com.hackeruso.automation.ui.cms.categories.CategoriesTest"/>
</classes>
</test>
<test name="Critical tests to run after DEV deploy build2">
<groups>
<run>
<include name="critical"/>
</run>
</groups>
<classes>
<class name="com.hackeruso.automation.ui.cms.content_manager.ContentManagerPresentationTest"/>
</classes>
</test>
<test name="Critical tests to run after DEV deploy build3">
<groups>
<run>
<include name="critical"/>
</run>
</groups>
<classes>
<class name="com.hackeruso.automation.ui.cms.cyberpedia.TermsTest"/>
</classes>
</test>
<test name="Critical tests to run after DEV deploy build4">
<groups>
<run>
<include name="critical"/>
</run>
</groups>
<classes>
<class name="com.hackeruso.automation.ui.cms.institutions.ClassesTest"/>
</classes>
</test>
</suite>
And this is the profiles section in my pom.xml file that defines this profile(critical tests):
<profiles>
<profile>
<id>critical</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>critical_tests.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
This is a test class for example:
public class ContentManagerPresentationTest extends BaseUiTest {
private static final String PREVIEW_IMAGE_PATH = "/automation-tests/src/test/resources/images/lion.png";
private static final String PPT_FILE_PATH = "/automation-tests/src/test/resources/ppt/Google_Adword_Project.pptx";
private static final String NOT_EXIST_PRESENTATION_NAME = "Not Exist";
private ContentManagerPresentationsCMSPage contentManagerPresentationsCMSPage;
private VideosNPresentationsRow row;
#BeforeMethod(alwaysRun = true)
public void setUpMethod(){
adminSignIn();
topBar.clickItem(TopNavBarItem.CMS);
contentManagerPresentationsCMSPage = cmsPage.selectItemSidePanelDropDownMenu(SidePanelDropDownMenuOptions.CONTENT_MANAGER, "presentations");
Assert.assertTrue(contentManagerPresentationsCMSPage.verifyElement());
}
#AfterMethod(alwaysRun = true)
public void tearDownMethod(){
cmsPage.clickLogoutButtonAndVerify();
}
#Test(priority = 10, dataProvider = "cancelUploadPresentationsProvider", description = "Cancel upload a new presentation")
public void cancelUploadNewPresentation(String name, String desc, String previewImgPath, String pptFilePath, boolean toCreate) throws FileNotFoundException {
contentManagerPresentationsCMSPage
.uploadNewPresentationOrVideo(name, desc, previewImgPath, pptFilePath, toCreate);
Assert.assertTrue(contentManagerPresentationsCMSPage.verifyElement(), "Expected to be on presentation main page");
T_Logger.info("cancelling and returning to main presentation page is successful!");
}
#DataProvider(name = "cancelUploadPresentationsProvider")
public Object[][] cancelUploadPresentationsProvider(){
return new Object[][]{
{"Automation Test", "Automation Desc",
PREVIEW_IMAGE_PATH,
PPT_FILE_PATH,
false}
};
}
#Test(priority = 20, description = "Negative test for non exist presentation in the table")
public void verifyNonExistPresentationInTable(){
row = contentManagerPresentationsCMSPage.findRowByVideoName(NOT_EXIST_PRESENTATION_NAME);
Assert.assertNull(row);//, String.format("Row should be null, instead we got =[%s]", row.toString()));
T_Logger.info("Verification of not exist row in the table is successful");
}
#Test(priority = 25, dataProvider = "validationFieldsProvider", description = "Verify mandatory field requirements are fulfilled")
public void verifyMandatoryFieldsPresentation(String name, String desc, String imagePreviewPath,
String pptFilePath, boolean toCreate, int msgNumber, String expectedMsg) throws FileNotFoundException {
contentManagerPresentationsCMSPage
.uploadNewPresentationOrVideo(name, desc,
imagePreviewPath,
pptFilePath,
toCreate);
Assert.assertEquals(contentManagerPresentationsCMSPage.getActualErrorMsg(msgNumber), expectedMsg,
String.format("Expected error message=[%s] is not displayed as expected, instead actual message=[%s]",
expectedMsg, contentManagerPresentationsCMSPage.getActualErrorMsg(msgNumber)));
contentManagerPresentationsCMSPage.clickCreateOrCancel(false);
T_Logger.info("Verification of mandatory fields is successful");
}
#DataProvider(name = "validationFieldsProvider")
public Object[][] validationFieldsProvider(){
return new Object[][] {
{"", "Automation Desc", PREVIEW_IMAGE_PATH, PPT_FILE_PATH, true, 1, "Enter Presentation name"},
{"Automation Test", "Automation Desc", "", PPT_FILE_PATH, true, 2, "Preview Image is required"},
{"Automation Test", "Automation Desc", PREVIEW_IMAGE_PATH, "", true, 3, "Presentation file is required"}
};
}
#Test(priority = 30, dataProvider = "addNewPresentationsProvider", description = "Add new presentation",groups = {"critical"})
public void addNewPresentationAndVerify(String name, String desc, String previewImgPath, String pptFilePath, boolean toCreate) throws FileNotFoundException {
contentManagerPresentationsCMSPage
.uploadNewPresentationOrVideo(name, desc, previewImgPath, pptFilePath, toCreate);
row = contentManagerPresentationsCMSPage.findRowByVideoName(name);
Assert.assertEquals(row.getNameTxt(), name, String.format("Actual name is =[%s] not as expected", row.getNameTxt()));
}
#DataProvider(name = "addNewPresentationsProvider")
public Object[][] addNewPresentationsProvider(){
return new Object[][]{
{"Automation Test", "Automation Desc", PREVIEW_IMAGE_PATH, PPT_FILE_PATH, true}
};
}
#Test(priority = 35, dataProvider = "caseSensitiveProvider", description = "Validation existence of presentation - case sensitive")
public void searchTablePresentationsCaseSensitive(String pptName){
row = contentManagerPresentationsCMSPage.findRowByVideoName(pptName);
Assert.assertNotNull(row);
}
#DataProvider(name = "caseSensitiveProvider")
public Object[][] caseSensitiveProvider(){
return new Object[][] {
{"Automation Test"},
{"AUTOMATION TEST"}
};
}
}
The problem: when I run mvn test -Pcritical there are 4 chrome browsers which opens but the actions occur only in one browser (although I defined and manage my webdrivers as threads to handle each one in his own thread), what am I missing?
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!
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"}
};
}
Given the following codes:
public class NewTest {
private Object _foreground = null;
#BeforeGroups("regression")
public void setUp() {
System.out.println("executed? setUp");
_foreground = new MyObject();
}
#Test(groups="regression")
public void testMyObjectToString() throws Exception {
System.out.println("??? ");
System.out.println(_foreground == null);
String value = _foreground.toString();
Assert.assertTrue(value != null);
}
}
And the testNG.xml:
<groups>
<run>
<include name="regression" />
</run>
</groups>
<classes>
<class name="com.automation.test.NewTest"/>
</classes>
When I tried to run this, the print statements say:
???
true
So that means _foreground is null, meaning the setUp method is not executed.
TestNG also shows java.lang.NullPointerException on the line:
String value = _foreground.toString();
However I have no idea what I missed. Looks to me the "regression" group will be run and the setUp method with #beforeGroup will be run before testMyObjectToString with #Test. Apparently this is not what is happening..
It is a very stupid mistake that maybe someone new to testNG may make...
#BeforeGroups("regression")
This is a wrong usage.. The correct usage should be:
#BeforeGroups(groups = "regression")
Took me two days!!