Can we follow the below method to initialise the test data? There are 2 points I want to implement.
Need to initialise/load the test data once from the file and use the same test data in all dataproviders.Thought to implement test data loader in #beforesuite class.
Need data from dataprovider and a parameter from testNG file at the same time in #test method.
#BeforeSuite
#Parameters(value = { "test_data_file" })
public static synchronized void init(String test_data_file) {
TestDataFactory.load(test_data_file);
}
#Test(dataProvider="dp_dummy",dataProviderClass = DP_1.class)
public void testDummyAPI(TestData test_data,ITestContext context){
String param = context.getCurrentXmlTest().getParameter("param");
}
#DataProvider(name = "dp_dummy")
public Object[][] getDataFromDataprovider(ITestContext context) {
List<TestData> test_data_collection = TestDataFactory.getTestData(targated_test_data);
Object[][] test_data_set = new Object[test_data_collection.size()][1];
for(TestData test_data : test_data_collection)
test_data_set[i++][0] = test_data;
return test_data_set;}
Assuming you are creating your test_data_set correctly you can achieve your second point like this
#Test(dataProvider="dp_dummy",dataProviderClass = DP_1.class)
public void testDummyAPI( String p, Object[][] ob){
System.out.println(p);
System.out.println(ob[0][0]);
}
#DataProvider(name = "dp_dummy")
public Object[][] getDataFromDataprovider(ITestContext context) {
List<TestData> test_data_collection = TestDataFactory.getTestData(targated_test_data);
Object[][] test_data_set = new Object[test_data_collection.size()][1];
for(TestData test_data : test_data_collection)
test_data_set[i++][0] = test_data;
String param = context.getCurrentXmlTest().getParameter("param");
return new Object[][] {
{ param, test_data_set}
};
}
Related
Is there a way to use Data Providers for BeforeMethod function?
I would like to run parallel tests for number of different devices, so I would like to use parameters to setup capabilities. But I want to have a different way than using testng.xml.
You can get the data passed to the test by the data provider in your BeforeMethod by having Object[] parameter.
#BeforeMethod
public void beforeMethod(Object[] data) {
//.......
}
Assume the following code:
#Test(dataProvider = "dataOne")
public void testMethodOne(String one, int two) {
}
#Test(dataProvider = "dataTwo")
public void testMethodTwo(int one) {
}
#DataProvider
public Object[][] dataOne() {
return new Object[][]{ {"a", 1} };
}
#DataProvider
public Object[][] dataTwo() {
return new Object[][]{ {1} };
}
In order to get the data passed by the data provider before it reaches the test methods, you define a before method as below. I have added Method m parameter as well. This would help to identify the running test case. Object[] data contains the data passed by the data provider. If you have added this argument, then testNG would automatically pass the data to the before method.
#BeforeMethod
public void beforeMethod(Method m, Object[] data) {
if(m.getName().equals("testMethodOne")) {
String x = (String) data[0];
int y = (int) data[1];
} else if(m.getName().equals("testMethodTwo")) {
int x = (int) data[0];
}
}
I have a FileRepository class to fill MutableLiveData. I have two functions in there. One is calling web service and setting list (getAllFilms). Other one is assigning MutableLiveData with first function List (getFilmData). I try to write unit test for MutableLiveData. Can you help me? This function data always comes null.
public class FilmRepositoryTest
#Mock
FilmRepository frepo;
#Rule
public InstantTaskExecutorRule instantTaskExecutorRule = new InstantTaskExecutorRule();
#Before
public void setUp() throws Exception {
}
#Test
public void getFilmData_forData() throws IOException {
ArrayList<film> filmlistesi = new ArrayList<>();
MutableLiveData<List<film>> bilgi = new MutableLiveData<>();
String arama = "ankara";
filmlistesi.add(new film("Behzat Ç.: Bir Ankara Polisiyesi","2010–2019","tt1795096","series","https://m.media-amazon.com/images/M/MV5BZDZjY2I5ZjEtZGE2MS00ZjRmLTlmMGEtMDQ5ZmZhZWJjYzk3XkEyXkFqcGdeQXVyNDg4MjkzNDk#._V1_SX300.jpg"));
when(frepo.getAllFilms(arama)).thenReturn(filmlistesi);
bilgi.setValue(filmlistesi);
System.out.println(frepo.getFilmData(arama)); // print(NULL)
System.out.println(bilgi.getValue()); // print(filmlistesi)
assertEquals(frepo.getFilmData(arama),bilgi.getValue());
}
public class FilmRepository
public MutableLiveData<List<film>> getFilmData(String a) throws IOException {
MutableLiveData<List<film>> data = new MutableLiveData<>();
data.setValue(getAllFilms(a));
return data;
}
public ArrayList getAllFilms(String filmName) throws IOException {
ArrayList<film> dataset = new ArrayList<>();
return dataset;
}
LiveData or MutableLiveData must have an Observer set of it or else it returns null
Observer<List<film>> observer = new Observer<List<film>>() {
#Override
public void onChanged(#Nullable List<film> films) {
assertEquals(frepo.getFilmData(arama), films.getValue());
biligi.removeObserver(this)
}
};
bilgi.observeForever(observer);
bilgi.setValue(filmlistesi);
I am facing an issue wherein I have created a parameterized method that uses dataprovider. Both DataProvider and method and created in same class. Now, I want to call this method from another class but it requires parameters to be passed which I cannot since they are being read from dataProvider.
I have tried declaring the dataProvider in different class too but that doesn't work. Please suggest some workaround for it.
NOTE: I have a restriction that I cannot use TestNG.xml to implement this scenario.
Please find the code below:
DataProvider:
#DataProvider(name = "TestSuite")
public Object[][] dataSheetTraverser() {
String SheetName = "ProgLang";
datatable = new Xls_Reader(TestDataSheetPath_ProgLang);
int rowcount = datatable.getRowCount(SheetName);
Object result[][] = new Object[rowcount - 1][3];
for (int i = 2; i < rowcount + 1; i++) {
result[i - 2][0] = SheetName;
result[i - 2][1] = i;
result[i - 2][2] = datatable.getCellData(SheetName, "caseType", i);
}
return result;
}
Test Method:
#Test(dataProvider="TestSuite_ProgLang",priority =2)
public void TC_Verify_EditProgLang(String SheetName,int i, String caseType)
{
String test1= datatable.getCellData(SheetName, "Skills", i);
String test2= datatable.getCellData(SheetName, "Version", i);
String test3= datatable.getCellData(SheetName, "LastUsed", i);
String test4= datatable.getCellData(SheetName, "ExperienceYr", i);
String ExperienceMn = datatable.getCellData(SheetName, "ExperienceMn", i);
proglang.FillForm_ProgLang(Skills, Version, LastUsed, ExperienceYr, ExperienceMn);
}
I want to call the above function TC_Verify_EditProgLang from another class. Please suggest.
You can use the dataProviderClass attribute for calling from other class
in #Test and The Provider method Must be static :
public class StaticProvider {
#DataProvider(name = "create")
public static Object[][] createData() {
return new Object[][] {
new Object[] { new Integer(42) }
};
}
}
//different Class
public class MyTest {
#Test(dataProvider = "create", dataProviderClass = StaticProvider.class)
public void test(Integer n) {
// ...
}
}
please check the Documentation :dataProviders
I'm using POM framework and managed the code in following way :
This is My InviteFriendPage
public class InviteFriends
{
#FindBy(xpath ="//li/a[normalize-space()='Invite Friends']")
public WebElement inviteFriendsLink;
#FindBy(id = "divLoader")
public WebElement loader;
#FindBy(xpath = "//input[#name='lstInviteFriendsModel[1].FriendName']")
public List<WebElement> friendName;
#FindBy(xpath = "//input[#name='lstInviteFriendsModel[1].FriendMobile']")
public WebElement friendNumber;
WebDriver driver;
public InviteFriends(WebDriver driver)
{
PageFactory.initElements(driver, this);
this.driver=driver;
}
public void inviteFriend(String friendName, String friendMobile)
{
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("arguments[0].click();", inviteFriendsLink);
for(int i=1;i<=3;i++)
{
driver.findElement(By.xpath("//input[#name='lstInviteFriendsModel["+i+"].FriendName']")).sendKeys(friendName);
driver.findElement(By.xpath("//input[#name='lstInviteFriendsModel["+i+"].FriendMobile']")).sendKeys(friendMobile);
}
}
}
This is my Executor Class from where I'm calling all the pages by creating object
public class MainSuitExecuter extends DriverSetup
{
#Test()
public void submitFeedback() throws InterruptedException
{
ContactUsPage conpage = new ContactUsPage(driver);
conpage.submitContactUsForm(TestDataComman.fName, TestDataComman.fEmail, TestDataComman.fMobile, TestDataComman.fType, TestDataComman.fMessage);
}
#Test()
public void login() throws IOException, InterruptedException
{
UserLogin login = new UserLogin(driver);
ReadExcel read = new ReadExcel();
String uname = read.getCellData(1, 0);
String passwd = read.getCellData(1, 1);
login.doLogin(uname, passwd);
}
#Test()
public void inviteFriend()
{
InviteFriends invitefriend = new InviteFriends(driver);
invitefriend.inviteFriend();
}
}
and Executing the MainSuitExecuter class from testing.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="MyKart">
<test name="Functional_Test">
<parameter name="browser" value="chrome" />
<classes>
<class name="com.commonutils.DriverSetup"/>
<class name="com.testexecuter.MainSuitExecuter"/>
</classes>
</test>
</suite>
The Problem is, For friend Invitation minimum 3 friends details(friendname and number) mandatory. So i'm using DataProvider of TestNG for that. But not getting the clear idea where i need to use in My code as i have structure as mentioned above.
I have tried it in InviteFriend.java class Like :
#Test(getData)
public void inviteFriend(String friendName, String friendMobile)
{
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("arguments[0].click();", inviteFriendsLink);
for(int i=1;i<=3;i++)
{
driver.findElement(By.xpath("//input[#name='lstInviteFriendsModel["+i+"].FriendName']")).sendKeys(friendName);
driver.findElement(By.xpath("//input[#name='lstInviteFriendsModel["+i+"].FriendMobile']")).sendKeys(friendMobile);
}
}
#DataProvider
public Object[][] getData()
{
Object[][] data = new Object[3][2];
// 1st row
data[0][0] ="A";
data[0][1] = "9442307801";
// 2nd row
data[1][0] ="B";
data[1][1] = "9887252210";
// 3rd row
data[2][0] ="C";
data[2][1] = "9925497562";
return data;
}
but no success as i have to call inviteFriend() method from MainSuitExecuter class so there i need to pass parameter.
Can anybody help me to get out from this glitch and suggest me better idea to accomplish my motive
This how you can probably do.
Create a separate Friend Class. with attribute you required, i.e. Name and mobile number
Create the object or list of object of this friends. I think list of object would be better.
Rather than using data provider, in your test create this friend object and pass it some of the method in inviteFriend class.
I think this would be cleaner approach and better to understand.
Sample code
Friend.java
public class Friend {
String name;
String mobile;
public Friend(String name, String mobile){
this.name = name;
this.mobile = mobile;
}
}
InviteFriends.java
public class InviteFriends {
public InviteFriends(WebDriver driver){
PageFactory.initElements(driver, this);
}
public void createFriendInvitation(List<Friend> friendList){
for (Friend friend: friendList) {
System.out.println(friend.mobile);
System.out.println(friend.name);
}
}
}
Your Test Class
public class TestClass {
#Test
public void testFriendInvitation(){
WebDriver driver = new FirefoxDriver();
List<Friend> friends = new ArrayList<Friend>();
friends.add(new Friend("bestfriend", "11111"));
friends.add(new Friend("newfriend", "222"));
friends.add(new Friend("oldfriend", "33333"));
InviteFriends inviteFriends = PageFactory.initElements(driver, InviteFriends.class);
inviteFriends.createFriendInvitation(friends);
driver.quit();
}
}
The code is pretty much good except one. We need a give a name to the data provider annotation and refer it as a source of input for the respectective #test method. The code below will ideally work for you,
public class MainSuitExecuter extends DriverSetup
{
#Test()
public void submitFeedback() throws InterruptedException
{
ContactUsPage conpage = new ContactUsPage(driver);
conpage.submitContactUsForm(TestDataComman.fName, TestDataComman.fEmail, TestDataComman.fMobile, TestDataComman.fType, TestDataComman.fMessage);
}
#Test()
public void login() throws IOException, InterruptedException
{
UserLogin login = new UserLogin(driver);
ReadExcel read = new ReadExcel();
String uname = read.getCellData(1, 0);
String passwd = read.getCellData(1, 1);
login.doLogin(uname, passwd);
}
#Test(dataProvider="users") //use dataprovider with name "users" as input source
public void inviteFriend(String name, String number)
{
InviteFriends invitefriend = new InviteFriends(driver);
invitefriend.inviteFriend(name, number);
}
#DataProvider(name = "users") //naming as users
public Object[][] getData()
{
Object[][] data = new Object[3][2];
// 1st row
data[0][0] ="A";
data[0][1] = "9442307801";
// 2nd row
data[1][0] ="B";
data[1][1] = "9887252210";
// 3rd row
data[2][0] ="C";
data[2][1] = "9925497562";
return data;
}
}
DataProvider becomes handy when we need to pass the data from excel sheet becomes handy. More details are available in the testng documentation.
http://testng.org/doc/documentation-main.html#parameters-dataproviders
Some tutorials for data provider implementation
http://learn-automation.com/data-driven-framework-in-selenium-webdriver/
I hope this helps you.
Thanks.
So the problem I am trying to solve is :
I have test class and a #test method runtest which receives data from a data provider. I want to perform some action based on the test data run test is going to receive from the data provider, before starting the runtest method.
For this I was looking at iTestListener, it has a method onTestStart but I am not able to figure out how to get the test data for that instance of run in the method.
Any other good approach is welcome.
Create a class extending TestListenerAdapter
public class TestListener extends TestListenerAdapter {
#Override
public void onTestStart(ITestResult tr) {
super.onTestStart(tr);
Object[] params = tr.getParameters();
String a = (String)params[0];
int b = (int)params[1];
//Add whatever you want to do before the test case starts
}
}
Add annotation to your test class
#Listeners(ResultReporter.class)
public class CoreSingleApplicant1TestCase {
#Test(dataprovider = "dataprovider",dataProviderClass = StaticProvider.class))
public void runtest(String a, int b){
}
}
Dataprovider class
public class StaticProvider {
#DataProvider(name = "create")
public static Object[][] createData() {
return new Object[][] {
new Object[] {
{"String", 1},
{"Integer",2} }
}
}
}