Enroll in Selenium Training

In the previous chapter of Transform Table into Dictionary we provided Vertical Data using Tables. That is useful when we have a long list of Data for e.g. Personal Information includes First Name, Last Name, Address and Job etc.

But this has some limitations like what if we want to execute the same step more than one time, it is not easy to manage that with Dictionary Key-Value pair. To obtain the functionality, it is required to use Horizontal Data rather than Vertical Data and that can be done by "Transform Table into DataTable".

Transform Table into DataTable

We will be using the same example of LogIn Feature and modify it according to our usage. Before moving on to this chapter, please have a look at the base chapter of Data Driven Testing and see how the simple functionality works for LogIn Scenario.

1) Create a New Step

The first step is to create a new Step which will take Data in Table format. It is again an easy job to specify data for the step in Horizontal format. Just provide the Header and their values.

When User enter credentials
	| Username   | Password |
	| testuser_1 | Test@123 |

2) Create a New Step Definition

The second step is to create a new Steps Definition for newly created step, which can be done if bring the cursor on the created step and press F12. The Specflow will display the pop up with the Skeleton body of the step, which can be copied and used accordingly.

    [When(@"User enter credentials")]
        public void WhenUserEnterCredentials(Table table)
        {

        }

3) Transform table into DataTable

To convert Table into DataTable, it is required to use System. Data package (using System.Data).

Create a new folder in the solution and name it as Utils. Then create a new C# class with the name TableExtensions in the same folder and create a new static method called ToDataTable(), which will accept Table data.

public static DataTable ToDataTable(Table table)
        {
            var dataTable = new DataTable();
            foreach (var header in table.Header)
            {
                dataTable.Columns.Add(header, typeof(string));
            }

            foreach (var row in table.Rows)
            {
                var newRow = dataTable.NewRow();
                foreach (var header in table.Header)
                {
                    newRow.SetField(header, row[header]);
                }
                dataTable.Rows.Add(newRow);
            }
            return dataTable;
        }

4) Complete Step Definition Method

Now make use of ToDataTable function and convert the Table data into DataTable.

[When(@"User enter credentials")]
        public void WhenUserEnterCredentials(Table table)
        {
            var dataTable = TableExtensions.ToDataTable(table);
            foreach (DataRow row in dataTable.Rows)
            {
                driver.FindElement(By.Id("log")).SendKeys(row.ItemArray[0].ToString());
                driver.FindElement(By.Id("pwd")).SendKeys(row.ItemArray[1].ToString());
                driver.FindElement(By.Id("login")).Click();
            }
        }

With this, one can use the multiple Data sets for the same step.

The complete code will look like this:

LogIn_Feature File

Feature: LogIn_Feature
	In order to access my account
    As a user of the website
    I want to log into the website

@mytag
Scenario: Successful Login with Valid Credentials
	Given User is at the Home Page
	And Navigate to LogIn Page
	When User enter credentials
	| Username   | Password |
	| testuser_1 | Test@123 |
	| testuser_2 | Test@154 |
	And Click on the LogIn button
	Then Successful LogIN message should display

Scenario: Successful LogOut
	When User LogOut from the Application
	Then Successful LogOut message should display

LogIn_Steps File

using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using TechTalk.SpecFlow;
using TechTalk.SpecFlow.Assist;
using SpecFlowDemo.Utils;
using System.Data;

namespace SpecFlowDemo.Steps
{
    [Binding]
    public class LogIn_Steps
    {
        public IWebDriver driver;
        [Given(@"User is at the Home Page")]
        public void GivenUserIsAtTheHomePage()
        {
           driver = new FirefoxDriver();
           driver.Url = "https://www.store.demoqa.com";
        }

        [Given(@"Navigate to LogIn Page")]
        public void GivenNavigateToLogInPage()
        {
            driver.FindElement(By.XPath(".//*[@id='account']/a")).Click();
        }

        [When(@"User enter credentials")]
        public void WhenUserEnterCredentials(Table table)
        {
            var dataTable = TableExtensions.ToDataTable(table);
            foreach (DataRow row in dataTable.Rows)
            {
                driver.FindElement(By.Id("log")).SendKeys(row.ItemArray[0].ToString());
                driver.FindElement(By.Id("pwd")).SendKeys(row.ItemArray[1].ToString());
                driver.FindElement(By.Id("login")).Click();
                driver.FindElement(By.Id("log")).Clear();
                driver.FindElement(By.Id("pwd")).Clear();
            }
        }

        [When(@"Click on the LogIn button")]
        public void WhenClickOnTheLogInButton()
        {
            driver.FindElement(By.Id("login")).Click();
        }

        [When(@"User LogOut from the Application")]
        public void WhenUserLogOutFromTheApplication()
        {
            ScenarioContext.Current.Pending();
        }

        [Then(@"Successful LogIN message should display")]
        public void ThenSuccessfulLogINMessageShouldDisplay()
        {
            //This Checks that if the LogOut button is displayed
            true.Equals(driver.FindElement(By.XPath(".//*[@id='account_logout']/a")).Displayed);
        }

        [Then(@"Successful LogOut message should display")]
        public void ThenSuccessfulLogOutMessageShouldDisplay()
        {
            ScenarioContext.Current.Pending();
        }
    }
}

TableExtension Class File

using System.Data;
using TechTalk.SpecFlow;

namespace SpecFlowDemo.Utils
{
    public class TableExtensions
    {

        public static DataTable ToDataTable(Table table)
        {
            var dataTable = new DataTable();
            foreach (var header in table.Header)
            {
                dataTable.Columns.Add(header, typeof(string));
            }

            foreach (var row in table.Rows)
            {
                var newRow = dataTable.NewRow();
                foreach (var header in table.Header)
                {
                    newRow.SetField(header, row[header]);
                }
                dataTable.Rows.Add(newRow);
            }
            return dataTable;
        }

    }
}

Project Solution Explorer

TableRows_1

Tables in Specflow
Tables in Specflow
Previous Article
CreateInstance in SpecFlow Table
CreateInstance in SpecFlow Table
Next Article
Lakshay Sharma
I’M LAKSHAY SHARMA AND I’M A FULL-STACK TEST AUTOMATION ENGINEER. Have passed 16 years playing with automation in mammoth projects like O2 (UK), Sprint (US), TD Bank (CA), Canadian Tire (CA), NHS (UK) & ASOS(UK). Currently, I am working with RABO Bank as a Chapter Lead QA. I am passionate about designing Automation Frameworks that follow OOPS concepts and Design patterns.
Reviewers
Virender Singh's Photo
Virender Singh

Similar Articles

Feedback