Using only one dataprovider , how to pass data to many test methods - selenium-webdriver

Im using DataProvider in TestNG for my Selenium Scripts . My requirement is to just use a single DataProvider and pass the data to many test methods .
For example : Say i have 10 test methods , So i need to create a Single DataProvider , so that it can pass data to all those 10 Test methods.
Is it possible to do it ? If yes , how to implement it .
Or is there any alternative for this ??
Pl Help !!!

If each of your test method has #Test annotation, then you can simply add parameter to this as -
#Test(dataProvider="Name of your DataProvider")
You can do this with all of the 10 test methods & this will make them get data from your single DataProvider.
I hope it helps. . .cheers!!

Yes it is possible.
So your data provider needs to know for which method or class it is providing the data. I made the following implementation. So you can get the context of the calling method in a data provider and you can ask it what is the parent class name for which the data has to be provided, and then depending on that you can have multiple files which you can read and supply the data or have different rows in the same csv differentiated by class name from where you can read the required row
#DataProvider(name="getDataFromFile")
public static Iterator<Object[]> getDataFromFile(Method testMethod) throws Exception
{
String expected=null;
String className=testMethod.getDeclaringClass().getSimpleName();
Reporter.log("Providing data for class " + className,true);
List<Map<String, String>> setupData = getTestDataFromCsv(classname);
//provide data here
}

Update on this:
I was looking for a solution for the same. But it is not possible to split the data provider. But no harm in reusing the data provider for all methods, the disadvantage is each method must use the complete list of arguments. All other options are more complex to implement and maintain. For my scenario, it is better than creating and maintaining separate data providers for each test methods.
#BeforeMethod
public void setUp() {
init();
login= new LoginPage(myD);
clientsearch = new ClientSearchPage(myD);
toppanel= new TopPanelPage(myD);
}
#Test(dataProvider="search_data")
public void verifySearchByClientNumber(String clientnumber, String policynumber, String policynumberClient, String webreference,
String webreferenceClient, String surname, String surnameClient, String forename, String forenameClient, String dob, String dobClient){
login.Login();
log.info("Logged in successfully, now in ClientSearch Page..");
log.info("Entering client number.." );
clientsearch.enterClientNumber(clientnumber);
log.info("Clicking on the Search button ..." );
clientsearch.clickSearchButton();
log.info("Verifying Client present in results.." );
boolean res=clientsearch.isClientPresent(clientnumber);
Assert.assertEquals(res, true,"Assertion failed !!");
toppanel.clickLogoutButton();
}
#Test(dataProvider="search_data")
public void verifySearchByPolicyNumber(String clientnumber, String policynumber, String policynumberClient, String webreference,
String webreferenceClient, String surname, String surnameClient, String forename, String forenameClient, String dob, String dobClient){
login.Login();
log.info("Logged in successfully, now in ClientSearch Page..");
log.info("Entering Policy number.." );
clientsearch.enterPolicyNumber(policynumber);
log.info("Clicking on the Search button ..." );
clientsearch.clickSearchButton();
log.info("Verifying Client present in results.." );
boolean res=clientsearch.isClientPresent(policynumberClient);
Assert.assertEquals(res, true,"Assertion failed !!");
toppanel.clickLogoutButton();
}
//More methods here with same data provider....
#AfterMethod
public void endTest() {
myD.quit();
}

Related

Retrieve executionId inside CommandInterceptor

I am implementing my own Activiti command intereceptor like this :
public class ActivitiCommandInterceptor extends AbstractCommandInterceptor {
private RuntimeService runtimeService;
private CommandInterceptor delegate;
public ActivitiSpringTxCommandInterceptor(RuntimeService runtimeService, CommandInterceptor delegate) {
this.runtimeService = runtimeService;
this.delegate=delegate;
}
#Override
public <T> T execute(CommandConfig config, Command<T> command) {
String myVariable = runtimeService.getVariable(<missingExecutionId>, "myVariableName");
...
}
}
Inside the execute() method I need to retrieve a variable from the execution context related to this command.
To do that, I need to have the executionId, but I can't find a way to retrieve it.
How can I get my variable from this interceptor?
Thanks
You can create a nativeExecutionQuery
This allows us to use SQL to perform operations directly on DB.
For your case, just find all the execution IDs that contains your variables, and filter them according to your need.

how to pass dataprovider to any test in testNG when dataset has data not specific to this testcase

