SK.
SK.

Reputation: 4358

Specflow - How to pass environment specific data from Specflow example table

I have a couple of Specflow's features file which contain multiple scenarios and I want to execute them against multiple environments (DEV, TEST, and SIT).

So, my question here is - what is the best way to pass environment specific data from feature file to step definition. As you can see in the example below employee records are different in each environment.

Scenario Outline: Employee Search
Given Application is logged
And Search for employee record with <EmployeeName>, <EmployeeID>, <Company>, <Designation> and <Environment>
 Examples: 
        | EmployeeName| EmployeeID| Company  | Designation | Environment |
        | John Smith 1| 123       | ABC      | Analyst     | DEV         |
        | John Smith 2| 456       | DFG      | Manager     | TEST        |
        | John Smith 3| 789       | XYZ      | Sr Analyst  | SIT         |

[When(@"Search for employee record with (.*), (.*), (.*), (.*) and (.*)")]
    public void WhenSearchEmployee (string EmployeeName, string EmployeeID, string Company, string Designation, string Environment)
    {
        if (Environment== "DEV")
        {
            EmployeeRecord.SearchEmployee(EmployeeName, EmployeeID, Company, Designation);
        }
        else if (Environment== "TEST")
        {
            EmployeeRecord.SearchEmployee(EmployeeName, EmployeeID, Company, Designation);
        }
        else if (Environment== "SIT")
        {
            EmployeeRecord.SearchEmployee(EmployeeName, EmployeeID, Company, Designation);
        }
    }

Edits

Basically, I want to execute the same test case in multiple environments (one at a time) with different data. Also if I have two rows in examples table, how to execute only once based on the environment.

Is this the right approach? Thanks.

Upvotes: 0

Views: 3142

Answers (2)

Dazed
Dazed

Reputation: 1551

If you can't create on demand each time, here is another way.

Create a data.cs file.

public class EnvData
{
    public EnvData()
    {
        { 
            defaultEmail = "[email protected]";
            defaultPassword = "MyPass123";
        }


        if(ConfigurationManager.AppSettings["Env"] == "Test")
        {
            empName = "John Smith";
            EmployeeID = "1234";
            Company = "McDonalds";
            Designation = "McManager";
           
        }
        else if (ConfigurationManager.AppSettings["Env"] == "Dev")
        {
            empName = "Joe Smith";
            EmployeeID = "3456";
            Company = "McDonalds";
            Designation = "FryGuy";
           
        }
    }

      public static string defaultEmail;
      public static string defaultPassword;
      public static string empName;
      public static string EmployeeID;  //can be an int
      public static string Company;
      public static string Designation;

  }
}

Then in your step file we use context injection - https://specflow.org/documentation/context-injection/

    private readonly EnvData _envData;

    public MyClassName(EnvData envData)
    {
        _envData = envData;
    }

The reason you do it this way is that if you need to change the data, you change it in one area and not in each test case.

Scenario: Employee Search
Given Application is logged
And Search for an employee


  [When(@"Search for employee]
  public void WhenSearchEmployee ()
  {

  //would look something like this...

          EmployeeRecord.SearchEmployee(envData.empName, envData.EmployeeID, envData.Company, envData.Designation);
   
       }

So in the above, the step will hit envData and based on the appconfig value for the environment, it will pull whatever employee info you set. This works great if your data is static. I still prefer creating the search criteria first and then searching so you do not have to do all this lol.

Upvotes: 0

Patrick McDonough
Patrick McDonough

Reputation: 1

Since you are already passing the environment in the step, I would personally pass that value to a database object constructor that switches the connection string from your app.config based on the constructor input.

Example using Entity Framework:

public void WhenSearchEmployee (string EmployeeName, string EmployeeID, string Company, string Designation, string Environment) {    
    using (var context = new SomeContext(Environment)) {        
         // Search Employee code here
    }
}

Then you can pass that value to the DbContext base class which can select your environment by matching the name parameter from your app.config <connectionStrings>. EF will do this automatically, but if you're using ado.net you can still do something similar.

public partial class SomeContext : DbContext {
    public SomeContext(string dbName) : base($"name={dbName}") {
    }
}

In the end, anytime you need to use an environment specific database for your steps, calling this context and passing the environment name will make all your steps generic enough to not care which environment they are executing against.

Upvotes: 0

Related Questions