Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make my Selenium tests less brittle?

Tags:

We use Selenium to test the UI layer of our ASP.NET application. Many of the test cases test longer flows that span several pages.

I've found that the tests are very brittle, broken not just by code changes that actually change the pages but also by innocuous refactorings such as renaming a control (since I need to pass the control's clientID to Selenium's Click method, etc) or replacing a gridview with a repeater. As a result I find myself "wasting" time updating string values in my test cases in order to fix broken tests.

Is there a way to write more maintainable Selenium tests? Or a better web UI testing tool?

Edited to add: Generally the first draft is created by recording a test in the IDE. (This first step may be performed by QA staff.) Then I refactor the generated C# code (extract constants, extract methods for repeated code, maybe repeat the test case with different data, etc). But the general flow of code for each test case remains reasonably close to the originally generated code.

like image 975
Helen Toomik Avatar asked Jan 21 '09 20:01

Helen Toomik


People also ask

Why Selenium tests are flaky?

In Selenium WebDriver tests, flakiness comes from a couple of tests: Lack of synchronization: The architecture of web apps contain multiple layers, The way these layers interact influences web app performance, including network speed, HTTP handling, source rendering, and computer processing resources.

Why do Selenium tests fail?

In every software testing process, there are inevitably times when test cases fail. Test cases usually fail due to server and network issues, an unresponsive application or validation failure, or even due to scripting issues.


1 Answers

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.

like image 160
MariangeMarcano Avatar answered Oct 02 '22 13:10

MariangeMarcano