Running parallel Testng tests in Selenium - selenium-webdriver

I have a BaseClass which has #BeforeSuite method that takes browser and other login parameters from xml. I want to run 2 parallel tests with different parameters. Since i am using parameters in #BeforeSuite so it takes values only once and not running any parallel execution. I cannot use parameters in #BeforeTest or #BeforeMethod or #BeforeClass as I need to use these parameters only once for each test and i have multiple test cases in each class.
My xml is as below;
<listeners>
<listener class-name="Utility.Listeners" />
</listeners>
<test name="Tests1" >
<parameter name="Browser" value="chrome" />
<parameter name="username" value="d1" />
<parameter name="password" value="P1" />
<parameter name="Brand" value="TC" />
<groups>
<run>
<include name="NatP" />
</run>
</groups>
<classes >
<class name="Maven.Dashboard"/>
<class name="Maven.TopBottomWidget"/>
<class name="Maven.Dashboard_BE"/>
</classes>
</test>
<parameter name="Browser" value="chrome" />
<parameter name="username" value="d1K" />
<parameter name="password" value="P1K" />
<parameter name="Brand" value="TCK" />
<groups>
<run>
<include name="NatP" />
</run>
</groups>
<classes >
<class name="Maven.Dashboard"/>
<class name="Maven.TopBottomWidget"/>
<class name="Maven.Dashboard_BE"/>
</classes>
</test>

You could try programmatic execution of testng by using the below code. You have to pass the parameters as maven run time arguments like below,
mvn clean install exec:java "-Dexec.mainClass=org.package.Test" "-DskipTests" "-Dexec.classpathScope=test" "-DBrowser=chrome,firefox"
The Test class is present inside src/test/java/, hence the classpathScope is mentioned as test in the above command. Also using the above maven command we are executing the main function of the Test class. This main method will in turn trigger the testng execution. The main method parse the existing testng XML file and add the arguments as parameters to each test. Each test will be run parallel with the thread size equal to the number of arguments you pass.
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.testng.TestNG;
import org.testng.xml.Parser;
import org.testng.xml.XmlSuite;
import org.testng.xml.XmlTest;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
public class Test {
public static void main(String[] args) throws Exception {
List<String> browserList = StringUtils.isEmpty(System.
getProperty("Browser")) ? new ArrayList<>() :
Arrays.asList(System.getProperty("Browser").split(","));
TestNG tng = new TestNG();
File initialFile = new File("testng.xml");
InputStream inputStream = FileUtils.openInputStream(initialFile);
Parser p = new Parser(inputStream);
List<XmlSuite> suites = p.parseToList();
List<XmlSuite> modifiedSuites = new ArrayList<>();
for (XmlSuite suite : suites) {
XmlSuite modifiedSuite = new XmlSuite();
modifiedSuite.setParallel(suite.getParallel());
modifiedSuite.setThreadCount(browserList.size());
modifiedSuite.setName(suite.getName());
modifiedSuite.setListeners(suite.getListeners());
List<XmlTest> tests = suite.getTests();
for (XmlTest test : tests) {
for (int i = 0; i < browserList.size(); i++) {
XmlTest modifedtest = new XmlTest(modifiedSuite);
HashMap<String, String> parametersMap = new HashMap<>();
parametersMap.put("browser", browserList.get(i));
modifedtest.setParameters(parametersMap);
modifedtest.setXmlClasses(test.getXmlClasses());
}
}
modifiedSuites.add(modifiedSuite);
}
inputStream.close();
tng.setXmlSuites(modifiedSuites);
tng.run();
}
}

Related

Login through multi browser parallely- Selenium

