Do not understand PO design mode? This practical article will take you to finish PO

When writing test cases for UI pages (such as web pages and mobile end pages), there will be a large number of elements and operation details in the test cases. When the UI changes, the test case also changes. PageObject
This problem is well solved!

When using UI automation test tools (including selenium, appium, etc.), if there is no unified pattern for specification, it will become difficult to maintain with the increase of use cases, and PageObject
Making the automated script orderly, maintaining the page separately and encapsulating the details can make testcase more robust without major changes.

**Use**

Specific methods: encapsulate the element information and operation details into the Page class, and call the Page object in the test case. For example, there is a function "select album title", for which the function selectAblumWithTitle() needs to be established. The internal part of the function is the operation details findElementsWithClass('album'):

Take "take album title" as an example, and the pseudo code is as follows:

selectAblumWithTitle() {    #Select album    findElementsWithClass('album')    #Select album title    findElementsWithClass('title-field')    #Return Title contentreturn gettext()  
}

The main principle of page object is to provide a simple interface
(or function, such as selectablumwithtitle above), so that the caller can do any operation on the page, click the page element, and enter the content in the input box.

Therefore, if you want to access a text field, page object should have methods to get and return strings. page
Objects should encapsulate the details of data operations, such as finding elements and clicking elements. When a page element is changed, only the contents of the page class should be changed without changing the place where it is called.

Instead of creating a page class for every UI page, you should only create a page class for important elements in the page.

For example, if a page displays multiple albums, you should create an album list page object, which contains many album pages
object. If the hierarchy of some complex UI is only used to organize the UI, it should not appear in the page object. page
The purpose of object is to make sense to the users of the application by modeling the page:

If you want to navigate to another page, the initial page object should return to another page object. For example, if you click Register to enter the registration page, you should return it in the code
Register(). If you want to get page information, you can return the basic type (string, date).

It is not recommended to put assertions in the page object. You should test the page object instead of letting the page object test itself. Page
Object is responsible for providing the status information of the page. Here, only HTML is used to describe the Page Object. This mode can also be used to hide Java swing
UI details, which can be used for all UI frameworks.

**PageObject principle**

The core idea of PageObject is the six principles. Only by mastering the six principles can we carry out PageObject practice. This is the essence of PageObject.

selenium officially condenses six principles, and the following PageObject uses will focus on the six principles:

  • Public methods represent the services provided by the page

  • Don't expose page details

  • Do not mix assertions with operational details

  • Method can return to the newly opened page

  • Don't put the whole page in the PO

  • The same behavior will produce different results, and different results can be encapsulated

The following is an explanation of the above six principles:

  • Principle 1: to encapsulate the functions (or services) in the page, for example, clicking on the elements in the page can enter a new page, so you can encapsulate the method "enter a new page" for this service.

  • Principle 2: encapsulate details, and only provide method names (or interfaces) externally.

  • Principle 3: do not use assertions in the encapsulated operation details. Put assertions in a separate module, such as testcase.

  • Principle 4: clicking a button will open a new page. You can use the return method to jump. For example, return MainPage() means to jump to a new PO:MainPage.

  • Principle 5: only design PO for important elements in the page, and discard unimportant content.

  • Principle 6: an action may produce different results. For example, after clicking a button, it may succeed or fail. Two methods are encapsulated for the two results. click_success and click_error.

**Cases**

Case: enterprise wechat

Take the enterprise wechat homepage as an example. The enterprise wechat homepage has two main functions: immediate registration and enterprise login.

Enterprise wechat website: https://work.weixin.qq.com/

Index page

Click enterprise login to enter the login page, where you can scan the code for login and enterprise registration.

Login page

Click enterprise registration to enter the registration page, where you can enter relevant information for registration.

Register page

The page object principle is used to model the page. Here, three pages are involved: home page, Login and registration. Create three corresponding classes Index, Login and Register in the code:

• the login page provides the login findPassword function

– Login Class + login findPassword method

• the number of elements in the login page panel does not matter heart and the internal boundary panel control is hidden

• login success and failure will return different pages

– findPassword

– loginSuccess

– loginFail

• judge whether the login meets the expectation by the return value of method

UML diagram

Code directory structure
directory structure

