Skip to content

ipjohnson/SeleniumFixture

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SeleniumFixture

Is a companion library for Selenium C# that provides functionality to easily populate forms, navigate pages and construct PageObjects.

var driver = new FirefoxDriver();

var fixture = new Fixture(driver);

fixture.Navigate.To("http://ipjohnson.github.io/SeleniumFixture/TestSite/InputForm.html");

fixture.AutoFill("//form");

Click & DoubleClick

Provides short hand for clicking and double clicking elements

// click button with id someButton
fixture.Click("#someButton");

// click button of type submit
fixture.Click("button[type='submit']");

// DoubleClick any button that has the html class 'some-class'
fixture.DoubleClick("button.some-class", ClickMode.Any);

Fill

Fill allows you to easily populate form elements with a given set of values. Currently textboxs, radiobutton, checkbox, select and textarea are supported.

// Navigate to page and fill out form
fixture.Navigate.To("http://ipjohnson.github.io/SeleniumFixture/TestSite/InputForm.html");

fixture.Fill("//form")
       .With(new 
              { 
                FirstName = "Sterling", 
                LastName = "Archer",
                Active = true,
                Gender = "Male"
              })
       .ThenSubmit();
       
// fill all elements with the html class some-class with the value 1111       
fixture.Fill(".some-class").With(1111);

AutoFill

Sometimes its useful to populate a form with random data. The AutoFill method can be used to fill a html input elements.

// AutoFill form element
fixture.AutoFill("//form");

// AutoFill form but use Bob to fill the FirstName field
fixture.AutoFill("//form", seedWith: new { FirstName = "Bob"});

// Find an element with the id #someDiv and populate all child input and select elements
fixture.AutoFill("#someDiv");

Wait

It's useful to wait for certain things to happen on page, the Wait API provides a number of helpful wait methods for things like ajax or form elements to exists.

// wait for ajax calls to finish
fixture.Wait.ForAjax();

// wait for #someElement to be present on the page
fixture.Wait.ForElement("#someElement");

// long hand for waiting for element 20 seconds
fixture.Wait.Until(i => i.CheckForElement("#someElement"), 20);

PageObject Pattern

The PageObject pattern is very useful and SeleniumFixture fully supports using PageObject classes to help package logic. SimpleFixture is used to create instances of PageObjects allowing for very complex object. For example, injecting constructor parameters , properties (using ImportAttribute), and etc.

var driver = new FirefoxDriver();

var fixture = new Fixture(driver, "http://ipjohnson.github.io/SeleniumFixture/TestSite/");

var formPage = fixture.Navigate.To<FormPage>("InputForm.html");

formPage.FillOutForm();

public class FormPage
{
  public void FillOutForm()
  {
    I.Fill("//form").With(new { FirstName = "Sterling", LastName = "Archer" });
  }

  protected IActionProvider I { get; private set; }
}

IActionProvider Property

The IActionProvider allows a page object to import the functionality of the Fixture into a local property. When PageObjects are constructed any IActionProvider property with a setter will be Populated with an instance of IActionProvider. Usually this property is named I

I.Fill("//form").With(new { FirstName = "Sterling" });

I.Click("#submitButton").Wait.ForAjax().Then.Yields<HomePage>();

Validate

PageObjects can validate themselves upon creation one of two ways. You can either have a method name "Validate" or a property called "Validate" that is an Action. Either choice will be called once the page object has been created.

public class HomePage
{
    public HomePage()
    {
      Validate = () => I.Get.PageTitle.Should().Be("Home");
    }
    
    protected Action Validate { get; private set; } 
    
    protected IActionProvider I { get; private set; }
}

Yields

Yields is how you can create new PageObject instances. It takes the type of page as the generic parameter and will instantiate a new instance of T. Note: your page types do not have to inherit from any particular type, you could use structs if you felt so inclined.

// click the submit button and yield a new HomePage object 
I.Click("#submitButton").Yields<HomePage>();

// click the link Some Text then yield a new OtherPage object
// and pass the value 5 into the constructor parameter someParam
I.Click(By.LinkText("Some Text")).Yields<OtherPage>(constraints: new { someParam = 5 });
 
public class OtherPage
{
  public OtherPage(int someParam)
  {
    Validate = () => I.Get.PageTitle.Should().EndWith(someParam.ToString());
  }
  
  private Action Validate { get; set; }
  
  private IActionProvider I { get; set; }
}

Note: Should() is part of Fluent Assertions.

xUnit support

xUnit 2.0 is a very extensible testing framework that SeleniumFixture.xUnit provides support for out of the box. Currently there are a set of attributes that make setup and tear down of IWebDrivers and Fixture easier. You can customize initialization and finalization of WebDriver & Fixtures. It also supports creation of PageObjects as well as xUnit DataAttributes

    public class AutoFillTests
    {
        /// <summary>
        /// Test navigates to the input form and auto fills the form.
        /// Runs against Chrome, Firefox and Internet Explorer
        /// </summary>
        /// <param name="fixture">populated fixture</param>
        [SeleniumTheory]
        [ChromeDriver]
        [FirefoxDriver]
        public void Fixture_FillForm_PopulatesCorrectly(Fixture fixture)
        {
            fixture.Navigate.To("http://ipjohnson.github.io/SeleniumFixture/TestSite/InputForm.html");

            fixture.AutoFill("//form");

            fixture.Get.Value.From("#FirstName").All(char.IsLetter).Should().BeTrue();

            fixture.Get.Value.From("#LastName").All(char.IsLetter).Should().BeTrue();
        }
        
        /// <summary>
        /// Test case that uses attribute to navigate to the input form
        /// then autofills the page then tests that the first and last names are all letters
        /// </summary>
        /// <param name="inputPage">Page object returned from InitializeToInputForm</param>
        [SeleniumTheory]
        [ChromeDriver]
        [FirefoxDriver]
        [InitializeToInputForm]
        public void Fixture_Initialize_ToInputForm(InputPage inputPage)
        {
            inputPage.AutoFill();

            inputPage.Get.Value.From("#FirstName").All(char.IsLetter).Should().BeTrue();

            inputPage.Get.Value.From("#LastName").All(char.IsLetter).Should().BeTrue();
        }
        
        /// <summary>
        /// Test that page object is created correctly and that InlineData is correctly populated into variables
        /// </summary>
        /// <param name="inputPage">page object from initialization attribute</param>
        /// <param name="helloString">Hello string</param>
        /// <param name="intValue">5 value</param>
        [SeleniumTheory]
        [ChromeDriver]
        [FirefoxDriver]
        [InlineData("Hello",5)]
        [InitializeToInputForm]
        public void Fixture_InlineData_CorrectDataPopulated(InputPage inputPage, string helloString, int intValue)
        {
            helloString.Should().Be("Hello");

            intValue.Should().Be(5);

            inputPage.AutoFill();

            inputPage.Get.Value.From("#FirstName").All(char.IsLetter).Should().BeTrue();

            inputPage.Get.Value.From("#LastName").All(char.IsLetter).Should().BeTrue();
        }
    }

Note: because each driver has slightly different behavior your tests and PageObjects need to be a little bit more robust.

About

Selenium testing fixture for C#

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages