TestNG, ITestContext - getIncludedGroups returns Null - java

There are several tests with different test groups. And I'm trying to run each of them with different set of data by using #DataProvider with ITestContext inside. I get NullPointerException. Here is my code:
String url = "http://google.com";
FirefoxDriver driver = new FirefoxDriver();
#BeforeTest(groups={"A","B"})
public void launchOfBrowser(){
driver.get(url);
}
#Test(dataProvider="Search", groups="A")
public void searchByUser(String author, String key) throws InterruptedException{
System.out.println("Welcome " + author + ", your search value is: " + key);
String enteredValue;
driver.findElement(By.name("q")).sendKeys(key);
Thread.sleep(3000);
enteredValue = driver.findElement(By.name("q")).getAttribute("value");
Assert.assertEquals(enteredValue, key);
driver.findElement(By.name("q")).clear();
}
#Test(dataProvider="Search", groups="B")
public void searchByIncognito(String key) throws InterruptedException{
System.out.println("Your search value is: " + key);
String enteredValue;
driver.findElement(By.name("q")).sendKeys(key);
Thread.sleep(3000);
enteredValue = driver.findElement(By.name("q")).getAttribute("value");
Assert.assertEquals(enteredValue, key);
driver.findElement(By.name("q")).clear();
}
#AfterTest(groups={"A","B"})
public void closeSessions(){
driver.quit();
}
#DataProvider(name="Search")
public static Object[][] getDataFromDataprovider(ITestContext c){
Object[][] groupArray = null;
for(String group : c.getIncludedGroups()){
if (group.equalsIgnoreCase("A")){
groupArray = new Object[][] {
{ "Guru99", "India" },
{ "Krishna", "UK" },
{ "Bhupesh", "USA" }
};
}
else{
groupArray = new Object[][] {
{ "India" },
{ "UK" },
{ "USA" }
};
}
}
return groupArray;
}

If you directly run your testng class, it will first call dataprovider which cant get groups information as groups are not available. But instead if you call this class via testng.xml, it will have groups info available with ITestContext.
You need to call this class(class name is say 'ParameterByITestContextInDataprovider') through TestNG xml.
Below is sample xml:-
<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >
<suite name="test-parameter">
<test name="example1">
<groups>
<run>
<include name="A" />
</run>
</groups>
<classes>
<class
name="com.package123.ParameterByITestContextInDataprovider" />
</classes>
</test>
<test name="example2">
<groups>
<run>
<include name="B" />
</run>
</groups>
<classes>
<class
name="com.package123.ParameterByITestContextInDataprovider" />
</classes>
</test>
</suite>

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));
}
}

Trying to run my automation project in parallel using java

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?

TestNG Dataprovider closing driver after each iteration

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!

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 #BeforeGroup is not executed before the group is run

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!!

Categories

Resources