A Selenium Testing Framework

A Selenium Testing Framework

Background

To bring you up to speed with the content of this article, read and perform the steps described in High-level testing concepts and Base classes by our guest Jason Smiley, from Gerson Lehrman Group.

This is what you should have:

  • SeleniumTestBase.cs, which handles creating of the test browser, reading from the DB, and handles changing of active windows or frames.
  • SeleniumActionBase.cs, which can update the DB and also can handle changing of the active windows or frames.
  • SeleniumPageBase.cs, which checks the starting number of the XPath browser index (IE uses 0 while all other browsers use 1).
  • SeleniumPageElement.cs, which handles waiting for and interacting with elements on the page.

The above classes should be in an external project from your testing project. Let’s refer to this set of classes in compiled form as the OurSeleniumFramework.dll. This .dll file should be referenced in your test project so test, action, and page classes can extend the base classes you have already.
When creating a test project to test a website, it is a good idea to create a project base test that will create all of the action and page classes, as well as having a project base action class that will create all page classes. Page classes will create SeleniumPageElements, which will be used by action and test classes.

Example Test Project

To demonstrate this structure, let’s examine how base classes are created and how this can be used to test a login page which has a username field, password field, submit button, login confirmation message that appears after successful login, and error message that appears after unsuccessful attempts. Let’s also look at what each class required to perform a basic login test will look like. See below for all the example test project files. The files will be:

  • ProjectTestBase.cs: Handles NUnit setup, teardown, and page and action initialization functionality for tests.
  • ProjectActionBase.cs: Handles page initialization functionality for actions.
  • LoginTests.cs: Implements the tests for the login page.
  • LoginActions.cs: Implements the steps required to do Login testing.
  • LoginPage.cs: Handles the initialization for PageElement objects which will be used by actions and tests.

Example ProjectTestBase.cs

public ProjectTestBase : SeleniumTestBase
{
#region Action declarations
protected LoginActions _LoginActions;
#endregion

#region Page declarations
protected LoginPage _LoginPage;
#endregion

public ProjectTestBase (IWebDriver webDriver)
: base(webDriver) { }

public void CreateActions(IWebDriver webDriver)
{
_LoginActions = new LoginActions(webDriver);
}

public void CreatePages(IWebDriver webDriver)
{
_LoginPage= new LoginPage(webDriver);
}

[SetupTestFixture]
public virtual void setupTestFixture()
{
//Function is virtual so child test classes can have additional functionality.

//For this example project, nothing needs to be done on this level.
}

[Setup]
public virtual void setup()
{
//Function is virtual so child test classes can have additional functionality.
myDriver = StartBrowser(“firefox”);
CreateActions(myDriver);
CreatePages(myDriver);
LaunchUrl(“http://myhomepage.com”);
}

[Teardown]
public virtual void tearDown()
{
//Function is virtual so child test classes can have additional functionality.
myDriver.Quit();
}

[TeardownTestFixture]
public virtual void setupTestFixture()
{
//Function is virtual so child test classes can have additional functionality.

//For this example project, nothing needs to be done on this level.
}
}

Example ProjectActionBase.cs

public ProjectActionBase : SeleniumActionBase
{
#region Page declarations
protected LoginPage _LoginPage;
#endregion

public ProjectActionBase(IWebDriver webDriver)
: base(webDriver);
{
_LoginPage = new LoginPage(webDriver);
}
}

Note that in this class, you can put common actions such as successful login so all action classes will be able to perform
this step. This is just a nice-to-have, though, and not a must.

Example LoginTests.cs

public LoginTests : ProjectTestBase
{

[Test]
public void successfulLoginTest()
{
_LoginActions.LoginAttempt(“Jason”, “Smiley”, true);
Assert.That(_LoginPage.ConfirmationMessage.Text, Is.EqualTo(“You are now logged in”).IgnoreCase,
“You should have logged in successfuly but didn’t”);
}

[Test]
public void invalidLoginTest()
{
_LoginActions.LoginAttempt(“fake”, “fake”, false);
Assert.That(_LoginPage.ErrorMessage.Text, Is.EqualTo(“Invalid login”).IgnoreCase,
“You should have gotten an error message but didn’t”)
}
}

Example LoginActions.cs

public LoginActions : ProjectActionBase
{
public void LoginAttempt(string username, string password, isValid = null)
{
LoginPage.UsernameTextField.Clear();
LoginPage.UsernameTextField.SendKeys(username);
LoginPage.PasswordTextField.Clear();
LoginPage.PasswordTextField.SendKeys(password);
LoginPage.SubmitBtn.Click();

if(isValid != null && isValid == true)
{
LoginPage.ConfirmationMessage.
WaitUntilVisibleAndPresent(“confirmation is not appearing after 5 seconds”);
}

if(isValid != null && isValid == false)
{
LoginPage.ErrorMessage.WaitUntilVisibleAndPresent(“error message is not
appearing after 5 seconds”);
}
}
}

Example LoginPage.cs

public LoginPage : SeleniumPageBase
{
#region PageElement declarations
public PageElement UsernameTextField;
public PageElement PasswordTextField;
public PageElement ConfirmationMessage;
public PageElement ErrorMessage;
#endregion

public LoginPage(IWebDriver webDriver)
: base(webDriver)
{
UsernameTextField = new PageElement(By.Id(“username”), webDriver);
PasswordTextField= new PageElement(By.Id(“password”), webDriver);
ConfirmationMessage= new PageElement(By.Id(“success”), webDriver);
ErrorMessage= new PageElement(By.Id(“error”), webDriver);
}
}