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

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

Related

Solr-CustomTransformer For Converting Data from Database to table data

I am quite new to the solr custom transformer. I am trying to use solr custom customtransformer for preprocessing of the data fetched from Database.
The basic problem that, I am getting in using custom transformer, There is no change in the resultant row of solr after importing the data. I have checked that, Class is loaded and there is no error of
Error loading class of cust.test.pretransform
And In the transformer code, I just want the code to be reacted to the code.
public Object transformRow(Map<String, Object> row, Context context) {
// TODO Auto-generated method stub
List<Map<String, String>> fields = context.getAllEntityFields();
for (Map<String, String> field : fields) {
String textstruk_tec = field.get("field_tec");
if("name".equals(textstruk_tec))
{
String columnName = field.get(DataImporter.COLUMN);
Object values = row.get(columnName);
if(values != null)
{
row.put(textstruk_tec, "Textteil");
}
}
}
return row;
}
Thanks in advance !
Best Regards !

ClassCastException - java.lang.String cannot be cast to com.codename1.ui.Image

I am consuming a JSON string that contains an image object among other objects. From this I create a PropertyBusinessObject which has a the following
public final Property<EncodedImage, Profile> profilePic = new Property<>("profilePic", EncodedImage.class);
I have created a method in the PropertyBusinessObject
public EncodedImage getProfilePic() {
return profilePic.get();
}
I populate my data into the Property business object as follows:
profile.getPropertyIndex().populateFromMap((Map) profileObject);
When I try to display the image on the form using the following code,
ScaleImageLabel profilePic = new ScaleImageLabel(profile.getProfilePic()) {
#Override
protected Dimension calcPreferredSize() {
Dimension dimension = super.calcPreferredSize();
dimension.setHeight(Math.min(dimension.getHeight(), Display.getInstance().convertToPixels(40)));
return dimension;
}
};
profilePic.setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FILL);
container.add(BorderLayout.NORTH, profilePic);
I get a ClassCastException
Exception: java.lang.ClassCastException - java.lang.String cannot be cast to com.codename1.ui.Image
Can anyone help me resolve, or suggest another way of consuming the JSON string?
populateFromMap doesn't currently support Base64 images, I'll add that as an option as that use case makes sense. Should be there with the Friday update.

Limit c# model class parameter call to MS SQL server for non-existing table field

Working with database-first approach creating ASPNETCORE MVC web app with user authentication, I would like to override the way the parameters from IdentityUser class are queried to the database. The reason is the current implementation of IdentityUser has two new parameters NormalizedEmail and NormalizedUserName (which in my opinion retracts from Normalization).
Is there a way I can write the code below in the Model class so that those two parameters are not included in the query to the database or is that something that needs to be done in the controller class?
public class IdentityUser : Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUser
{
public override string NormalizedUserName
{ get { return null; } set { value = null; } }
public override string NormalizedEmail
{ get { return null; } set { value = null; } }
}
Not far as I can tell, both parameters are part of the data model and as explained in this Issue #351
About Identity 3.0:
...Instead we compute a normalized representation of the user name and we
store it in a separate column so that lookups by normalized user name
should now be sargable.
So in other words, if you "override the way the parameters from IdentityUser class are queried to the database" in essence you'll be doing exactly the opposite the class intends to do.

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

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

Sorting a CellTable server-side

