IDEA does not allow me to use table.raw();
I am new in cucumber so while I was learning/practising I tried to get the data from a DataTable by the following code
public void iEnterTheFollowingForLogin(DataTable table) {
List<List<String>> data = table.raw();
System.out.println("The value is : "+ data.get(1).get(0).toString());
System.out.println("The value is : "+ data.get(1).get(1).toString());
}
I realized that IDEA type the raw method in red so I think maybe it is obsolete and now I should use a newer one.
Rather then accessing the raw table you can address individual cells directly using cell(row, column) or use cells() to get a list of lists.
import io.cucumber.datatable.DataTable;
import java.util.List;
class Scratch {
public static void main(String[] args) {
DataTable data = //...create data table here
System.out.println("The value is : " + data.cell(1, 0));
System.out.println("The value is : " + data.cell(1, 1));
List<List<String>> cells = data.cells();
System.out.println("The value is : " + cells.get(1).get(0));
System.out.println("The value is : " + cells.get(1).get(1));
}
}
Just Want to explain MP's answer in detail for others easy understanding-
Yes you wont be able to use raw() method anymore as, its not supported by cucumber api with newer versions of cucumber i.e. io.cucumber. However One can still still use it with older info.cukes dependencies.
So an alternative to raw() is as answered by MP.
For ex- Let's say you have below- Sample gherkin Step:
Then I should see following sections in my app detail page
|Basic Details|Bank Details|Reconciliation|Summarised Options|Currency Code|
>> The Cucumber step definition for above step should be like belwo-
#Then("I should see following sections in my app detail page")
public void verifySectionsOnDetailPageUI(List<List<String>> dTable) {
//Create your table as below (notice- dataTable declared as- List<List<String>> in method argument above)
DataTable data= DataTable.create(dTable);
// to get number of rows from DataTable
int i=data.cells().size();
// To print entire row's column (iterate via for loop using size if u have more than one row defined in data table
System.out.println("All Cells Data: "+data.cells());
//Read cell by cell data as below, row index to be started from 1 if you have column headings provided in ur table
System.out.println(data.cell(0,0));
System.out.println(data.cell(0,1));
System.out.println(data.cell(0,2));
.....
......... so On .. to be used as per your step's objective .....
O/P:
Basic Details
Bank Details
Reconciliation
Related
The only data that should appear when I click the "view data button" should be the employee's personal data by searching its employee id.
This is my code:
public void viewAll() {
btnview.setOnClickListener(
new View.OnClickListener() {
#Override`enter code here`
public void onClick(View v) {
Cursor res = EmployeeData.getAllData();
if(res.getCount() == 0) {
// show message
showMessage("Error","Nothing found");
return;}
How can I get the specific data from the existing database?
You need to replace the getAllData with a method that SELECTs the appropriate data using a WHERE clause which is invoked with the employeeId being passed to it (after extracting the employeeId from the clicked item ).
You then need to process the Cursor by extracting the data from it, if any exists.
So you could have something like the following in your class that extends SQLiteOpenHelper :-
public Cursor getEmployeeDataById(long id) {
return this.getWritableDatabase().query("the_table",null,"employeeId=?",new String[]{String.valueOf(id)},null, null,null);
}
obviously "the_table" and "employeeId" should be replaced by the actual names.
see Query for an explanation of the method's parameters.
the Query (method which has 4 signatures) is a convenience method that returns a Cursor object.
-It generates the SQL on your behalf e.g. the above would generate the SQL SELECT * FROM the_table WHERE employeeId=?
- where the ? is bound (prevents SQL Injection) to the passed id value by SQLite.
When extracting the data from the Cursor, rather than checking the count, you can rely upon the fact that the Cursor's will return false if it cannot move to the first row (i.e. there is no first row). So extracting the data could be along the lines of:-
Cursor csr = EmployeeData.getEmployeeDataById(extracted_employee_id);
if (csr.moveToFirst()) {
.... extract the data from the cursor
} else {
showMessage("Error","Nothing found");
}
A website that I am testing at the moment derives value from the DB and it's dynamic. I need to be able to fetch the value from DB and validate that against what is present in UI which will not be static. The text I am trying to verify is below, for this, I need to identify the element and verify text by comparing the data from DB and what is present on the screen. The specific text here in this example is "Resource". The same span is repeated several times with different values in the same screen. Please help as to how can I identify the element as well validating against DB. I am new to selenium WebDriver.
<span class="card-title grey-text">Resource</span>
If span value "Resource" is dynamic every time, try to retrieve it by following :
driver.findElement(By.xpath("//span[#class='card-title grey-text']")).getText();
You could gather all spans in list and validate against DB values:
int iCnt=0;
List<String> listDB = new ArrayList();
public List<String> DBconnection(){
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection con = DriverManager.getConnection("jdbc:mysql://localhost/t", "", "");
Statement st = con.createStatement();
String sql = ("SELECT * FROM table ORDER BY id;");
ResultSet rs = st.executeQuery(sql);
if(rs.next()) {
listDB.add(rs.getString("second_column_name"));
}
con.close();
return list;
}
//testing part
public void testAginstDb(List<String> listDB){
List<WebElement> listSpan =
driver.findElement(By.cssSelector("span.card-title.grey-text"));
for(String itemDb : listDB){
for (WebElement item : listSpan) {
if(item.getText().equals(rs.value())){
iCnt+=1;
break;
}
}
Assert.equals(list.size(), iCNT);
}
}
Sorry code was written from head, maybe there are some mistakes, essentially I would make that approach.
Hope it helps,
As part of Selenium Web-driver learning I came across a scenario. Please let me know the professional approach to proceed.
I am testing a eCommerce application where while I click on Mobile link all mobile phones are getting displayed.I want to check whether they are sorted based on name and price. So basically I need to get Name & price of all elements in the result page.
So My Question is there any way I can map html elements to java value objects ? Any API already available for doing this mapping for me ? Something similar to gson api for converting java objects to their corresponding Json representation ?
Deepu Nair
//Get all the mobile phones links into a list before sorting
List<WebElement> mobilelinks=driver.findElements(("locator"));
Map maps = new LinkedHashMap();//use linked hash map as it preserves the insertion order
for(int i=0;i<mobilelinks.size();i++){
//store the name and price as key value pair in map
maps.put("mobilelinks.get(i).getAttribute('name')","mobilelinks.get(i).getAttribute('price')" );
}
/*sort the map based on keys(names) store it in a separate list
sort the map based on values(prices) store it in a separate list
*/
/* Using webdriver click the sort by name and compare it with the list which we got after sorting
and also click sort by prices and compare it with the list*/
To catch an assertion and continue with the test after assertion failures override the Assertion class and create your own CustomAssertion or use SoftAssertions
CustomAssertion.java
public class CustomAssertions extends Assertion {
private Map<AssertionError, IAssert> m_errors = Maps.newLinkedHashMap();
#Override
public void executeAssert(IAssert a) {
try {
a.doAssert();
} catch(AssertionError ex) {
onAssertFailure(a, ex);
System.out.println(a.getActual());
System.out.println(ex.getMessage());
m_errors.put(ex, a);
}
}
public void assertAll() {
if (! m_errors.isEmpty()) {
StringBuilder sb = new StringBuilder("The following asserts failed:\n");
boolean first = true;
for (Map.Entry<AssertionError, IAssert> ae : m_errors.entrySet()) {
if (first) {
first = false;
} else {
sb.append(", ");
}
sb.append(ae.getKey().getMessage());
}
throw new AssertionError(sb.toString());
}
}
}
Instead of using Assertions class to verify the tests use CustomAssertions class
Ex:
//create an object of CustomAssertions class
CustomAssertions custom_assert=new CustomAssertions();
cust_assert.assertTrue(2<1);
cust_assert.assertEquals("test", "testing");
//and finally after finishing the test in aftersuite method call
cust_assert.assertAll();
Hope this helps you if you have any doubts kindly get back...
I'm linking all our our System Tests to test cases and to our Requirements. Every requirement has an ID. Every Test Case / System Tests tests a variety of requirements. Every module of code links to multiple requirements.
I'm trying to find the best way to link every system test to its driving requirements.
I was hoping to do something like:
[NUnit.Framework.Property("Release", "6.0.0")]
[NUnit.Framework.Property("Requirement", "FR50082")]
[NUnit.Framework.Property("Requirement", "FR50084")]
[NUnit.Framework.Property("Requirement", "FR50085")]
[TestCase(....)]
public void TestSomething(string a, string b...)
However, that will break because Property is a Key-Value pair. The system will not allow me to have multiple Properties with the same key.
The reason I'm wanting this is to be able to test specific requirements in our system if a module changes that touches these requirements.
Rather than run over 1,000 system tests on every build, this would allow us to target what to test based on changes done to our code.
Some system tests run upwards of 5 minutes (Enterprise healthcare system), so "Just run all of them" isn't a viable solution. We do that, but only before promoting through our environments.
Thoughts?
Have you considered a custom property attribute derived from NUnit.Framework.Property?
Something like the following seems like it might work for you judging by a LINQPad 4 "query" with Language set to C# Program and a reference to nunit.framework.dll (version 2.4.8) added:
// main method to exercise a our PoC test case
void Main()
{
TestSomething("a", "b");
}
// our PoC custom property attribute
[AttributeUsage(AttributeTargets.Method, AllowMultiple=false)]
public class RequirementsAttribute : NUnit.Framework.PropertyAttribute
{
public RequirementsAttribute(string[] requirements)
: base(requirements)
{
}
}
// a test case using our custom property attribute to relate it to multiple requirements
[Requirements(new string[] { "FR50082", "FR50084" })]
[TestCase("PoCTest")]
public void TestSomething(string a, string b)
{
// blah, blah, blah
Assert.AreNotEqual(a, b);
}
For some reason I could not add the link to the google discussion post to the comment above, so I have added the post here too. (The link is https://groups.google.com/forum/#!topic/nunit-discuss/ndV3VTPndck)
A Category is always displayed in TE as "Category [xxxxxxx]", where xxxxx is whatever string you send in, if you don't specify any, it will be the name of the class derived from CategoryAttribute.
If you want to use Category, you should, as Charlie said on the google post, use one entry per requirement. If you add the string Requirement to the value, it can look pretty good, but most follow the rules in (1) above, it could be like:
Category[Requirement:FR12345]
Code:
public class RequirementAttribute : CategoryAttribute
{
public RequirementAttribute(string s)
: base("Requirement:" + s)
{ }
}
If you want it to display like : Requirement[FR12345], then you MUST use a Property, but you can't have multiple Keys, so only one such per test.
Code:
public class RequirementAttribute : PropertyAttribute
{
public RequirementAttribute(string s)
: base(s)
{}
}
4: If you want to have multiple requirements per test and still have something like the display in (3), you must make the keys unique. It doesn't need to look too bad. In the code below I have just added a counter to it.
It will display as :
Requirement-1[FR12345]
Requirement-2[FR23456]
Code:
public class RequirementAttribute : PropertyAttribute
{
public RequirementAttribute(string[] array)
{
int i = 0;
foreach (var s in array)
{
Properties.Add("Requirement-" + i, s);
i++;
}
}
}
and you use it like:
[Requirement(new[] { "1234", "2345" })]
[Test]
public void Test()
{ }
(And if you want a syntax without the "new", the previous answer show that syntax with the param instead.)
Option 4 will not group by requirement number, but by the counter. If you want to group by requirement number you can use option 5:
5.
Add the requirement number to the key, but leave the value blank.
It will look like:
Requirement-FR12345
In this way, you also skip the prefix and have each requirement as its own kind of category in the TE.
Code:
public class RequirementAttribute : PropertyAttribute
{
public RequirementAttribute(string[] array)
{
foreach (var s in array)
{
Properties.Add("Requirement-" + s,"");
}
}
}
And, you could of course also skip the prefix altogether.
Scenario:
I have built a testNG class which contains multiple test methods + an excel read method.I wish to put All the test methods to Iteration depending upon the no of rows in the excel sheet.
Also I wish to selectively utilize the data values amongst test methods. ie
all column 1 values to be used in test 1 only..
all col 2 values to be used in test 2 only.. so on..
I do not think this is possible through a single instance of DataProvider which is something I wish for.
Any help appreciated.
FYI I am pasting my Programming logic here:
My Programming Code:
public class sample {
#DataProvider(name = "dp")
public static Object[][] readExcel() {
.
.
.
.
return data;
}
#Test(dataProvider = "dp")
public void test1(String a,String b) throws Exception {
System.out.println("test 1 OUTPUT IS "+ a);
}
#Test(dataProvider = "dp")
public void test2(String a,String b) throws Exception {
System.out.println("test 1 OUTPUT IS "+ b);
}
}
{Data in excel :
Row 1: sam miller
Row 2: peter paul
Output (presently coming):
test 1 OUTPUT IS sam;
test 1 OUTPUT IS peter;
test 2 OUTPUT IS miller;
test 2 OUTPUT IS paul;
Output (that is required):
test 1 OUTPUT IS sam;
test 2 OUTPUT IS miller;
test 1 OUTPUT IS peter;
test 2 OUTPUT IS paul;
}
Your dataprovider can take your method as input. You can probably name your column headers with TC name and only fetch values of column method name in your dataprovider, something like
Courtesy TestNG documentation : "If you declare your #DataProvider as taking a java.lang.reflect.Method as first parameter, TestNG will pass the current test method for this first parameter. This is particularly useful when several test methods use the same #DataProvider and you want it to return different values depending on which test method it is supplying data for."