Selenium Tutorial - Part 2
Selenium WebDriver with C# and NUnit

Prerequisites

We will be creating automated Web Tests using the WebDriver in C# Visual Studio. The following must exist in your system before creating WebDriver tests.

Selenium WebDriver Download

(Visual Studio) You can do this easily by going into the NUGET packages and installing Selenium WebDriver and Web Driver Support (Optional: For more advanced features not covered here).
Otherwise, You can download it at their website but you must add a reference.

WebBrowser WebDriver Download

Download the one that corresponds to your OS. Other Browser Drivers exist in the Selenium Homepage and projects created by others.

After downloading the driver, you must add it into your project. (In VS, it is Via Add Reference)

Testing framework

The export function provides with it the markup used in NUnit tests, though WebDriver tests can be executed in any testing framework - NUnit or not - as WebDriver is independent of the test environment and language.

Test Adapter

To run tests in VS, we must download the proper adapter from Extensions. You can also run selenium tests without the adapter and using command-line: @NUnit/run "./path/to/TestProjectNUnitSelenium.dll"

WebDriver API

This is the exhaustive list of commands available in Selenium WebDriver(OpenQA.Selenium) in C#. You can easily find this using Intellisense on Visual studio. References will also be listed at the bottom.

  //Navigation Commands, similar to buttons on the top of any 
  driver.Navigate().Forward();
  driver.Navigate().Back();
  driver.Navigate().Refresh();
  driver.Navigate().GoToUrl(baseURL + "/bootstrap-cheatsheet/");

  //Locators
  driver.FindElement(By.Id("Id"));
  driver.FindElement(By.ClassName("ClassName")).Click();
  driver.FindElement(By.PartialLinkText("close-showcase"));
  driver.FindElement(By.LinkText("close"));
  driver.FindElements(By.TagName("div"));
  driver.FindElement(By.XPath(".//*[@id='item-checkbox']"));
  //Works like XPath
  driver.FindElement(By.CssSelector("item-checkbox[href=\"#checkbox\"] > span"));

  //FindElement() Returns IWebElement
  driver.FindElement(By.Id("item-input-group")).Click();
  driver.FindElement(By.XPath(".//*[@id='showbox-example']/div/input")).SendKeys("testbot");
  driver.FindElement(By.XPath(".//*[@id='showbox-example']/div/input")).Clear();
  driver.FindElement(By.XPath(".//*[@id='showbox-example']/form/button")).Submit();
  //FindElements() Returns List<IWebElement>
  System.Collections.ObjectModel.ReadOnlyCollection<IWebElement> names = driver.FindElements(By.ClassName("UserName"));

  //Returns Boolean
  bool status;
  status = driver.FindElement(By.Id("UserName")).Displayed;
  status = driver.FindElement(By.Id("UserName")).Enabled;
  status = driver.FindElement(By.Id("Sex-Male")).Selected;
  //Returns tagname: div, input, etc.
  String tagName = driver.FindElement(By.Id("SubmitButton")).TagName;

  //Handling dropdowns (Multiple Select)
  SelectElement select = new SelectElement(driver.FindElement(By.Id("yy_date_8")));
  select.SelectByText("dropdown-item");
  select.SelectByIndex(1);
  select.SelectByValue("dropdown-value");

  //Deselect 
  select.DeselectByText("");
  select.DeselectAll();
  select.DeselectByValue("");
  var listOptions = select.Options;
  var boolean = select.IsMultiple;
  var listSOptions = select.AllSelectedOptions;
  var selectedOption = select.SelectedOption;

Creating tests from Selenium IDE Export

We will continue where we left off from Part 1, which is obtained from 2TestCaseSelenium.html By File -> Export Test Case As -> C#/NUnit in the Selenium IDE.

This is what the generated file should look like:

using System;
using System.Text;
using System.Collections;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome; //imports for drivers
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.Support.UI;

namespace SeleniumTests
{
  [TestFixture]
  public class ExportTestCase
  {
      private IWebDriver driver;
      private StringBuilder verificationErrors;
      private string baseURL;
      private bool acceptNextAlert = true;

      [SetUp]
      public void SetupTest()
      //Setup Driver, runs before EVERY TEST METHOD (as opposed to [SetUpTextFixture])

      [TearDown]
      public void TeardownTest()
      //Close Driver, runs after EVERY TEST METHOD.