I am trying to login to facebook.com in parallel on 2 different browsers (Chrome and firefox).
Although both the browser opens the URL, in one browser no credentials are being entered, but in the second browser, the credentials are getting appended twice.
Due to this, my tests are failing.
I have used parallel as tests and methods as well. But it is not working.
MyWebDriver's driver instances are static, so there should not be any confusion when dealing with different browser types as both the browsers are opening this url.
Below is my testng.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
<suite name="Suite" verbose="1" thread-count="3" parallel="tests">
<listeners>
<listener class-name = "myTestingProject.Tests.TestListener"/>
<listener class-name = "myTestingProject.Tests.RetryListener"/>
<listener class-name = "myTestingProject.Tests.ReportListener"/>
</listeners>
<test name="TestCorrectCredChrome">
<parameter name= "correctUsername" value ="user123#gmail.com"/>
<parameter name= "CorrectPassword" value ="password"/>
<parameter name= "browser" value ="Chrome"/>
<parameter name= "url" value ="https://www.facebook.com/"/>
<parameter name= "waitTime" value ="50"/>
<classes>
<class name="myTestingProject.Tests.BaseWebDriverTest"/>
<class name="myTestingProject.Tests.LoginTest"/>
</classes>
</test>
<test name="TestCorrectCredFirefox">
<parameter name= "correctUsername" value ="user123#gmail.com"/>
<parameter name= "CorrectPassword" value ="password"/>
<parameter name= "browser" value ="Firefox"/>
<parameter name= "url" value ="https://www.facebook.com/"/>
<parameter name= "waitTime" value ="50"/>
<classes>
<class name="myTestingProject.Tests.BaseWebDriverTest"/>
<class name="myTestingProject.Tests.LoginTest"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
Below is the code for my custom MyWebDriver class which has methods of selenium webdriver
public class MyWebDriver {
public static WebDriver driver;
public static int waitTime = 60;
public static void openUrl(String url)
{
driver.get(url);
}
public static void closeDriver()
{
driver.close();
}
public static void quitDriver()
{
driver.quit();
}
//other methods like findElements etc
Below is the code for the testclass Basedriver which intializes the MyWebdriver
public class BaseWebDriverTest extends MyWebDriver{
#BeforeClass
#Parameters({"url","browser","waitTime"})
public void init(String url, String browser,String waitTime) {
System.out.println("Current Thread ID - "+Thread.currentThread().getId());
if(browser.equalsIgnoreCase("chrome")) {
System.setProperty("webdriver.chrome.driver","C:\\eclipse-workspace\\project\\resources\\chromedriver.exe");
MyWebDriver.driver = new ChromeDriver();
} else if (browser.equalsIgnoreCase("firefox")) {
System.setProperty("webdriver.gecko.driver","C:\\eclipse-workspace\\project\\resources\\geckodriver.exe");
MyWebDriver.driver = new FirefoxDriver();
}
MyWebDriver.waitTime = Integer.parseInt(waitTime);
MyWebDriver.openUrl(url);
}
}
Below is the Testclass for Login, which feeds credentials.
public class LoginTest extends BaseWebDriverTest{
#Test
#Parameters({"correctUsername","CorrectPassword"})
public void loginCorrectCredenential(String correctUname,
String correctPwd) throws InterruptedException {
MyWebDriverWait.waitUntilVisibilityOfElementLocatedBy("id", Login.getPasswordId());
MyWebDriverWait.waitUntilVisibilityOfElementLocatedBy("id", Login.getUserId());
MyWebDriver.driver.findElement(By.id("email")).sendKeys(correctUname);
MyWebDriver.driver.findElement(By.id("pass")).sendKeys(correctPwd);
}
Since my webdriver is static here, it is opening two browsers, 1st chrome and then firefox. But the credentials are written only on firefox and the credentials are repeated. Please see attached image. Left one is chrome and the right one is firefox.
Please suggest as to how this can be resolved. I have tried doing this using grid too but the problem still remains.
ChromeFirefox

How to I run extent report in parallel suit in selenium webdriver

I have created a Parallel suit and added parameters such as firefox, chrome etc. My issue is that when i run the suit, it logs results for the very first run. For example, if i am doing cross browser, so my test will run in firefox, and chrome so firefox triggers first. The issue is that the result logs are displayed only for fire fox driver. Below is my code. Please someone advice.
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Cross Browser Testing" parallel="tests" thread-count="2">
<test name="Firefox Test">
<parameter name="browser" value="firefox"></parameter>
<classes>
<class name="mwgToQuotients.ResponsiveHeaderFooter1"></class>
</classes>
</test>
<test name="Chrome Test">
<parameter name="browser" value="chrome"></parameter>
<classes>
<class name="mwgToQuotients.ResponsiveHeaderFooter1"></class>
</classes>
</test>
</suite>
#BeforeClass
#Parameters({ "browser" })
public void setUp(String browser) {
report = new ExtentReports("C:\\Users\\aaarb00\\Desktop\\Quotients\\MWG Reports\\QuotientCrossBrowser.html");
test = report.startTest("Functional Test");
baseURL = "http://ngcp-qi.safeway.com/";
if (browser.equalsIgnoreCase("firefox")) {
System.setProperty("webdriver.gecko.driver",
"C:\\Users\\aaarb00\\Desktop\\Quotients\\lib\\geckodriver.exe");
driver = new FirefoxDriver();
hp = new HomePage(driver, test);
lp = new SignInPage(driver, test);
sl = new StoreLocatorPage(driver);
wa = new WeeklyAdPage(driver, test);
} else if (browser.equalsIgnoreCase("chrome")) {
System.setProperty("webdriver.chrome.driver",
"C:\\Users\\aaarb00\\Desktop\\Quotients\\lib\\chromedriver.exe");
driver = new ChromeDriver();
hp = new HomePage(driver, test);
lp = new SignInPage(driver, test);
sl = new StoreLocatorPage(driver);
wa = new WeeklyAdPage(driver, test);
}
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get(baseURL);

How to show grouping of Test methods in Extent reports based on TEST groups

Please refer to the sample testng.xml file below.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Main Test Suite" verbose="2">
<test name="Sample registration tests">
<classes>
<class name="com.Practice.PracticeTest1" />
</classes>
</test>
<test name="Sample login tests">
<classes>
<class name="com.Practice.PracticeTest2" />
</classes>
</test>
</suite>
The file contains 2 Test Groups named Sample registration tests and Sample login tests and under that 1 test class in each group. Now I have configured Extent reports for my project and when running the reports are coming fine. But all the test methods in the 2 classes are coming sequentially.
Report screenshot
I want to show the test methods grouped under the Test groups. Like
all the methods of PracticeTest1 test class will come under Sample registration tests Test group and like that.
Actually You're not grouping tests by the meanings of TestNG in your .xml, You're just naming them. To group tests add argument 'groups' under #Test annotation, like this:
public class Test1 {
#Test(groups = { "functest", "checkintest" })
public void testMethod1() {
}
#Test(groups = {"functest", "checkintest"} )
public void testMethod2() {
}
#Test(groups = { "functest" })
public void testMethod3() {
}
}
And then in .xml configure your test run:
<test name="Test1">
<groups>
<run>
<include name="functest"/>
</run>
</groups>
<classes>
<class name="example1.Test1"/>
</classes>
</test>
For more info about grouping Your tests visit
http://testng.org/doc/documentation-main.html

Parameter 'browserType' is required by #Configuration on method before but has not been defined in src\test\resources\testng.xml

When running Selenium case, I want firefox and chrome at the same build. My testng.xml :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
<test name="Browser Compatibility Test Cases--firefox" thread-count="1" preserve-order="false">
<parameter name="browserType" value="firefox" />
<classes>
<class name="com.yeetrack.selenium.test.ParameterTest" />
</classes>
</test>
<test name="Browser Compatibility Test Cases--chrome" thread-count="1" preserve-order="false">
<parameter name="browserType" value="chrome" />
<classes>
<class name="com.yeetrack.selenium.test.ParameterTest" />
</classes>
</test>
</suite>
And my test case:
public class ParameterTest {
#Parameters("browserType")
#BeforeMethod
public void before(String browser)
{
System.out.println(browser);
}
#Test(dataProvider = "KeywordDataProvider", dataProviderClass = KeywordData.class)
public void test(String keyword)
{
System.out.println(keyword);
}
}
But I got an error:
before(com.yeetrack.selenium.test.ParameterTest) Time elapsed: 0.222 sec <<< FAILURE!
org.testng.TestNGException:
Parameter 'browserType' is required by #Configuration on method before
but has not been defined in src\test\resources\testng.xml
at org.testng.internal.Parameters.createParameters(Parameters.java:109)
at org.testng.internal.Parameters.createParameters(Parameters.java:264)
at org.testng.internal.Parameters.createConfigurationParameters(Parameters.java:69)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:135)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:427)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:607)
When running, browserType=firefox, it passed. But when browserType=chrome, it failed. I can't use #Parameters and DataProvider at the same time? When I change my case to :
#Test //no DataProvider
public void test()
{
System.out.println("Hello world"));
}
It passed! Why? thx.
Here is the OP's comment solution as an answer, to make it clearer for future visitors.
In the pom.xml, the original poster added testng instead of surefire:
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.8</version>
</dependency>
This is instead of surefire-testng:
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-testng</artifactId>
<version>2.14.1</version>
</dependency>

