Creating the Base Scenarios

Validating the Title of a Website

Creating the SpecFlow Scenario

  1. Open up the ‘BaseScenarios.feature’ file and add the following test scenario. We can also add a tag (e.g. ‘@Chrome’ for Chrome or ‘@HeadlessFirefox’ for Firefox in headless mode, either above the ‘Scenario’ (to apply to the specific scenario) or above the ‘Feature’ (to apply to all scenarios within the feature)…
    @Chrome
    Feature: BaseScenarios
     These scenarios can be used in any project
     
     Scenario: 01. Validate the title of a website
       Given a DuckDuckGo user is on the base page
       Then they see the page title contains "DuckDuckGo"

    The Given and Then steps are still undefined, so let’s add definitions for them now.

Creating the Undefined Step Definitions

  1. Copy the method below in BaseSteps class for the undefined Given step…
    using TechTalk.SpecFlow;
    
    namespace ProductAutomation.Steps.BaseSteps
    {
        [Binding]
        public class BaseSteps
        {
            [Given(@"a DuckDuckGo user is on the base page")] 
            public void GivenIAmOnTheBasePage() 
            { 
                throw new PendingStepException(); 
            }
        }
    }
  2. Because our base page is also the search page, let’s slightly tweak our undefined ‘Given’ step definition so that we can use RegEx to either use the word ‘base’ or ‘search’ when referring to the step and being on the page, without capturing the match and also accept either DuckDuckGo user or internet user(see https://agileforall.com/just-enough-regular-expressions-for-cucumber/ for more info…
    using TechTalk.SpecFlow;
    
    namespace ProductAutomation.Steps.BaseSteps
    {
        [Binding]
        public class BaseSteps
        {
            [Given(@"(?:a DuckDuckGo|an internet) user is on the (?:base|search) page")] 
            public void GivenIAmOnTheBasePage() 
            { 
                throw new PendingStepException(); 
            }
        }
    }
  3. Next, copy the method for the undefined Then step definition to the BaseSteps class…
    using TechTalk.SpecFlow;
    
    namespace ProductAutomation.Steps.BaseSteps
    {
        [Binding]
        public class BaseSteps
        {
            [Given(@"(?:a DuckDuckGo|an internet) user is on the (?:base|search) page")]  
            public void GivenIAmOnTheBasePage() 
            { 
                throw new PendingStepException(); 
            }
    
            [Then(@"they see the page title contains ""(.*)""")]
            public void ThenIseeThePageTitleContains(string expectedTitle)
            {
                throw new PendingStepException();
            }
        }
    }

Creating the Test Methods

  1. Open up the ‘BasePage.cs’ class file in the ‘Pages’ namespace and add the following method to navigate to the Base URL (as defined in your ‘Settings.cs’ class file, with the whole thing looking similar to below…
    using System;
    using OpenQA.Selenium;
    using ProductAutomation.Utils.Selenium;
    
    using static ProductAutomation.Utils.Selenium.Settings;
    
    namespace ProductAutomation.Pages
    {
        public class BasePage
        {
            protected IWebDriver driver = Driver.CurrentDriver;
    
            public void NavigateBaseUrl()
            {
                driver.Navigate().GoToUrl(baseUrl);
                driver.Manage().Window.Maximize();
                Console.WriteLine(" :: The base URL is navigated to");
            }
        }
    }
  2. Also add another method for asserting the page title contains the expected string…
    public void ValidatePageTitle(string expectedTitle 
    {
        var titleToValidate = GetTitle.Contains(expectedTitle);
        Assert.IsTrue(titleToValidate, " :: The actual page title is incorrect");
        Console.WriteLine(" :: The title of the site is " + GetTitle);
    }

    For the above to work, you will also need to add a GetTitle() method near the top of the class (near where Driver is declared), which returns Driver.GetTitle() …

    public string GetTitle => Driver.CurrentDriver.Title;

The whole thing should look similar to below when done…

using System;
using NUnit.Framework;
using OpenQA.Selenium;
using ProductAutomation.Utils.Selenium;

using static ProductAutomation.Utils.Selenium.Settings;

namespace ProductAutomation.Pages
{
    public class BasePage
    {
        protected IWebDriver driver = Driver.CurrentDriver;
        public string GetTitle => Driver.CurrentDriver.Title;

        public void NavigateBaseUrl()
        {
            driver.Navigate().GoToUrl(baseUrl);
            driver.Manage().Window.Maximize();
            Console.WriteLine(" :: The base URL is navigated to");
        }
    }
}

Connecting the Step Definitions to the Test Methods

We will now call the test methods from their appropriate step definitions. This whole POM approach is nice as we have suitable layers of abstraction, which helps the code be easier to read.  It also allows the step definitions to simply contain one line of code when calling the test methods.

  1. Open up the ‘BaseSteps.cs’ step definition class file again, and refactor the class to look like below, noting how we initialise our basePage object at the top and how we keep assertions outside of our page classes…
    using NUnit.Framework;
    using System;
    using ProductAutomation.Pages;
    using TechTalk.SpecFlow;
    
    namespace ProductAutomation.Steps.BaseSteps
    {
        [Binding]
        public class BaseSteps
        {
            private BasePage basePage = new BasePage();
    
            [Given(@"(?:a DuckDuckGo|an internet) user is on the (?:base|search) page")] 
            public void GivenIAmOnTheBasePage() 
            { 
                basePage.NavigateBaseUrl();
            }
    
            [Then(@"they see the page title contains ""(.*)""")]
            public void ThenIseeThePageTitleContains(string expectedTitle)
            {
                var titleToValidate = basePage.GetTitle.Contains(expectedTitle);
                Assert.IsTrue(titleToValidate, " :: The actual page title is incorrect");
                Console.WriteLine(" :: The actual page title is " + titleToValidate);
            }
        }
    }

Validate the URL of the Website

Creating the SpecFlow scenario

  1. Open up the ‘BaseScenarios.feature’ file and add the following test scenario…
    Scenario: 02. Validate the Url of a webpage
        Given a DuckDuckGo user is on the base page
        Then the page URL contains "https://start.duckduckgo.com"

Creating the Undefined Step Definition

  1. Next, let’s create the undefined step definition for the Then step…
    [Then(@"they see the page title contains ""(.*)""")]
    public void ThenIseeThePageTitleContains(string expectedTitle)
    {
        throw new PendingStepException();
    }

Creating the Test Method

We will now create the test method in C# for our undefined ‘Then’ step 😀

  1. Let’s add a GetUrl() property near the top of the BasePage class (near where Driver is declared), which returns Driver.GetUrl() …
    public string GetUrl => Driver.CurrentDriver.Url;

Defining the Step Definition

  1. Open up the BaseSteps.cs class and add the assertions to the step definition, using the GetUrl property we just added to the BasePage…
    [Then(@"the page URL contains ""(.*)""")]
    public void ThenISeeThePageUrlContains(string expectedUrl)
    {
        var urlToValidate = basePage.GetUrl.Contains(expectedUrl);
        Assert.IsTrue(urlToValidate, " :: The actual page Url is different");
        Console.WriteLine(" :: The actual page URL is " + urlToValidate);
    }

    The whole thing should look like below…

    using System;
    using NUnit.Framework;
    using ProductAutomation.Pages;
    using TechTalk.SpecFlow;
    
    namespace ProductAutomation.Steps.BaseSteps
    {
        [Binding]
        public class BaseSteps
        {
            private BasePage basePage = new BasePage();
    
            [Given(@"(?:a DuckDuckGo|an internet) user is on the (?:base|search) page")] 
            public void GivenIAmOnTheBasePage() 
            { 
                basePage.NavigateBaseUrl();
            }
    
            [Then(@"they see the page title contains ""(.*)""")]
            public void ThenIseeThePageTitleContains(string expectedTitle)
            {
                var titleToValidate = basePage.GetTitle.Contains(expectedTitle);
                Assert.IsTrue(titleToValidate, " :: The actual page title is different");
                Console.WriteLine(" :: The actual page title is " + titleToValidate);
            }
    
            [Then(@"the page URL contains ""(.*)""")]
            public void ThenISeeThePageUrlContains(string expectedUrl)
            {
                var urlToValidate = basePage.GetUrl.Contains(expectedUrl);
                Assert.IsTrue(urlToValidate, " :: The actual page Url is different");
                Console.WriteLine(" :: The actual page URL is " + urlToValidate);
            }
        }
    }

Validate a PageSource String on the Website

Creating the SpecFlow Scenario

  1. Open up the ‘BaseScenarios.feature’ file and add the following test scenario…
    Scenario: 03. Validate the PageSource string on a web page
        Given a DuckDuckGo user is on the base page
        Then they see "DuckDuckGo" in the PageSource

Creating the Undefined Step Definition

  1. Next, let’s create the method for the undefined step definition and add it to the BaseSteps class again…
  2. [Then(@"they see ""(.*)"" in the PageSource")]
    public void ThenISeeInThePageSource(string expectedText)
    {
        throw new PendingStepException();
    }

Creating the Test property

  1. Open up the BasePage class again and add a new property for the current page source
    public string GetPageSource => Driver.CurrentDriver.PageSource;

Defining the Step Definition

  1. Open up the ‘BaseSteps.cs’ class file again, and add the assertion to the step definition…
    [Then(@"they see ""(.*)"" in the PageSource")]
    public void ThenISeeInThePageSource(string expectedText)
    {
        var pageSourceTextToValidate = basePage.GetPageSource.Contains(expectedText);
        Assert.IsTrue(pageSourceTextToValidate, " :: The expected string is not present in the page source");
        Console.WriteLine(" :: The page source does not contain " + expectedText);
    }

    The whole thing should look like below…

    using System;
    using NUnit.Framework;
    using ProductAutomation.Pages;
    using TechTalk.SpecFlow;
    
    namespace ProductAutomation.Steps.BaseSteps
    {
        [Binding]
        public class BaseSteps
        {
            private BasePage basePage = new BasePage();
    
            [Given(@"(?:a DuckDuckGo|an internet) user is on the (?:base|search) page")]  
            public void GivenIAmOnTheBasePage() 
            { 
                basePage.NavigateBaseUrl();
            }
    
            [Then(@"they see the page title contains ""(.*)""")]
            public void ThenIseeThePageTitleContains(string expectedTitle)
            {
                var titleToValidate = basePage.GetTitle.Contains(expectedTitle);
                Assert.IsTrue(titleToValidate, " :: The actual page title is different");
                Console.WriteLine(" :: The actual page title is " + titleToValidate);
            }
    
            [Then(@"the page URL contains ""(.*)""")]
            public void ThenISeeThePageUrlContains(string expectedUrl)
            {
                var urlToValidate = basePage.GetUrl.Contains(expectedUrl);
                Assert.IsTrue(urlToValidate, " :: The actual page Url is different");
                Console.WriteLine(" :: The actual page URL is " + urlToValidate);
            }
    
            [Then(@"they see ""(.*)"" in the PageSource")]
            public void ThenISeeInThePageSource(string expectedText)
            {
                var pageSourceTextToValidate = basePage.GetPageSource.Contains(expectedText);
                Assert.IsTrue(pageSourceTextToValidate, " :: The expected string is not present in the page source");
                Console.WriteLine(" :: The page source does not contain " + expectedText);
            }
        }
    }

Validate Existence of Multiple Text in PageSource

Creating the SpecFlow Scenario

  1. Open up the ‘BaseScenarios.feature’ file and add the following test scenario…
    Scenario: 04. Validate existence of multiple texts in PageSource
        Given a DuckDuckGo user is on the base page
        Then they see
          | expectedText   |
          | DuckDuckGo     |
          | search engine  |
          | track you      |

Creating the Undefined Step Definition

  1. Next, create the undefined step definition for the Then step in BaseSteps class and add a Table parameter, like below…
    [Then(@"they see")]
    public void ThenISee(Table table)
    {
        throw new PendingStepException();
    }

Defining the Step Definition

  1. Open up the ‘BaseSteps.cs’ class file again, and define the step by adding the assertion for each item in the table…
    [Then(@"they see")]
    public void ThenISee(Table table)
    {
        foreach (var row in table.Rows) 
        { 
            var textToValidate = row["expectedText"]; 
    	Assert.IsTrue(basePage.GetPageSource.Contains(textToValidate), textToValidate + " is not in the PageSource!"); 
    	Console.WriteLine(":: The text " + textToValidate + " is in the PageSource "); 
        }
    }

    The whole thing should look like below now…

    using System;
    using NUnit.Framework;
    using ProductAutomation.Pages;
    using TechTalk.SpecFlow;
    
    namespace ProductAutomation.Steps.BaseSteps
    {
        [Binding]
        public class BaseSteps
        {
            private BasePage basePage = new BasePage();
    
            [Given(@"(?:a DuckDuckGo|an internet) user is on the (?:base|search) page")] 
            public void GivenIAmOnTheBasePage() 
            { 
                basePage.NavigateBaseUrl();
            }
    
            [Then(@"they see the page title contains ""(.*)""")]
            public void ThenIseeThePageTitleContains(string expectedTitle)
            {
                var titleToValidate = basePage.GetTitle.Contains(expectedTitle);
                Assert.IsTrue(titleToValidate, " :: The actual page title is different");
                Console.WriteLine(" :: The actual page title is " + titleToValidate);
            }
    
            [Then(@"the page URL contains ""(.*)""")]
            public void ThenISeeThePageUrlContains(string expectedUrl)
            {
                var urlToValidate = basePage.GetUrl.Contains(expectedUrl);
                Assert.IsTrue(urlToValidate, " :: The actual page Url is different");
                Console.WriteLine(" :: The actual page URL is " + urlToValidate);
            }
    
            [Then(@"they see ""(.*)"" in the PageSource")]
            public void ThenISeeInThePageSource(string expectedText)
            {
                var pageSourceTextToValidate = basePage.GetPageSource.Contains(expectedText);
                Assert.IsTrue(pageSourceTextToValidate, " :: The expected string is not present in the page source");
                Console.WriteLine(" :: The page source does not contain " + expectedText);
            }
    
            [Then(@"they see")]
            public void ThenISee(Table table)
            {
                foreach (var row in table.Rows) 
    	    { 
    		var textToValidate = row["expectedText"]; 
    		Assert.IsTrue(basePage.GetPageSource.Contains(textToValidate), textToValidate + " is not in the PageSource!"); 
    		Console.WriteLine(":: The text " + textToValidate + " is in the PageSource "); 
    	    }
            }
        }
    }

SpecFlow Background Step

  1. If you look at the four base scenarios in your ‘BaseScenarios.feature’ file, you will see that every scenario shares the step of ‘Given I navigate to the base URL’.  Because of this, we can clean up the Feature file a bit by declaring the ‘Given’ step once as a Background step, which will be applied at the beginning of every scenario in the Feature file (see https://github.com/cucumber/cucumber/wiki/Background for more information)…
    @Chrome
    Feature: BaseScenarios
    
    These scenarios can be used in any project
    
    Background: DuckDuckGo user is already on the correct page
     Given a DuckDuckGo user is on the base page
    
    Scenario: 01. Validate the title of a website
     Then they see the page title contains "DuckDuckGo"
    
    Scenario: 02. Validate the URL of a web page
     Then the page URL contains "https://start.duckduckgo.com"
    
    Scenario: 03. Validate the PageSource string on a web page
     Then they see "DuckDuckGo" in the PageSource
    
    Scenario: 04. Validate the PageSource contains multiple text
     Then they see
      | expectedText  |
      | DuckDuckGo    |
      | search engine |
      | track you     |

    We have now successfully added our BaseScenarios.  In the next part, we will actually add our first proper test of searching for something on Google and then clicking through on a search result 😀

Digiprove sealCopyright secured by Digiprove © 2018
Liked it? Take a second to support Thomas on Patreon!

Previous Article

Next Article

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.