      [Test]
      public void TheExportTestCaseTest()
      {
          driver.Navigate().GoToUrl(baseURL + "/");
          driver.FindElement(By.LinkText("Download")).Click();

          ...

          //An Assert
          Assert.AreEqual("Google Custom Search", driver.Title);

          //A Verify
          try
          {
              Assert.AreEqual("server", driver.FindElement(By.Id("gsc-i-id1")).GetAttribute("value"));
          }
          catch (AssertionException e)
          {
              verificationErrors.Append(e.Message);
          }
      }

      //Extension methods
      private bool IsElementPresent(By by)
      private bool IsAlertPresent()
      private string CloseAlertAndGetItsText()
    }
}

Since this is NUnit, The [Attribute] specifies commands to execute at the Test Fixture start up and exit. The function under [Test] is the method that will be executing your Selenium commands. We will go through all of these and more commands next.

The rest of the functions are helper or otherwise called extension methods. Extension methods wrap existing IWebDriver concrete methods with your own code for tailoring and at programmer’s convinience

Unsupported asserts

Selenium IDE comes with a number of \asserts in its plugin. However, export to C# / WebDriver results in some unsupported Asserts and Verifies. Here is a list of unsupported ones (at the time of this blog)

  //Unsupported:

  // ERROR: Caught exception [ERROR: Unsupported command [getAllButtons |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getAllFields |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getAllLinks |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getAllWindowIds |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getAllWindowNames |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getAllWindowTitles |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getAttributeFromAllWindows | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getCookie |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getCookieByName | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [isCookiePresent | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [isCookiePresent | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getCursorPosition | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [isEditable | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getElementHeight | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getElementIndex | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getElementPositionLeft | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getElementPositionTop | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getEval | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getExpression | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getHtmlSource |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getMouseSpeed |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getAllButtons |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getAllFields |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getAllLinks |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getAllWindowIds |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getAllWindowNames |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getAllWindowTitles |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getAttributeFromAllWindows | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getCookie |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getMouseSpeed |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getPrompt |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [isOrdered | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getSelectOptions | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getSelectedId | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getSelectedIds | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getSelectedIndex | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getSelectedIndexes | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getSelectedLabel | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getSelectedValue | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getSelectedValues | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [isSomethingSelected | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getSpeed |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getTable | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [isOrdered | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getPrompt |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [isPromptPresent |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [isPromptPresent |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getSelectOptions | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getSelectedId | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getSelectedIndex | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getSelectedIds | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getSelectedIndexes | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getSelectedLabel | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getSelectedLabels | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getSelectedValue | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getSelectedValues | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [isSomethingSelected | element | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getSpeed |  | ]]
  // ERROR: Caught exception [ERROR: Unsupported command [getTable | element | ]]

Unsupported IDE actions can still be replicated using the API presented above. Similar notion applies to verifies, as cerify is implemented with asserts and try-catch.

Coding style

Currently, a driver is created at the start of each test method. It is possible to wrap drivers in a using statment using(IWebDriver driver = new FirefoxDriver()){} and have that in each test method, which imitates what we currently have. The modern argument against it is that it is repeated code. Plus if you would like to test multiple drivers, we can have a List and use loop within the method.

The Teardown executes after each test method. Though, it may be required to add extra code such that exceptions will be caught and call driver.quit less there will be a memory leak.

Example Test Method

[Test]
public void TheExportTestCaseTest()
{
  driver.Manage().Timeouts().SetPageLoadTimeout(TimeSpan.FromSeconds(250));
  driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(250));
  driver.Navigate().GoToUrl(baseURL + "/bootstrap-cheatsheet/");
  //Include some asserts

  driver.FindElement(By.Id("item-input-group")).Click();
  IWebElement input = driver.FindElement(By.XPath(".//*[@id='showbox-example']/div/input"));
  input.SendKeys("testbot");
  input.Clear();

  //Submit
  driver.FindElement(By.XPath(".//*[@id='close-showcase']/i")).Click();
  driver.FindElement(By.Id("item-form")).Click();
  driver.FindElement(By.XPath(".//*[@id='showbox-example']/form/button")).Submit();
}

Afterword

Topics not covered here can be found at the references below.

References

Selenium - ToolsQA
Selenium IDE Documentation
SeleniumHQ




Last updated: June 23th, 2016