No Activity to handle Intent for Illumination API

Today the illumination API was released and I tried to make a simple app of showing of a blink of the illumination bar upon click of a button. I just copy-pasted the code in the sony developers website, but it gives error that, there is no acitivity to handle this intent START_LED.
Here's the main_activity:
package com.example.myillumin;
import com.sonyericsson.illumination.IlluminationIntent;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
private Button b1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b1= (Button) findViewById(R.id.button1);
b1.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0){
Intent intent=new Intent(IlluminationIntent.ACTION_START_LED);
intent.putExtra(IlluminationIntent.EXTRA_LED_COLOR,0xFFFF0000);
intent.putExtra(IlluminationIntent.EXTRA_PACKAGE_NAME, "com.example.myillumin");
startActivity(intent);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
And here's the manifest file I tried to modify seeing other posts of stackoverflow.
<uses-permission android:name="com.sonyericsson.illumination.permission.ILLUMINATION"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.myillumin.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.sonyericsson.illumination.IlluminationIntent"
android:label="#string/activity_name"
android:exported="false">
<intent-filter>
<action android:name="com.sonyericsson.illumination.intent.action.START_LED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
Please help me out :(
The illumination bar API uses a 'service' to change the colors of the bar, so you have to start a Service not an Activity.
So, in your code,
Intent intent=new Intent(IlluminationIntent.ACTION_START_LED);
intent.putExtra(IlluminationIntent.EXTRA_LED_COLOR,0xFFFF0000);
intent.putExtra(IlluminationIntent.EXTRA_PACKAGE_NAME, "com.example.myillumin");
startActivity(intent);
instead of starting an activity with the intent, try starting a service with the created Intent. From:
startActivity(intent);
change to
startService(intent);
You can also check whether the device supports the API by calling:
Intent checkIntent = new Intent(IlluminationIntent.ACTION_STOP_LED);
if (null == getPackageManager().resolveService(checkIntent,
PackageManager.GET_RESOLVED_FILTER)) {
// Not supported
}
In order to start the illumination service you must provide the intent with certain mandatory fields, you already have IlluminationIntent.EXTRA_PACKAGE_NAME and IlluminationIntent.ACTION_START_LED so now u need to add IlluminationIntent.EXTRA_LED_ID, therefore, inside the onClick method Add the line:
intent.putExtra(IlluminationIntent.EXTRA_LED_ID, IlluminationIntent.VALUE_BUTTON_2);
Since it is a service, you need to change:
startActivity(intent);
And replace it with:
startService(intent);

Resources