How can I make my Selenium tests less brittle? How can I make my Selenium tests less brittle? asp.net asp.net

How can I make my Selenium tests less brittle?


I've found PageObject pattern very helpful.

http://code.google.com/p/webdriver/wiki/PageObjects

more info: - What's the Point of Selenium?- Selenium Critique

maybe a good way to start is to incrementally refactor your test cases.

I use the same scenario you have selenium + c#

Here is how my code looks like:

A test method will look like somethink like this

    [TestMethod]    public void RegisterSpecialist(UserInfo usrInfo, CompanyInfo companyInfo)    {        var RegistrationPage = new PublicRegistrationPage(selenium)              .FillUserInfo(usrInfo)              .ContinueSecondStep();        RegistrationPage.FillCompanyInfo(companyInfo).ContinueLastStep();        RegistrationPage.FillSecurityInformation(usrInfo).ContinueFinishLastStep();        Assert.IsTrue(RegistrationPage.VerifySpecialistRegistrationMessagePayPal());        selenium.WaitForPageToLoad(Resources.GlobalResources.TimeOut);        paypal.LoginSandboxPage(usrInfo.sandboxaccount, usrInfo.sandboxpwd);        Assert.IsTrue(paypal.VerifyAmount(usrInfo));        paypal.SubmitPayment();        RegistrationPage.GetSpecialistInformation(usrInfo);        var bphome = new BPHomePage(selenium, string.Format(Resources.GlobalResources.LoginBPHomePage, usrInfo.AccountName, usrInfo.Password));        Assert.IsTrue(bphome.VerifyPageWasLoaded(usrInfo));        Assert.IsTrue(bphome.VerifySpecialistProfile());        bphome.Logout();    }

A page Object will be something like this

public class PublicRegistrationPage{    public ISelenium selenium { get; set; }    #region Constructors    public PublicRegistrationPage(ISelenium sel)    {        selenium = sel;        selenium.Open(Resources.GlobalResources.PublicRegisterURL);    }    #endregion    #region Methods    public PublicRegistrationPage FillUserInfo(UserInfo usr)    {        selenium.Type("ctl00_cphComponent_ctlContent_wizRegister_tUserFirstName", usr.FirstName);        selenium.Type("ctl00_cphComponent_ctlContent_wizRegister_tUserLastName", usr.LastName);        selenium.Select("ctl00_cphComponent_ctlContent_wizRegister_ddlUserCountry", string.Format("label={0}",usr.Country ));        selenium.WaitForPageToLoad(Resources.GlobalResources.TimeOut);        selenium.Type("ctl00_cphComponent_ctlContent_wizRegister_tUserEmail", usr.Email );        selenium.Type("ctl00_cphComponent_ctlContent_wizRegister_tUserDirectTel", usr.DirectTel);        selenium.Type("ctl00_cphComponent_ctlContent_wizRegister_tUserMobile", usr.Mobile);        return this;    }

}

Hope this helps.


How are you creating your Selenium tests, by recording them and playing them back? What we have done is build an object model around pages so that you call a method like "clickSubmit()" rather than clicking on an id (with a naming convention for these ids), which allows selenium tests to survive many changes.


You may or may not be able to write tests that are resilient to refactoring. Here's how to make the refactoring less painful: Continuous integration is essential.

Run them every day or every build. The sooner it's fixed, the easier.

Ensure devs can run the tests themselves. Again, the sooner it's seen and fixed, the easier.

Keep selenium tests few. They should focus on critical path / pri 1 test scenarios. Deep testing should be done at unit test level (or jsunit tests). Integration tests are always expensive and less valuable.