SpecFlow: 02 - Gherkin Wiring

SpecFlow Feature File

  • The Feature file uses common Gherkin language
  • In a given project, normally this would be placed in a dedicated Features folder
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 'UnityAdmin' and 'UnityAdmin@2017'
    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

SpecFlow Test Definitions Generation

  • Once Feature file is created, the SpeckFlow 'Generate Definitions' option will auto-generate the required methods & open a dialog to save the newly created class file.
  • In a given project, normally this would be placed in a dedicated Definitions folder
using NUnit.Framework;
using System;
using TechTalk.SpecFlow;

namespace SpecFlowDemo
{
    [Binding]
    public class LogIn_FeatureSteps
    {
        IWebDriver driver;

        [Given(@"User is at the Home Page")]
        public void GivenUserIsAtTheHomePage()
        {
            ScenarioContext.Current.Pending();
        }
        
        [Given(@"Navigate to LogIn Page")]
        public void GivenNavigateToLogInPage()
        {
            ScenarioContext.Current.Pending();
        }
        
        [When(@"User enter '(.*)' and '(.*)'")]
        public void WhenUserEnterUserNameAndPassword(string username, string password)
        {
            ScenarioContext.Current.Pending();
        }
        
        [When(@"Click on the LogIn button")]
        public void WhenClickOnTheLogInButton()
        {
            ScenarioContext.Current.Pending();
        }
        
        [When(@"User LogOut from the Application")]
        public void WhenUserLogOutFromTheApplication()
        {
            ScenarioContext.Current.Pending();
        }

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

SpecFlow Test Runner

  • While there is a SpecFlow Test Runner, the 'free' version inserts a 'wait' between tests, so use NUnit to avoid this

SpecFlow Test Runner Options

NUnit Test Runner Execution

  • Build the project before running any tests as this should populate the runner with available tests
  • Run the tests to verify everything is wired up correctly & the test runner doesn't encounter errors

Selenium Inline Test Logic

  • Adding Selenium Logic directly into the Step Definitions for now for purposes of illustrating SpecFlow test execution
  • Selenium PageObject Model should be used in the long term
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.Support.UI;
using System;
using System.IO;
using TechTalk.SpecFlow;

namespace SpecFlowDemo
{
    [Binding]
    public class LogIn_FeatureSteps
    {
        IWebDriver driver;

        [Given(@"User is at the Home Page")]
        public void GivenUserIsAtTheHomePage()
        {
            driver = new FirefoxDriver("C:\\Users\\silosix\\source\\repos\\CEssentials2018\\SpecFlowDemo");
            driver.Manage().Timeouts().ImplicitWait = System.TimeSpan.FromSeconds(15);
            driver.Url = "http://www.unityconstruct.org/uc";
            Assert.True(driver.Title == "Home | UnityConstruct");
        }
        
        [Given(@"Navigate to LogIn Page")]
        public void GivenNavigateToLogInPage()
        {
            driver.FindElement(By.XPath("//a[@href='/uc/user/login']")).Click();
            Assert.True(driver.Title == "Log in | UnityConstruct", "Login Page Title is not correct");
        }
        
        [When(@"User enter '(.*)' and '(.*)'")]
        public void WhenUserEnterUserNameAndPassword(string username, string password)
        {
            driver.FindElement(By.Id("edit-name")).SendKeys(username);
            driver.FindElement(By.Id("edit-pass")).SendKeys(password);
        }
        
        [When(@"Click on the LogIn button")]
        public void WhenClickOnTheLogInButton()
        {
            driver.FindElement(By.Id("edit-submit")).Click();
        }
        
        [When(@"User LogOut from the Application")]
        public void WhenUserLogOutFromTheApplication()
        {
            ScenarioContext.Current.Pending(); 
        }

        [Then(@"Successful LogIN message should display")]
        public void ThenSuccessfulLogINMessageShouldDisplay()
        {
            bool b = driver.FindElement(By.XPath("//h1[contains(.,'UnityAdmin')]")).Displayed;
            driver.Quit();
            Assert.True(b, "Login not successful, h1/username not found");        
        }
        
        [Then(@"Successful LogOut message should display")]
        public void ThenSuccessfulLogOutMessageShouldDisplay()
        {
             ScenarioContext.Current.Pending();
        }
    }
}

??DryRun=true

??DryRun=false

??Test Output