【问题标题】:How can I make my Selenium tests less brittle?如何使我的 Selenium 测试不那么脆弱?
【发布时间】:2010-10-02 18:46:25
【问题描述】:

我们使用 Selenium 来测试 ASP.NET 应用程序的 UI 层。许多测试用例测试跨越多个页面的较长流程。

我发现测试非常脆弱,不仅会被实际更改页面的代码更改破坏,而且还会被重命名控件等无害的重构破坏(因为我需要将控件的 clientID 传递给 Selenium 的 Click 方法等) 或用中继器替换网格视图。结果,我发现自己在“浪费”时间更新测试用例中的字符串值以修复损坏的测试。

有没有办法编写更易维护的 Selenium 测试?还是更好的 Web UI 测试工具?

编辑添加: 通常,第一稿是通过在 IDE 中记录测试来创建的。 (这第一步可能由 QA 人员执行。)然后我重构生成的 C# 代码(提取常量、提取重复代码的方法、可能用不同的数据重复测试用例等)。但是每个测试用例的一般代码流仍然与最初生成的代码相当接近。

【问题讨论】:

标签: asp.net testing selenium


【解决方案1】:

我发现 PageObject 模式非常有用。

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

更多信息: - What's the Point of Selenium? - Selenium Critique

也许一个好的开始方法是逐步重构您的测试用例。

我使用与 selenium + c# 相同的场景

我的代码如下所示:

测试方法看起来像这样

    [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();
    }

页面对象会是这样的

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;
    }

}

希望这会有所帮助。

【讨论】:

  • 感谢您提供全面的示例!在愤世嫉俗者的回答的提示下,并受到 Google wiki 页面的启发,我已经重构了我的测试代码并最终得到了非常相似的东西。
  • 连接 XPath 和 ID 会导致不稳定
【解决方案2】:

您如何通过录制和回放来创建您的 Selenium 测试?我们所做的是围绕页面构建一个对象模型,这样您就可以调用诸如“clickSubmit()”之类的方法,而不是单击一个 id(这些 id 有一个命名约定),这使得 selenium 测试能够在许多变化中存活。

【讨论】:

    【解决方案3】:

    您可能会也可能不会编写对重构具有弹性的测试。以下是减少重构痛苦的方法:持续集成至关重要。

    每天或每次构建运行它们。越早修复越容易。

    确保开发人员可以自己运行测试。同样,越早看到并修复它,就越容易。

    尽量少做硒测试。他们应该关注关键路径/pri 1 测试场景。深度测试应该在单元测试级别(或 jsunit 测试)进行。集成测试总是很昂贵且价值较低。

    【讨论】:

      【解决方案4】:

      在端到端测试中使用任何低级概念(如 XPath、CSS 选择器或 ID)是不稳定测试的秘诀。 我建议使用testRigor 来生成在您运行/更改/改进应用程序时不会中断的测试。 类似于上面的页面对象的代码如下所示:

          enter "Peter" into "First Name"
          enter "Pen" into "Last Name"
          enter "US" into "Country" below "User Data"
          enter stored value "email" into "Email"
          enter stored value "password" into "Password"
          enter "415-123-4567" into "Direct Telephone"
          enter "415-123-4568" into "Mobile Number"
          click "Submit"
      

      testRigor 会将看起来像标签的文本与输入相关联,这样一旦从最终用户的角度来看,您的页面看起来相同,那么 testRigor 脚本就会变成绿色。这是doc

      免责声明:我是 testRigor 的联合创始人。我共同创立了它,因为我们自己也有这些确切的问题。

      希望这会有所帮助。

      【讨论】:

      • 这看起来很棒,是否可以识别没有文字的图标?
      • 是的,testRigor 对图像进行分类并分配标签,您也可以使用自己的
      【解决方案5】:

      在测试自动化方面没有无害的变化;)

      我们将SAFS framework 与 Rational Robot (RRAFS) 结合使用,以最大限度地减少对自动化脚本的影响。仍然需要维护应用程序映射,但脚本在大多数情况下保持稳定。 SAFS 框架听起来与 cynicalman 提到的方法非常相似,但已经打包了您将在脚本中使用的通用方法。

      SAFS 网站说部分支持 Selenium,所以这可能对你有用。

      【讨论】:

        【解决方案6】:

        我发现在 Selenuium-RC 中使用 XPath 表达式可以大大提高测试的稳健性。

        我以类似的方式编写测试。第一遍通常是通过 IDE/Record 编写的,以获取我的大部分页面流和单击操作。完成后,我开始通过 Selenium-RC 逐步完成测试,添加断言并将绝对小部件定位器更改为更易读和更友好的 Xpath 表达式。 (以及记录测试!:))

        需要注意的一件事.. 如果您的测试是 xpath-heavy,由于 IE6 的 javascript 执行能力较差,它们可能会在 IE6 中运行得稍慢一些。 (我有一些测试套件在 IE 下的执行时间比在 FF 下要长近一个小时。这是可管理的,但在编写测试时需要牢记。)

        【讨论】:

          【解决方案7】:

          理论上,Selenium 有一个抽象称为 UI 元素(文档为 here)。

          特点是

          • 抽象定位器,独立于 html 实现;这将很好地映射到 Web 框架的组件或小部件的概念,

          • 汇总规则,允许将多个命令合并为一个更抽象的命令。

          我为利用此功能苦苦挣扎了几天,但最终我决定放弃它,原因如下:

          • 某些概念,例如偏移定位器(将它们视为组件的一部分)的概念尚未得到充分或有用的开发;
          • 格式化程序不完全支持该功能,并且格式化程序越新,支持的功能就越少,这暗示核心 Selenium 进化正在放弃此功能;
          • 它没有完全集成在 Selenium 2.0 (WebDriver) 中。

          【讨论】:

            【解决方案8】:

            我认为 Xpath 是确保可靠的硒测试的最佳方式。 我目前正在开发一个库来帮助更轻松地编写 xpath 表达式。

            如果有兴趣,可以在这里查看: http://www.unit-testing.net/CurrentArticle/How-To-Write-XPath-for-Selenium-Tests.html

            【讨论】:

              猜你喜欢
              • 2014-10-21
              • 1970-01-01
              • 2022-10-22
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多