Serenity+Cucumber: Reading testdata from Excel - excel

I am running Automation test cases with #RunWith(CucumberWithSerenity.class).
We want to expose and maintain the Testdata separately in the Excel sheets instead of placing it in the Feature files.
The Template for Excel Testdata looks like:
|Scenario |UserName |Password|Name |Address|City |Pincode|
|Testcase1|testuser1|pass1 |testUser1|US |Jersy |12345 |
|Testcase1|testuser2|pass1 |testUser1|US |Virginia|78955 |
We have chose to use Primary Key as 'Scenario' which would be present in both Feature file and Excel sheet and based on that we will read the specific row from excel and refer the specific row data as Testdata for that particular Scenario.
Questions:
Is there a way to get the Scenario Name at run time from Feature file when Test is running, so that we can get the Excel sheet the extract the data for it from the Excel Sheets?
Is there a default way/method available in above mentioned use case, so that we can use it for above use case?

Cucumber doesn't support external sources by design (it is a collaboration tool, not a test automation tool). In Serenity, you can build a parameterised JUnit test that gets data from a CSV file: http://serenity-bdd.info/docs/serenity/#_using_test_data_from_csv_files

public class ExcelDataTable {
private XSSFWorkbook book;
private FileInputStream file;
public String ReadDataSheet(String page, String path, int rowValue, int cellValue) throws IOException {
String pointer;
file = new FileInputStream(new File(path));
book = new XSSFWorkbook(file);
Sheet sheet = book.getSheet(page);
Row row = sheet.getRow(rowValue);
Cell cell = row.getCell(cellValue);
pointer = cell.getStringCellValue();
book.close();
file.close();
return pointer;
}
}
Just create a class with this code and here is how I'm using it
public class OpenWebSite implements Task {
ExcelDataTable data = new ExcelDataTable();
public static OpenWebSite openWebSite(){
return Tasks.instrumented(OpenWebSite.class);
}
#Override
public <T extends Actor> void performAs(T actor) {
try {
actor.attemptsTo(Open.url(data.ReadDataSheet("info", "Data.xlsx", 1, 1)));
}
catch (IOException e) {
e.printStackTrace();
}
}
}
Sort that out to make yours bro

Related

How to read real numeric values instead of formatted value using Apache XSSF POI streaming API?

I use streaming POI API and would like to read the real value of a cell instead of the formatted one. My code which is below works fine but if the user doesn't display all the digit of a value in the excel sheet which is readed by my code, I've got the same truncated value in my result. I didn't find any solution in the streaming API - which is needed in my case to solve memory issue I had using the POI API without streaming.
/**
* #see org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler.SheetContentsHandler cell(java.lang.String,
* java.lang.String)
*/
#Override
void cell(String cellReference, String formattedValue, XSSFComment comment) {
useTheCellValue(formattedValue)
}
If you are constructing the XSSFSheetXMLHandler you can provide a DataFormatter. So if you are creating your own DataFormatter this DataFormatter could give you fully access to the formatting issues.
Example of how this could look like by changing the public void processSheet of the XLSX2CSV example in svn:
...
public void processSheet(
StylesTable styles,
ReadOnlySharedStringsTable strings,
SheetContentsHandler sheetHandler,
InputStream sheetInputStream) throws IOException, SAXException {
//DataFormatter formatter = new DataFormatter();
DataFormatter formatter = new DataFormatter(java.util.Locale.US) {
//do never formatting double values but do formatting dates
public java.lang.String formatRawCellContents(double value, int formatIndex, java.lang.String formatString) {
if (org.apache.poi.ss.usermodel.DateUtil.isADateFormat(formatIndex, formatString)) {
return super.formatRawCellContents(value, formatIndex, formatString);
} else {
//return java.lang.String.valueOf(value);
return super.formatRawCellContents(value, 0, "General");
}
}
};
InputSource sheetSource = new InputSource(sheetInputStream);
try {
XMLReader sheetParser = SAXHelper.newXMLReader();
ContentHandler handler = new XSSFSheetXMLHandler(
styles, null, strings, sheetHandler, formatter, false);
sheetParser.setContentHandler(handler);
sheetParser.parse(sheetSource);
} catch(ParserConfigurationException e) {
throw new RuntimeException("SAX parser appears to be broken - " + e.getMessage());
}
}
...
I've seen a ticket on POI about this point : https://bz.apache.org/bugzilla/show_bug.cgi?id=61858
It provides a first solution by changing the existing class.
This could be an interesting workaround even if the ideal solution should be to use a standard one.