I am trying to build a Selenium hybrid framework using TestNG wherein i am getting data from my excel datasheet. I am trying to use DataProvider of testNG, But problem is since my datasheet contains data which belongs to different test case (for eg. 2 rows for add user, 1 rows for modify user, some rows for searching user etc)
since my dataprovider will return all the data from datasheet and passing it to any particular testCase that will run for all row of dataprovider will cause problem (eg. create user will need 5 parameter but the data of edit user will not be sufficient to it).
how can we handle this problem?
Here's how you do this:
Within your .xls file, create a sheet which represents a particular functionality. (For e.g, login, compose, address-book etc., if I were to be taking the example of an emailing application)
Now each sheet would have test data for various test cases, that test out that particular functionality.
In your #Test method, you can create a new custom annotation (this would be a marker annotation), which would indicate the "sheet" name from which the data provider should be retrieving data from. If you are not keen on creating a new custom annotation, then you can make use of the "description" attribute of the #Test annotation to capture this information.
TestNG can natively inject a Method object to your #DataProvider annotated method. Here the Method object that was injected would represent the #Test method for which the data provider is about to be invoked. So now you can retrieve the sheet name, either from the new custom annotation (or) from the description attribute of the #Test annotation to figure out which sheet name to query for data.
That should solve your issue.
Here's a sample that demonstrates the overall idea. You would need to enrich the data provider, such that it uses the sheet name to query data from the excel spreadsheet. My sample just excludes all of that, for the sake of demonstration.
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
#Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
#Target({METHOD})
public #interface SheetName {
String value() default "";
}
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.lang.reflect.Method;
public class TestClass {
#Test(dataProvider = "dp")
#SheetName("one")
public void test1(String name) {
System.err.println("Name is " + name);
}
#Test(dataProvider = "dp")
#SheetName("two")
public void test2(int age) {
System.err.println("Age is " + age);
}
#DataProvider(name = "dp")
public Object[][] getData(Method method) {
String sheetName = getSheetName(method);
if (sheetName == null) {
// Handle the case, wherein our custom annotation is missing. That means the test perhaps
// expects
// either all of the data, or it could be a error case.
return new Object[][] {{}};
}
if ("one".equalsIgnoreCase(sheetName)) {
return new Object[][] {{"Cedric"}, {"Beust"}};
}
if ("two".equalsIgnoreCase(sheetName)) {
return new Object[][] {{1}, {2}};
}
// Handle the case, wherein we had a valid sheet name, but it represents a sheet that cant be
// found in our
// excel spreadsheet.
return new Object[][] {{}};
}
private String getSheetName(Method method) {
SheetName sheetName = method.getAnnotation(SheetName.class);
if (sheetName == null || sheetName.value().trim().isEmpty()) {
return null;
}
return sheetName.value();
}
}

iBatis unable to read property from Map when using isEqual

I'm seeing a very bizarre issue with iBatis when trying to read a property from a Java map using isEqual, but not with other iBatis operators. For example it is able to read the map properties fine when using isNotNull and iterate. The xml:
<isNotNull property="filterCriteria.account">
AND
id
<isEqual property="filterCriteria.account.meetsCriteria" compareValue="false">
NOT
</isEqual>
IN
(SELECT DISTINCT id
FROM account
WHERE some other criteria....
)
</isNotNull>
The 2 java classes we're using here:
public class SearchProfile {
private Map<String, SearchProfileCriteria> filterCriteria;
public SAOSearchProfile() {
filterCriteria = new HashMap<>();
}
public Map<String, SAOSearchProfileCriteria> getFilterCriteria() {
return filterCriteria;
}
public void setFilterCriteria(Map<String, SAOSearchProfileCriteriaBase> filterCriteria) {
this.filterCriteria = filterCriteria;
}
}
Above is the container object that is passed to iBatis for the querying, and below is the criteria object that will be the value of the map. In this example it is keyed with the String "account"
public class SearchProfileCriteria {
boolean meetsCriteria;
public String getCriteriaAsString() {
return StringUtils.getStringValueFromBoolean(meetsCriteria);
}
public boolean isMeetsCriteria() {
return meetsCriteria;
}
public void setMeetsCriteria(boolean meetsCriteria) {
this.meetsCriteria = meetsCriteria;
}
public String getSQLString(){
return meetsCriteria ? "" : "NOT";
}
}
And the exception:
Cause: com.ibatis.common.beans.ProbeException: There is no READABLE property named 'account' in class 'java.util.Map'; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:
The getSQLString() method was my half baked attempt at a work around, the String gets escaped in the query and throws a syntax error.
When I remove the <isEqual> block the query executes find, which indicates it is able to read the "account" key when checking the to see if it is null. As I mentioned above, we're also able to use the map keys in <iterate> tags without issue. It seems <isEqual> and <isNotEqual> are the only tags causing issues. Does anyone have experience with this or know what may be going on?
Beware: Using isNotNull, isEqual, iterate is iBatis, they don't exist anymore in Mybatis, so referencing to Mybatis indifferently is confusing.
Reference documentation.
For your issue, how does it behave if replacing Map with a class (property will be known at compile time)?
Or try using <isPropertyAvailable>.
The work around could work with right syntax: $ instead of #: $filterCriteria.account.SQLString$ instead of #filterCriteria.account.SQLString#, then the value is just concatenated instead of bound as parameter.