I'm currently using a Gwt CellTable, bound to my GAE/Objectify backend via RPC calls.
All right now! :-)
Then I want to sort columns, so I read http://code.google.com/intl/it-IT/webtoolkit/doc/latest/DevGuideUiCellTable.html#columnSorting
The Async Remote sorting sections shows very well how to get sorting into my AsyncDataProvider but... how can I retrieve the name of the column the user wants to sort?
It shows this code: ColumnSortList sortList = table.getColumnSortList();
But how can I get String names from that? I simply want to know "surname" or "soldDate", the name of the field the column is bound to! Then I will pass it to my rpc service, and use it to sort data server-side query(...).order(<field_name>)
Am I missing something?
UPD: interesting stuff here: http://groups.google.com/group/google-web-toolkit/browse_thread/thread/77a0eaf8086218a6/effb8d3abe69270b#effb8d3abe69270b
You can keep a list of column names ordered as they are in the table:
List<String> columnNames = new ArrayList<String>();
table.addColumn(surnameColumn, "surname");
columnNames.add("surname");
// add the other columns
Then when you need to get the sort column name:
String sortColumnName;
ColumnSortList sortList = table.getColumnSortList();
if (sortList != null && sortList.size() != 0){
Column <MyEntity, ?> sortColumn = (Column <MyEntity, ?>)
sortList.get(0).getColumn();
Integer columnIndex = table.getColumnIndex(sortColumn);
sortColumnName = columnNames.get(columnIndex);
}
// do your rpc call
*where MyEntity is your data object displayed in the cell table.
A bit late to the party, but here's a more straight-forward solution based off of the current documentation (see section 'ColumnSorting with AsyncDataProvider').
When we're adding our columns we can simply set the dataStoreName:
TextColumn<MyData> surname = new TextColumn<MyData>() {
...
}
surname.setSortable(true);
surname.setDataStoreName("surname"); // Set the column name
table.getColumnSortList().push(surname);
table.addColumn(surname, "Last Name"); // eg. A different name for the UI
Then we can retrieve the column's dataStoreName later when sorting:
#Override
protected void onRangedChanged(HasData<MyData> display) {
...
ColumnSortList.ColumnSortInfo info = table.getColumnSortList().get(0);
String sortColumn = info.getColumn().getDataStoreName(); // Get the column name
boolean sortIsAscending = info.isAscending();
rpcService.requestMyData(
sortColumn,
sortIsAscending,
new AsyncCallback<ArrayList<MyData>>() {...}
);
...
}
Using this method we can pass the column name directly to our RPC method. It even allows us to use a different name (eg. the database column name) than the column name used on the UI/client side.
I have used something like this as an application column object.
public class ScrollTableColumn
{
// --------------------------------------------------------------- Field(s)
private int sequence;
private Column column;
private Header header;
private int size;
private int calculatedSize;
private boolean show;
private PartialColumn partialColumn;
private ColumnNameEnum columnName;
}
Now create a HashMap of the above as follows:
Map<Column, ScrollTableColumn> columnMap
= new HashMap<Column, ScrollTableColumn>();
Add all the columns as you create them both in the ScrollTableColumn and in the columnMap.
Finally you can get the required name as:
ColumnSortList sortList = dataTable.getColumnSortList();
Column<?, ?> column = sortList.get(0).getColumn();
ColumnNameEnum = columnMap.get(column);
String name = ColumnNameEnum.getName();
The proper way is to extend the base column class which will allow you to override cell rendering, pass in column configuration via your constructor, and most importantly set the DataStoreName which is where you should store the field name for the column. Lastly you should not reuse the onrangechanged fire, but access the columnsort handler directly by overriding it. on range change and column sort handler should call some type of method that you have to update your grid. I call mine updateGrid for sanity. This allows you to set any grid parameters used by your async request to specific sort column and direction. The main reason you want to use column sort handler is to access the ColumnSort event which contains your sort direction information
your column class that extends the base GWT column. You can also extend date or number columns too.
public GridStringColumn(String fieldName, String text, String tooltip, boolean defaultShown, boolean sortable, boolean hidden) {
super(new TextCell());
setDataStoreName(fieldName);
this.text_ = text;
this.tooltip_ = tooltip;
this.defaultShown_ = defaultShown;
setSortable(sortable);
this.hidden_ = hidden;
}
create your handler
dataGrid.addColumnSortHandler(new DataGridSortEvent());
your sort event class
protected class DataGridSortEvent implements ColumnSortEvent.Handler {
#Override
public void onColumnSort(ColumnSortEvent event) {
ColumnSortList sortList = dataGrid_.getColumnSortList();
if (sortList != null && sortList.size() > 0) {
Column<T, ?> sortColumn = (Column<T, ?>) sortList.get(0).getColumn();
LOG.info("col_sorta: " + event.isSortAscending());
LOG.info("col_index: " + sortColumn.getDataStoreName());
updateDataList();
}
}
}
updateDataList is your method you use to make the actual AJAX request to your server side. rather then logging you sould store this info in private members of your datagrid class so that your request can parameterize them.
you could also make this work for local caching too, just make a copy of the data from your server locally then return a sorted collection of that cached collection, rather then calling the updateDataList method.
Now you do not need to store a separate list for just string names, which is waste of memory not to mention a synchronicity issue if the column order is change from user interaction or whatever.

Resources