NPOI Write Corrupts File - Bare Ampersands

Using NPOI 2.1.3.1, I am trying to read an existing Excel (*.xlsx) workbook, modify it, and then write it back to the original file. After reading various threads (including this one), I still cannot find a solution to the problem I'm having.
When I write the file to disk and then try to open it again in Excel, I get the following error:
We found a problem with some content in (filename. Do you want us to
try to recover as much as we can? If you trust the source of this
workbook, click Yes.
Clicking "Yes" fixes various problems in the Excel file, after which I see the following report of the fixes performed:
Replaced Part: /xl/worksheets/sheet3.xml part with XML error. Illegal
name character. Line 3, column 3891168.
Replaced Part: /xl/worksheets/sheet19.xml part with XML error. Illegal name
character. Line 1, column 699903.
Removed Records: Formula from /xl/calcChain.xml part (Calculation properties)
I unzipped the *.xlsx file and found the sheets mentioned and discovered that the character it was referring to is a bare ampersand (&) that was not written as "&" in the XML. The original does use "&", but the file NPOI wrote does not. I have no idea what the issue is with the formula (third issue).
Here is a complete program that reproduces this issue every single time with the workbook I'm using, with the file name removed:
using System.IO;
using NPOI.XSSF.UserModel;
namespace NpoiTest
{
public sealed class NpoiTest
{
public static void Main(string[] args)
{
XSSFWorkbook workbook;
using (FileStream file = new FileStream(#"C:\Path\To\File.xlsx", FileMode.Open, FileAccess.Read))
{
workbook = new XSSFWorkbook(file);
}
using (FileStream file = new FileStream(#"C:\Path\To\File.xlsx", FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
{
workbook.Write(file);
}
}
}
}
As a test, I wrote pretty much the same program using Apache POI, to see if it was just a universal problem with my workbook, and the result was that POI didn't have any problems.
Here is the complete program:
package poitest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class PoiTest
{
public static void main(String[] args)
{
XSSFWorkbook workbook;
try (FileInputStream file = new FileInputStream(new File("C:\\Path\\To\\File.xlsx")))
{
workbook = new XSSFWorkbook(file);
}
catch (IOException e)
{
System.out.println(e.getMessage());
return;
}
try (FileOutputStream out = new FileOutputStream(new File("C:\\Path\\To\\File.xlsx")))
{
workbook.write(out);
}
catch (IOException e)
{
System.out.println(e.getMessage());
}
}
}
So the question is why is NPOI leaving the bare ampersands? Is this just a bug in NPOI?

Saving Monotouch.Dialog element values to a file

I'm using MonoTouch for developing my iPhone application. I want to use Monotouch. Dialog for showing some data to a client and let them change data and then save them to the file again.
My code is something like the code of Xamarin tutorials:
(Orginal Sample link)
public enum Category
{
Travel,
Lodging,
Books
}
public class ExpesObject{
public string name;
}
public class Expense
{
[Section("Expense Entry")]
[Entry("Enter expense name")]
public string Name;
[Section("Expense Details")]
[Caption("Description")]
[Entry]
public string Details;
[Checkbox]
public bool IsApproved = true;
[Caption("Category")]
public Category ExpenseCategory;
}
It is representing the TableView so good.
But the question is this, how we can save the data of this elements and the use them in other class of application? What is the best way for doing this?
I guess that we can save data to a file when user changed them. but how we can detect when the user change the data?
In the example you have shown, you are using the simple Reflection API for Monotouch.Dialog. While this is nice and easy, it really limits what you can do. I would suggest learning to use the Elements API seen here (http://docs.xamarin.com/guides/ios/user_interface/monotouch.dialog/elements_api_walkthrough) of Monotouch.Dialog which will give you so much more control over each item in the table, and be able to detect the changes, etc.
Each of the table cells (e.g. Name is a cell, which you can edit) have actions/events for when certain things happen, like text being changed.
For example, the above screen can be made with the elements API doing the following.
public class ExpenseViewController : DialogViewController
{
EntryElement nameEntry;
public ExpenseViewController() : base(null, true)
{
Root = CreateRootElement();
// Here is where you can handle text changing
nameEntry.Changed += (sender, e) => {
SaveEntryData(); // Make your own method of saving info.
};
}
void CreateRootElement(){
return new RootElement("Expense Form"){
new Section("Expense Entry"){
(nameEntry = new EntryElement("Name", "Enter expense name", "", false))
},
new Section("Expense Details"){
new EntryElement("Description", "", "", false),
new BooleanElement("Approved", false, ""),
new RootElement("Category", new Group("Categories")){
new CheckboxElement("Travel", true, "Categories"),
new CheckboxElement("Personal", false, "Categories"),
new CheckboxElement("Other", false, "Categories")
}
}
};
}
void SaveEntryData(){
// Implement some method for saving data. e.g. to file, or to a SQLite database.
}
}
Consider these areas to get started using the Elements API:
Source: https://github.com/migueldeicaza/MonoTouch.Dialog
MT.D intro: http://docs.xamarin.com/guides/ios/user_interface/monotouch.dialog
MT.D Elements walkthrough: http://docs.xamarin.com/guides/ios/user_interface/monotouch.dialog/elements_api_walkthrough

VSTO Excel: Restore ListObject data source when reopening a file

I am working on an Excel 2010 template project. In my template I have many sheets with static ListObject controls in each of them. To initialize my ListObject, I bind a BindingList<MyCustomType> so it generates a column for each of my MyCustomType public properties. It is really handy because when the user some rows in the ListObject, it automatically fills up my BindingList instance. I added a button in the Excel ribbon so that the program can validate and commit these rows through an EDM. This is how I bind my data to the ListObject in the startup event handler of one of my Excel sheet.
public partial class MyCustomTypesSheet
{
private BindingList<MyCustomType> myCustomTypes;
private void OnStartup(object sender, System.EventArgs e)
{
ExcelTools.ListObject myCustomTypeTable = this.MyCustomTypeData;
BindingList<MyCustomType> customTypes = new BindingList<MyCustomType>();
myCustomTypeTable.SetDataBinding(customTypes);
}
// Implementation detail...
}
Now my issue is that it is very likely that the user of this template will enter these rows in many sessions. It means that he will enter data, save the file, close it, reopen it, enter some new rows and eventually try to commit these rows when he thinks he is done. What I noticed is that when the Excel file created from the template is reopened, the DataSource property of my ListObject controls is null. Which means I have no way to get back the data from the ListObject into a BindingList<MyCustomType>. I have been searching and I found no automatic way to do that and I don't really want to make a piece of code that would crawl through all of the columns to recreate my MyCustomType instances. In an ideal world I would have done like this.
private void OnStartup(object sender, System.EventArgs e)
{
ExcelTools.ListObject myCustomTypeTable = this.MyCustomTypeData;
BindingList<MyCustomType> customTypes = null;
if (myCustomTypeTable.DataSource == null) // Will always be null and erase previous data.
{
customTypes = new BindingList<MyCustomType>();
myCustomTypeTable.SetDataBinding(customTypes);
}
else
{
customTypes = myCustomTypeTable.DataSource as BindingList<MyCustomType>;
}
}
I have been doing a lot of research on this but I was not able to find a solution so I hope some of your can help me to resolve this issue.
Thanks.
As a last solution I decided that I would serialize my object list in XML and then add it as a XML custom part to my Excel file on save. But when I got into MSDN documentation to achieve this, I found out that there was 2 ways to persist data: XML custom part and data caching. And actually data caching was exactly the functionality I was looking for.
So I have been able to achieve my goal by simply using the CachedAttribute.
public partial class MyCustomTypesSheet
{
[Cached]
public BindingList<MyCustomType> MyCustomTypesDataSource { get; set; }
private void OnStartup(object sender, System.EventArgs e)
{
ExcelTools.ListObject myCustomTypeTable = this.MyCustomTypeData;
if (this.MyCustomTypesDataSource == null)
{
this.MyCustomTypesDataSource = new BindingList<MyCustomType>();
this.MyCustomTypesDataSource.Add(new MyCustomType());
}
myCustomTypeTable.SetDataBinding(this.MyCustomTypesDataSource);
}
private void InternalStartup()
{
this.Startup += new System.EventHandler(OnStartup);
}
}
It works like a charm. You can find more information about data caching in MSDN documentation.

How to add a new item into ObjectListView?

I tried the demo code in demo project but I can't add new item successfully.
It just add new new NULL group and NULL item.
Please give me an simple example code to add new item (text and image).
Thank you!
Oh sorry! I forgot it. This is the first time I participate in this site.
I use C#. And the code is:
objectListView1.BeginUpdate();
objectListView1.AddObject(new string [] {"Hello","dfdsF" });
objectListView1.EndUpdate();
and
objectListView1.BeginUpdate();
OLVListItem item = new OLVListItem(new string [] {"Hello","dfdsF" });
objectListView1.Items.Add(item);
objectListView1.EndUpdate();
It's so different form ListView and EXListView which I can define a text or a image when creating new item. But in ObjectListView, I don't understand OBJECT?
I get ObjectListView anh it's demo code form here http://nchc.dl.sourceforge.net/project/objectlistview/objectlistview/v2.5/ObjectListViewFull-2.5.0.zip
I will show you what to do to add items. Try to create a class, then make getters and setters for the properties you want to show on your ObjectListView.
SetObjects method takes a List<T>:
public Form1()
{
InitializeComponent();
this.objectListView1.SetObjects(haha.GET());
}
Now this is my class, I called it haha, I've two properties in it (Name and Detail):
class haha
{
string name;
string detail;
public haha(string name , string detail)
{
this.name = name;
this.detail = detail;
}
public string Name
{
get { return name; }
set { name = value; }
}
public string Detail
{
get { return detail; }
set { detail = value; }
}
static internal List<haha> GET()
{
haha item = new haha("zeko", "dunno");
haha xx = new haha("sheshe", "dunno");
haha ww = new haha("murhaf", "dunno");
haha qq = new haha("soz", "dunno");
haha ee = new haha("HELLO", "dunno");
List<haha> x = new List<haha>();
x.Add(item);
x.Add(xx);
x.Add(ww);
x.Add(qq);
x.Add(ee);
return x;
}
}
Now
change ShowGroups in ObjectListView to false
then add the columns that you want; I've added two columns, one for Name and one for Detail
and as in the picture when you add a column, see the AspectName and write exactly the same name of its property that you want to show from your class
Here's the result:
If you want to use AddObject(), which takes an object, I'd write this:
private void button1_Click(object sender, EventArgs e)
{
haha newObject = new haha("memo","zezo");
objectListView1.AddObject(newObject);
}
Happy coding :)
The best thing is to use an entity class. Then make a list of items and add this list to your ObjectListView.
myObjectListView.SetObjects(myListofEntityItems);
But before you do that, you have to setup the columns in your designer. Just add a column, and in the field AspectName enter the exact name of the attribute of your entity item.

Resources