Save result from Objectify in human readable form in datastore

I am trying to create an Eventlog (ORMSLOG in example), that saves events in human readable form in Datastore.
Doing this should write readable event:
List<Device> devices = ofy().transactionless().load().type(Device.class).list();
ORMSLOG.log(ORMSLOG.GET_ALL_DEVICES, "Devices found: " + String.valueOf(devices));
The ORMSLOG is a simple class.
public class ORMSLOG {
public final static String CREATE_DEVICE = "Create Device";
public final static String GET_ALL_DEVICES = "Get all Devices";
public static void log(final String event, final String data) {
ofy().save().entity(new Event(event, data)).now();
}
}
But the data saved in Datastore is not readable and looks like this:
ORMSLOG data
I need to transform the reference to the object into human readable text.
You are just logging the String representation of the objects, which is done by calling the toString method. Since you did not override the toString method in the Device class, you are getting the pointer to the objects. If you override the toString method in your Device class to return whatever state you want to return, you would see a much better result. Most IDEs (e.g. Eclipse) have an option to generate toString method for you.

Getting Dapper to return an empty string instead of a null string

I know it's kind of the wrong thing to do, but I'm dealing with a legacy codebase that has NULLS when it means empty strings and vice versa.
I can't immediately see how it is possible, but is it possible to get (or modifiy dapper so it will) return an empty string instead of a null string when mapping back from the database.
Dapper doesn't call any setter when it sees a null, so options might include:
set the default value to "" in the constructor
check for null in the accessor
So:
public class SomeDto
{
public SomeDto()
{
Name = "";
}
public string Name {get;set;}
}
or:
public class SomeDto
{
private string name;
public string Name { get {return name ?? "";} set {name = value;} }
}
However, this only applies to reading values; I can't think of a nice way to get dapper to turn "" into null when passing the dto in as the parameter object; options include:
creating an anon-type, substituting "" to null (perhaps write a string NullIfBlank(this string s) extension method)
having a shim property on the type that returns null in place of "", and have your database query bind to #NameOrNull rather than #Name
You can control this with your queries, for example:
public class Data
{
public string Foo { get; set; }
}
var result = conn.Query<Data>("select Foo = coalesce(Foo, '') from MyTable");
So in the above example, coalesce will return an empty string when Foo is null.
In short: depending how you load the data to the dapper you may get two different scenarios.
First: Turn up your data provider layer, for example like in this post - How to return null from a Dapper query rather than default(T)?.
Second way to try: you may modify your GetTypeDeserializer like in the following post - Change Dapper so that it maps a database null value to double.NaN
Third and the last: it is my friendly advice to work on your previous questions acceptance rate. In this way you may increase chances of replies for your questions.
Hope all this will help.
I tend to use a global extension method on string called ConvertNull() which converts any null values to an empty string. You can then call this anywhere without your code looking cluttered. If you're using this directly on an aspx page, just make sure you've imported the namespace of the extension methods and then the method will be available to you:
namespace ExtensionMethods
{
using System;
public static class StringExtensionsClass
{
/// <summary>Converts null strings to empty strings</summary>
/// <param name="s">Input string</param>
/// <returns>Original string, or empty string if original string was null</returns>
public static string ConvertNull(this string s)
{
return s ?? "";
}
}
}
Then call this on an instance of a string.
Usage:
myStringInstance.ConvertNull().Replace("\r\n", "<br />");

Resources