页面对象  

页面对象模式是一种用可重用类表示页面及其元素的方法。页面对象通过构建一个抽象来消除重复,使你能够编写浏览器测试以实现最大的可维护性和健壮性。

页面对象模式起源于 WebDriver,可以在 此处 找到一个很好的解释(带有 Java 中的示例)。

为应用程序的每个页面创建一个页面对象,该对象具有表示给定页面上可用服务的方法。你应该将系统的全部实现细节(即 HTML 元素、等待 DOM 更新等)封装在这些对象中。你的测试代码(即 RSpec 代码块、Cucumber 步骤定义)永远不应访问基础浏览器实例或直接处理 HTML 元素。

从本质上讲,你应该有这样的心态:如果你的 Web 应用程序被重写为桌面应用程序,你的测试代码不应该需要更改 - 你只需要页面对象层的另一个实现即可。虽然严格来说,一组页面不一定是对桌面应用程序进行建模的好方法,但牢记这一点可以很容易地决定什么应该放在哪里。

以下示例假设你熟悉 RSpec 执行测试断言的方式。

考虑此脚本

  browser = Watir::Browser.new
  browser.goto "http://example.com/login"

  browser.text_field(:name => "user").set "Mom"
  browser.text_field(:name => "pass").set "s3cr3t"
  browser.button(:id => "login").click

  Watir::Wait.until { browser.title == "Your Profile" }
  browser.div(:id => "logged-in").should exist

使用页面对象,这可能会变成

  site = Site.new(Watir::Browser.new)

  login_page = site.login_page.open
  user_page = login_page.login_as "Mom", "s3cr3t"

  user_page.should be_logged_in

其实现可以是

 
  class BrowserContainer
    def initialize(browser)
      @browser = browser
    end
  end

  class Site < BrowserContainer
    def login_page
      @login_page = LoginPage.new(@browser)
    end

    def user_page
      @user_page = UserPage.new(@browser)
    end

    def close
      @browser.close
    end
  end # Site

  class LoginPage < BrowserContainer
    URL = "http://example.com/login"

    def open
      @browser.goto URL
      self
    end

    def login_as(user, pass)
      user_field.set user
      password_field.set pass

      login_button.click

      next_page = UserPage.new(@browser)
      Watir::Wait.until { next_page.loaded? }

      next_page
    end

    private

    def user_field
      @browser.text_field(:name => "user")
    end

    def password_field
      @browser.text_field(:name => "pass")
    end

    def login_button
      @browser.button(:id => "login")
    end
  end # LoginPage

  class UserPage < BrowserContainer
    def logged_in?
      logged_in_element.exists?
    end

    def loaded?
      @browser.title == "Your Profile"
    end

    private

    def logged_in_element
      @browser.div(:id => "logged-in")
    end
  end # UserPage

然后可以将其与其他工具集成。例如,使用 Cucumber,你可以在 env.rb 中拥有以下内容

 
require "watir-webdriver"
require "/path/to/site"

module SiteHelper
  def site
    @site ||= (
      Site.new(Watir::Browser.new(:firefox))
    )
  end
end

World(SiteHelper)

以及此步骤定义

 
 Given /I have successfully logged in/ do
   login_page = site.login_page.open

   user_page = login_page.login_as "Mom", "s3cr3t"
   user_page.should be_logged_in
 end

断言/期望应保存在你的测试代码中。不要在页面对象中使用断言;而是询问它们的状态,并对结果进行断言。例如

 

  #
  # bad example
  #

  class SomePage
    def assert_loaded
      raise "not loaded" unless some_element.exists?
    end
  end

  it "should be loaded" do
    page.assert_loaded
  end

  #
  # good example
  #

  class SomePage
    def loaded?
      some_element.exists?
    end
  end

  it "should be loaded" do
    page.should be_loaded
  end

另请参阅

与 Watir-webdriver 配合使用的页面对象 gem

与页面对象和 Watir-webdriver 相关的博客文章

与页面对象和 webdriver/Selenium 相关的博客文章

上次更新:2018 年 8 月 4 日