![]() | Using the Selenium WebDriver |
In this walkthrough you'll learn how to use Selenium's WebDriver and Wait pattern to drive browser interactions.
A unit test project with the UAT SDK (Project Blue) NuGet package installed.
An Enterprise CRM application is accessible and tests can be run against this application.
Familiarity with:
Using the UAT SDK (Project Blue) Custom SpecFlow Plugin for Visual Studio.
Creating new feature files.
Generating step classes bound to feature files.
Accessing the UAT SDK (Blueshirt) Core API.
Create the Gherkin test and Step method.
using System; using Blackbaud.UAT.Base; using Blackbaud.UAT.Core.Base; using TechTalk.SpecFlow; using System.Collections.Generic; 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(); } } }
[Given(@"I have logged into BBCRM and navigated to functional area ""(.*)""")] public void GivenIHaveLoggedIntoBbcrmAndNavigatedToFunctionalArea(string functionalArea) { BBCRMHomePage.Logon(); MyCustomBBCrmHomePage.NavigateToFunctionalArea(functionalArea); }
Create custom class inheriting BBCRMHomePage
using System; using Blackbaud.UAT.Base; using Blackbaud.UAT.Core.Base; using TechTalk.SpecFlow; using System.Collections.Generic; namespace Delving_Deeper { public class MyCustomBBCrmHomePage : BBCRMHomePage { public static void NavigateToFunctionalArea(string caption) { throw new NotImplementedException(); } } }
Implement the custom method. The common pattern employed in the UAT SDK is to wait until a certain condition has been met before proceeding with the next action. The Selenium Webdriver is what allows us to interact with the browser in order to determine whether or not our desired condition has been met.
public static void NavigateToFunctionalArea(string caption) { WebDriverWait navigateWaiter = new WebDriverWait(Driver, TimeSpan.FromSeconds(TimeoutSecs)); navigateWaiter.IgnoreExceptionTypes(typeof(InvalidOperationException)); navigateWaiter.Until(driver => { throw new NotImplementedException(); }); }
In the above code, we have essentially created a while loop that waits for 'True' to be returned before exiting the loop. Any time 'False' is returned, the loop starts over. We can specify an amount of time that should expire in the loop until a WebDriverTimeoutException will be thrown. Finally we can specify Exception types to ignore in the loop. If exceptions of the specified types are thrown, the resulting action is the equivalent of 'False' being returned at that moment.
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; });
Above we used the WebDriver (referenced as 'driver' in our lambda method) to find an element on our application and checked a condition on the element. In this instance, we want to check if the element is 'Displayed' before proceeding. If we found the element but it is not visible yet, we can immediately return false because our desired condition has not been met. This will cause the loop to start over, and the web driver will attempt to get a refreshed version of the element. If the element is visible, then we use the WebDriver to send a 'Click' action on it and return true to exit the loop so that the next step method call can begin.
An immediate question might be "How did the WebDriver find the element we wanted?" The WebDriver has an API with different selection methods in order to find elements in your browser application. The UAT SDK (Project Blue) relies on XPaths to parse the HTML elements and find the desired element. More details about XPaths and best practices can be found in the reference links at the end of this article. Suggested Enterprise CRM XPath patterns and examples will be discussed in a later walkthrough. For the moment, update the code driver.FindElement line to the following:
IWebElement functionalAreaElement = driver.FindElement(By.XPath(String.Format("//button[text()='{0}']", caption)));
Finish Implementing Step Methods
[Given(@"I have logged into BBCRM and navigated to functional area ""(.*)""")] public void GivenIHaveLoggedIntoBbcrmAndNavigatedToFunctionalArea(string functionalArea) { BBCRMHomePage.Logon(); MyCustomBBCrmHomePage.NavigateToFunctionalArea(functionalArea); } [When(@"I navigate to functional area ""(.*)""")] public void WhenINavigateToFunctionalArea(string functionalArea) { MyCustomBBCrmHomePage.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)); }
![]() |
---|
The UAT SDK (Project Blue) API provides lots browser interactions that encapsulate different WebDriver logic. Before creating new WebDriver logic, first look into the API to see what functionality is already provided. Hopefully the desired WebDriver logic and XPath constructor are already available from the API. |