• Page Objects


    Page Objects

    原文地址:https://github.com/SeleniumHQ/selenium/wiki/PageObjects

    Within your web app's UI there are areas that your tests interact with. A Page Object simply models these as objects within the test code. This reduces the amount of duplicated code and means that if the UI changes, the fix need only be applied in one place.//Page Object将页面内的元素及操作模型化,目的是减少重复代码和易于修改。

    Implementation Notes

    PageObjects can be thought of as facing in two directions simultaneously. Facing towards the developer of a test, they represent the services offered by a particular page. Facing away from the developer, they should be the only thing that has a deep knowledge of the structure of the HTML of a page (or part of a page) It's simplest to think of the methods on a Page Object as offering the "services" that a page offers rather than exposing the details and mechanics of the page. As an example, think of the inbox of any web-based email system. Amongst the services that it offers are typically the ability to compose a new email, to choose to read a single email, and to list the subject lines of the emails in the inbox. How these are implemented shouldn't matter to the test.//PageObject隐藏页面的细节,只提供页面的功能。

    Because we're encouraging the developer of a test to try and think about the services that they're interacting with rather than the implementation, PageObjects should seldom expose the underlying WebDriver instance. To facilitate this, methods on the PageObject should return other PageObjects. This means that we can effectively model the user's journey through our application. It also means that should the way that pages relate to one another change (like when the login page asks the user to change their password the first time they log into a service, when it previously didn't do that) simply changing the appropriate method's signature will cause the tests to fail to compile. Put another way, we can tell which tests would fail without needing to run them when we change the relationship between pages and reflect this in the PageObjects.//PageObject的一个方法应该返回一个页面PageObject。

    One consequence of this approach is that it may be necessary to model (for example) both a successful and unsuccessful login, or a click could have a different result depending on the state of the app. When this happens, it is common to have multiple methods on the PageObject://将成功和失败的操作都模型化。

     1 public class LoginPage {
     2     public HomePage loginAs(String username, String password) {
     3         // ... clever magic happens here
     4     }
     5 
     6     public LoginPage loginAsExpectingError(String username, String password) {
     7         //  ... failed login here, maybe because one or both of the username and password are wrong
     8     }
     9 
    10     public String getErrorMessage() {
    11         // So we can verify that the correct error is shown
    12     }
    13 }

    The code presented above shows an important point: the tests, not the PageObjects, should be responsible for making assertions about the state of a page. For example://PageObject的方法不做断言,断言由测试代码去做。

    1 public void testMessagesAreReadOrUnread() {
    2     Inbox inbox = new Inbox(driver);
    3     inbox.assertMessageWithSubjectIsUnread("I like cheese");
    4     inbox.assertMessageWithSubjectIsNotUnread("I'm not fond of tofu");
    5 }

    could be re-written as:

    public void testMessagesAreReadOrUnread() {
        Inbox inbox = new Inbox(driver);
        assertTrue(inbox.isMessageWithSubjectIsUnread("I like cheese"));
        assertFalse(inbox.isMessageWithSubjectIsUnread("I'm not fond of tofu"));
    }

    Of course, as with every guideline there are exceptions, and one that is commonly seen with PageObjects is to check that the WebDriver is on the correct page when we instantiate the PageObject. This is done in the example below.//检查当前页面是不是所需页面。

    Finally, a PageObject need not represent an entire page. It may represent a section that appears many times within a site or page, such as site navigation. The essential principle is that there is only one place in your test suite with knowledge of the structure of the HTML of a particular (part of a) page.//PageObject不需要包含整个页面。

    Summary

    • The public methods represent the services that the page offers//使用公共方法提供页面的功能。
    • Try not to expose the internals of the page//不要展示页面的内部构造。
    • Generally don't make assertions//不要做断言。
    • Methods return other PageObjects//方法的返回值是一个PageObject。
    • Need not represent an entire page//不需要呈现整个页面。
    • Different results for the same action are modelled as different methods//用不同方法展示一个操作的失败和成功结果。

    Example

     1 public class LoginPage {
     2     private final WebDriver driver;
     3 
     4     public LoginPage(WebDriver driver) {
     5         this.driver = driver;
     6 
     7         // Check that we're on the right page.
     8         if (!"Login".equals(driver.getTitle())) {
     9             // Alternatively, we could navigate to the login page, perhaps logging out first
    10             throw new IllegalStateException("This is not the login page");
    11         }
    12     }
    13 
    14     // The login page contains several HTML elements that will be represented as WebElements.
    15     // The locators for these elements should only be defined once.
    16         By usernameLocator = By.id("username");
    17         By passwordLocator = By.id("passwd");
    18         By loginButtonLocator = By.id("login");
    19 
    20     // The login page allows the user to type their username into the username field
    21     public LoginPage typeUsername(String username) {
    22         // This is the only place that "knows" how to enter a username
    23         driver.findElement(usernameLocator).sendKeys(username);
    24 
    25         // Return the current page object as this action doesn't navigate to a page represented by another PageObject
    26         return this;    
    27     }
    28 
    29     // The login page allows the user to type their password into the password field
    30     public LoginPage typePassword(String password) {
    31         // This is the only place that "knows" how to enter a password
    32         driver.findElement(passwordLocator).sendKeys(password);
    33 
    34         // Return the current page object as this action doesn't navigate to a page represented by another PageObject
    35         return this;    
    36     }
    37 
    38     // The login page allows the user to submit the login form
    39     public HomePage submitLogin() {
    40         // This is the only place that submits the login form and expects the destination to be the home page.
    41         // A seperate method should be created for the instance of clicking login whilst expecting a login failure. 
    42         driver.findElement(loginButtonLocator).submit();
    43 
    44         // Return a new page object representing the destination. Should the login page ever
    45         // go somewhere else (for example, a legal disclaimer) then changing the method signature
    46         // for this method will mean that all tests that rely on this behaviour won't compile.
    47         return new HomePage(driver);    
    48     }
    49 
    50     // The login page allows the user to submit the login form knowing that an invalid username and / or password were entered
    51     public LoginPage submitLoginExpectingFailure() {
    52         // This is the only place that submits the login form and expects the destination to be the login page due to login failure.
    53         driver.findElement(loginButtonLocator).submit();
    54 
    55         // Return a new page object representing the destination. Should the user ever be navigated to the home page after submiting a login with credentials 
    56         // expected to fail login, the script will fail when it attempts to instantiate the LoginPage PageObject.
    57         return new LoginPage(driver);   
    58     }
    59 
    60     // Conceptually, the login page offers the user the service of being able to "log into"
    61     // the application using a user name and password. 
    62     public HomePage loginAs(String username, String password) {
    63         // The PageObject methods that enter username, password & submit login have already defined and should not be repeated here.
    64         typeUsername(username);
    65         typePassword(password);
    66         return submitLogin();
    67     }
    68 }

    Support in WebDriver

    There is a PageFactory in the support package that provides support for this pattern, and helps to remove some boiler-plate code from your Page Objects at the same time.

  • 相关阅读:
    PSP总结报告
    第十三周例行报告
    对团队成员公开感谢
    附加作业 软件工程原则的应用实例分析
    第十二周例行报告
    第十一周例行报告
    第十周例行报告
    第八周例行报告
    第七周例行报告
    第六周例行报告
  • 原文地址:https://www.cnblogs.com/superbaby11/p/6084721.html
Copyright © 2020-2023  润新知