BasePage is all page s
The parent class of object, which provides public methods for subclasses. For example, the following BasePage provides initialization driver and exit driver. In the code, the_ Used in the BasePage class of the page module__ init__ The initialization method performs initialization operations, including driver reuse, driver assignment, global wait setting (implicit wait), etc

from time import sleepfrom selenium import webdriverfrom selenium.webdriver.remote.webdriver import WebDriver  
  
class BasePage:    def __init__(self, driver: WebDriver = None):        #Right here driver Reuse, if it does not exist driver,Just build a new        if driver is None:            # Index The page needs to be used. When it is used for the first time, a new driver            self._driver = webdriver.Chrome()            # Set implicit wait time            self._driver.implicitly_wait(3)            # Visit web page            self._driver.get(self._base_url)        else:            # This method is required for Login, Register and other pages to avoid repeated construction of driver self_ driver = driver  
    def close(self):        sleep(20)        self._driver.quit()  

Index is the page object of the enterprise wechat homepage. It has two methods: enter the registration page object and enter the login page
Object, where the return method returns page object to realize page Jump, such as goto_register method return
Register to jump from the home page to the registration page:

class Index(BasePage):    _base_url = "https://work.weixin.qq.com/ "\enter the registration page def goto\u Register (self): self.\u driver.find\u element (by.link\u text," Register now "). click() \ #After creating a Login instance, you can call the method return Login (self.\u driver) in Login  

Login is the page of the login page
The main functions of object are to enter the registration page and scan the QR code. Therefore, two methods are created to represent two functions: scan_qrcode and goto_registry. The code is similar to the above, but more details:

from selenium.webdriver.common.by import Byfrom test_selenium.page.base_page import BasePagefrom test_selenium.page.register import Register  
class Login(BasePage):    # Scan QR code    def scan_qrcode(self):        pass    # Enter the registration page def goto_registry(self):        self._driver.find_element(By.LINK_TEXT, "enterprise registration") click()        return Register(self._driver)  

Register is the page of the registration page
The main function of object is to fill in the correct registration information. When the registration information is filled in incorrectly, the error information is returned. The register method implements the correct filling of the form. When the form is filled out, it returns to itself (the page still stays on the registration page). get_ error_ The message method implements the error filling. If the error is filled in, the error content is collected and returned:

from selenium.webdriver.common.by import Byfrom test_selenium.page.base_page import BasePage  
  
class Register(BasePage):    # Fill in the registration information. Only part of the information is filled in here, not all    def register(self, corpname):        # Fill in the form        self._driver.find_element(By.ID, "corp_name").send_keys(corpname)        self._driver.find_element(By.ID, "submit_btn").click()        # After filling in, stay on the registration page and continue to call Register Methods within         return self    #Error information is returned when filling in errors    def get_error_message(self):        # Collect error information and return result=[] for element in self_ driver. find_ elements(By.CSS_SELECTOR, ".js_error_msg"):            result. append(element.text)  
        return result  

test_ The index module tests the above functions. It is independent of the page class. In the TestIndex class, you only need to call the methods provided by the page class. For example, the following tests on the registration page and landing page use test_register and test_login method:

from test_selenium.page.index import Index  
  
class TestIndex:    # Initialization before all steps    def setup(self):        self.index = Index()    # Test of registration function    def test_register(self):        # get into index,Then enter the registration page to fill in the information        self.index.goto_register().register("Hogwarts Testing Institute")    # yes login Functional test    def test_login(self):        # Go to the registration page from the home page        register_page = self.index.goto_login().goto_registry()\            .register("Test bar (Beijing) Technology Co., Ltd")        # Assert whether the filling result is successful or failed        assert "Please select" in "|".join(register_page.get_error_message())    # Close driver def teardown (self): self index. close()  

** _
Come to Hogwarts test and development society to learn more advanced technologies of software testing and test development. The knowledge points cover web automated testing, app automated testing, interface automated testing, test framework, performance testing, security testing, continuous integration / continuous delivery /DevOps, test left, test right, precision testing, test platform development, test management, etc. the course technology covers bash, pytest, junit, selenium appium, postman, requests, httprunner, jmeter, jenkins, docker, k8s, elk, sonarqube, Jacobo, JVM sandbox and other related technologies to comprehensively improve the technical strength of test and development engineers

Click for more information

Posted by snoopgreen on Sat, 06 Aug 2022 01:54:34 +0930