Use the Selenium WebDriver

The UAT Automation Kit provides an API that lets you take advantage of Selenium WebDriver to interact with common elements in Infinity-based applications such as Blackbaud CRM. You can use Selenium's WebDriver and Wait pattern to drive browser interactions.

  • Complete the Get Started walkthrough. For each new project, you must:
    • Add the UAT Automation Kit NuGet packages.
    • Ensure that ChromeDriver is on your path.
    • Add target environment URLs to the App.config file.
  • unit test project with the UAT Automation Kit NuGet packages.
  • Access to a Blackbaud CRMinstance to test against.
  • Familiarity with the UAT Automation Kit Custom SpecFlow Plugin for Visual Studio.
  • Familiarity with creating feature files.
  • Familiarity with generating step classes bound to feature files.
  • Access to UAT Automation Kit Core API.

This tutorial guides you through the steps to create a custom interaction with the Selenium WebDriver and to use the WebDriver and Wait pattern to drive browser interactions. In this walkthrough, you will:

  • Create a behavior-driven development test with Gherkin to navigate between functional areas.
  • Create a step file to specify actions for the test.
  • Create a custom class that uses WebDriver to find an element, check a condition, and execute a step if the condition is met.
  • Provide an XPath within the custom class's method to parse HTML elements and find the desired element.
  • Build the test project and run the test.
  1. Create a Gherkin test and step method in your unit test project in Visual Studio.
    1. To create a feature test that requires navigation between functional areas, right-click the project in Solution Explorer, select Add, New item, and then select the SpecFlow Feature File template and click Add.
    2. Then update the behavior-driven development test to confirm that you can navigate from the Constituents functional area to the Revenue functional area.

      Unimplemented feature showTableOfContents

      Gherkin
      @DelvingDeeper
      Scenario: Log into BBCRM, load a functional area, and change functional area.
        Given I have logged into BBCRM and navigated to functional area "Constituents"
        When I navigate to functional area "Revenue"
        Then the panel header caption is "Revenue"
    3. To generate the failing step class methods, right-click within the feature file and select Generate Step Definitions, then click Generate, make sure the path points to your test project, and click Save.
    4. At the beginning of the step file, insert using Blackbaud.UAT.Core.Base, using Blackbaud.UAT.Core.Crm, and using Blackbaud.UAT.Base to import the Blackbaud CRM types defined by those namespaces. Then update the class to specify that it inherits from BaseSteps. For this tutorial, we also update the first two p0 parameters to functionalArea and the third p0 parameter to headerCaption.

      Failing step class methods

      C#
      using System;
      using System.Collections.Generic;
      using Blackbaud.UAT.Base;
      using Blackbaud.UAT.Core.Base;
      using Blackbaud.UAT.Core.Crm;
      using TechTalk.SpecFlow;
      
      namespace Delving_Deeper
      {
          [Binding]
          public class SampleTestsSteps : BaseSteps
          {
              [Given(@"I have logged into BBCRM and navigated to functional area ""(.*)""")]
              public void GivenIHaveLoggedIntoBbcrmAndNavigatedToFunctionalArea(string functionalArea)
              {
                  ScenarioContext.Current.Pending();
              }
      
              [When(@"I navigate to functional area ""(.*)""")]
              public void WhenINavigateToFunctionalArea(string functionalArea)
              {
                  ScenarioContext.Current.Pending();
              }
      
              [Then(@"the panel header caption is ""(.*)""")]
              public void ThenThePanelHeaderCaptionIs(string headerCaption)
              {
                  ScenarioContext.Current.Pending();
              }
          }
      }
    5. Update the first ScenarioContext.Current.Pending(); placeholder with an unimplemented class and method.

      Delete ScenarioContext.Current.Pending(); and replace it with BBCRMHomePage.Login(); MyCustomBBCrmHomePage.NavigateToFunctionalArea(functionalArea); to specify logging in to Blackbuad CRM and navigating to the Constituents functional area.

      Unimplemented class and method

      C#
      [Given(@"I have logged into BBCRM and navigated to functional area ""(.*)""")]
      public void GivenIHaveLoggedIntoBbcrmAndNavigatedToFunctionalArea(string functionalArea)
      {
          BBCRMHomePage.Login();
          CustomBBCrmHomePage.NavigateToFunctionalArea(functionalArea);
      }

      If you build the project at this point with the unimplemented class and method in place, the build should fail.

  2. To create a custom class that inherits BBCRMHomePage, right-click the project in Solution Explorer and select Add, New item. On the Add New Item screen, select the Visual C# Items category and the Class template, enter "CustomBBCrmHomePage.cs" for the file name, and click Add.
  3. At the beginning of the class file, insert using Blackbaud.UAT.Core.Crm to import the Blackbaud CRM types defined by that namespace, along with using OpenQA.Selenium and using OpenQA.Selenium.Support.UI. Next, specify that the MyCustomBBCrmHomePage class inherits from BBCRMHomePage. Then add the NavigateToFunctionalArea method to the class and specify that the method throws a NotImplementedException.

    Custom class and method

    C#
    using System;
    using Blackbaud.UAT.Core.Crm;
    using OpenQA.Selenium;
    using OpenQA.Selenium.Support.UI;
    
    namespace Delving_Deeper
    {
        public class CustomBBCrmHomePage : BBCRMHomePage
        {
            public static void NavigateToFunctionalArea(string caption)
            {
                throw new NotImplementedException();
            }
        }
    }

    If you attempt to build the project at this point with the exception specified for the method, the build should now succeed.

  4. Implement the custom method.
    1. Create a while loop that waits for "True" to be returned and starts over if "False" is returned. Specify the amount of time to expire before the loop throws a WebDriverTimeoutException, and specify the exception types to ignore in the loop. If exceptions of the specified types are thrown, the resulting action is the equivalent to "False" being returned at that moment.
    2. Loop

      C#
      {
          WebDriverWait navigateWaiter = new WebDriverWait(Driver, TimeSpan.FromSeconds(TimeoutSecs));
          navigateWaiter.IgnoreExceptionTypes(typeof(InvalidOperationException));
          navigateWaiter.Until(driver =>
          {
              throw new NotImplementedException();
          });
      }
    3. Replace NotImplementedException. Use the WebDriver (referenced as driver in the lambda method) to find an element in Blackbaud CRM and check a condition on the element. In this example, check whether the element is Displayed. If the element is found but is not visible yet, return "False" because the desired condition is not met. This causes the loop to start over, and the WebDriver attempts to get a refreshed version of the element. When the element is visible, the WebDriver can send a Click action on the element and return "True" to exit the loop so that the next step method call can begin.
    4. Example of using WebDriver to find an element, check a condition, and execute a step if the condition is met

      C#
      WebDriverWait navigateWaiter = new WebDriverWait(Driver, TimeSpan.FromSeconds(TimeoutSecs));
      navigateWaiter.IgnoreExceptionTypes(typeof(InvalidOperationException));
      navigateWaiter.Until(driver =>
      {
          IWebElement functionalAreaElement = driver.FindElement(null);
          if (!functionalAreaElement.Displayed) return false;
          functionalAreaElement.Click();
          return true;
      });
    5. To find elements the browser application, the WebDriver has an API with different selection methods. The UAT Automation Kit relies on XPaths to parse HTML elements and find desired elements. To learn about XPath patterns and best practices for Blackbaud CRM, see XPath Guidelines.
    6. For now, update the code driver .FindElement line with the following XPath information:

      WebDriver FindElement using an XPath for the selector

      C#
      IWebElement functionalAreaElement = driver.FindElement(By.XPath(String.Format("//button[text()='{0}']", caption)));
    7. Return to the step file and update the remaining ScenarioContext.Current.Pending(); placeholders to implement the remaining step methods.
    8. C#
      [Given(@"I have logged into BBCRM and navigated to functional area ""(.*)""")]
      public void GivenIHaveLoggedIntoBbcrmAndNavigatedToFunctionalArea(string functionalArea)
      {
          BBCRMHomePage.Login();
          CustomBBCrmHomePage.NavigateToFunctionalArea(functionalArea);
      }
      
      [When(@"I navigate to functional area ""(.*)""")]
      public void WhenINavigateToFunctionalArea(string functionalArea)
      {
          CustomBBCrmHomePage.NavigateToFunctionalArea(functionalArea);
      }
      
      [Then(@"the panel header caption is ""(.*)""")]
      public void ThenThePanelHeaderCaptionIs(string headerCaption)
      {
          if (!BaseComponent.Exists(Panel.getXPanelHeaderByText(headerCaption)))
              FailTest(String.Format("'{0}' was not in the header caption.", headerCaption));
      }
    9. Build the project and run your test.
      1. Right-click the project in Solution Explorer and select Build.
      2. In Test Explorer (Test, Windows, Test Explorer), right-click the test and select Run Selected Tests.

See Also

XPath Guidelines