Don't understand the PO design pattern? This practical article takes you through PO

When writing test cases for UI pages (such as web pages, mobile pages), there will be a large number of elements and operational details in the test cases. When the UI changes, the test case should also change accordingly. PageObject solves this problem very well!

When using UI automation testing tools (including selenium, appium, etc.), if there is no unified model for specification, it will become difficult to maintain as the number of use cases increases, and PageObject makes the automation script in order, maintains the page separately and encapsulates the details, It can make the testcase more robust without major changes.

Specific method: Encapsulate the element information and operation details into the Page class, and call the Page object (PageObject) on the test case. For example, there is a function "select the title of the album", and a function selectAblumWithTitle() needs to be created for it. Inside the function is the operation details findElementsWithClass('album') etc:

Taking "Get Album Title" as an example, the pseudocode is as follows:

selectAblumWithTitle() {
    #选取相册
    findElementsWithClass('album')
    #选取相册标题
    findElementsWithClass('title-field')
    #返回标题内容
    return getText()

}

 

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

So if you want to access a text field, the page object should have methods to get and return the string. The page object should encapsulate details of operations on the data, such as finding elements and clicking elements. When the page element changes, only the content in the page class should be changed, and there is no need to change the place where it is called.

Don't create a page class for every UI page, only create page classes for the important elements of the page.

For example, if a page displays multiple albums, an album list page object should be created, which contains many album page objects. If the hierarchical structure of some complex UI is only used to organize the UI, then it should not appear in the page object. The purpose of the page object is to make sense to the user of the application by modeling the page:

If you want to navigate to another page, the initial page object should return another page object, such as clicking register to enter the registration page, and return Register() in the code. If you want to get page information, you can return basic types (string, date).

It is recommended not to put assertions in the page object. The page object should be tested instead of letting the page object test itself. The responsibility of the page object is to provide page status information. Here only HTML is used to describe Page Object, this mode can also be used to hide Java swing UI details, it can be used in all UI frameworks.

The core idea of ​​PageObject is the six principles. Only by mastering the six principles can the actual practice of PageObject be carried out. This is the essence of PageObject. Selenium officially condenses six principles, and the subsequent use of PageObject will be carried out around the six principles:

  • Public methods represent services provided by the page
  • Do not expose page details
  • Don't mix assertions with operational details
  • The method can return to the newly opened page
  • Don't put whole page content in PO
  • The same behavior will produce different results, different results can be encapsulated

Below, the above six principles are explained:

  • Principle 1: It is necessary to encapsulate the functions (or services) in the page, such as clicking an element in the page to enter a new page, so the method of "entering a new page" can be encapsulated for this service.
  • Principle 2: Encapsulate details, and only provide method names (or interfaces) to the outside world.
  • Principle 3: Do not use assertions in the encapsulated operation details, put the assertions in a separate module, such as testcase.
  • Principle 4: Clicking a button will open a new page, and the return method can be used to indicate a jump, such as return MainPage() means to jump to a new PO: MainPage.
  • Principle 5: Only do PO design for important elements on the page, and discard unimportant content.
  • Principle 6: An action may produce different results. For example, after clicking a button, the click may be successful or the click may fail. Two methods are encapsulated for the two results, click_success and click_error.

Taking the corporate WeChat homepage as an example, the corporate WeChat homepage has two main functions: immediate registration and corporate login. Corporate WeChat URL: work.weixin.qq.com/

Click Enterprise Login to enter the login page, where you can scan the code to log in and register as an enterprise.

Click Enterprise Registration to enter the registration page, where you can enter relevant information to register.

Use the page object principle to model the page, which involves three pages: home page, login, and registration. Create the corresponding three classes Index, Login, 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 does not matter, and the internal interface controls are hidden • Different pages will be returned for successful and failed logins – findPassword – loginSuccess – loginFail • Determine whether the login meets expectations through the return value of the method

BasePage is the parent class of all page objects. It provides public methods for subclasses. For example, the following BasePage provides initialization driver and exit driver. In the code, the __init__ initial method is used in the BasePage class of the base_page module to perform initialization operations, including driver Multiplexing, driver assignment, global wait setting (implicit wait), etc.:

from time import sleep
from selenium import webdriver
from selenium.webdriver.remote.webdriver import WebDriver

class BasePage:
    def __init__(self, driver: WebDriver = None):
        #此处对driver进行复用,如果不存在driver,就构造一个新的
        if driver is None:
            # Index页面需要用,首次使用时构造新driver
            self._driver = webdriver.Chrome()
            # 设置隐式等待时间
            self._driver.implicitly_wait(3)
            # 访问网页
            self._driver.get(self._base_url)
        else:
            # Login与Register等页面需要用这个方法,避免重复构造driver
            self._driver = driver

    def close(self):
        sleep(20)
        self._driver.quit()

Index is the page object of the enterprise WeChat home page. It has two methods, entering the registration page object and entering the login page object. Here, the return method returns the page object to realize the page jump. For example: the goto_register method returns Register to realize the jump from the home page to Registration page:

class Index(BasePage):
    _base_url = "https://work.weixin.qq.com/"
    # 进入注册页面
    def goto_register(self):
        self._driver.find_element(By.LINK_TEXT, "立即注册").click()
        # 创建Register实例后,可调用Register中的方法
        return Register(self._driver)
    # 进入登录页面
    def goto_login(self):
        self._driver.find_element(By.LINK_TEXT, "企业登录").click()
        # 创建Login实例后,可调用Login中的方法
        return Login(self._driver)

Login is the page object of the login page. Its main functions are: 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 introduction:

from selenium.webdriver.common.by import By
from test_selenium.page.base_page import BasePage
from test_selenium.page.register import Register

class Login(BasePage):
    # 扫描二维码
    def scan_qrcode(self):
        pass
    # 进入注册页面
    def goto_registry(self):
        self._driver.find_element(By.LINK_TEXT, "企业注册").click()
        return Register(self._driver)

Register is the page object of the registration page. Its main function is to fill in the correct registration information, and return an error message when it is filled in incorrectly. The register method implements the correct form filling, and returns itself when the filling is complete (the page still stays on the registration page). The get_error_message method realizes the case of wrong filling. If it is wrong, it will collect the error content and return:

from selenium.webdriver.common.by import By
from test_selenium.page.base_page import BasePage

class Register(BasePage):
    # 填写注册信息,此处只填写了部分信息,并没有填写完全
    def register(self, corpname):
        # 进行表格填写
        self._driver.find_element(By.ID, "corp_name").send_keys(corpname)
        self._driver.find_element(By.ID, "submit_btn").click()
        # 填写完毕,停留在注册页,可继续调用Register内的方法 
        return self
    #填写错误时,返回错误信息
    def get_error_message(self):
        # 收集错误信息并返回
        result=[]
        for element in self._driver.find_elements(By.CSS_SELECTOR, ".js_error_msg"):
            result.append(element.text)

        return result

The test_index module is a test for 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 test_register and test_login methods are used for the registration page and landing page test below:

from test_selenium.page.index import Index

class TestIndex:
    # 所有步骤前的初始化
    def setup(self):
        self.index = Index()
    # 对注册功能的测试
    def test_register(self):
        # 进入index,然后进入注册页填写信息
        self.index.goto_register().register("霍格沃兹测试学院")
    # 对login功能的测试
    def test_login(self):
        # 从首页进入到注册页
        register_page = self.index.goto_login().goto_registry()\
            .register("测吧(北京)科技有限公司")
        # 对填写结果进行断言,是否填写成功或者填写失败
        assert "请选择" in "|".join(register_page.get_error_message())
    # 关闭driver
    def teardown(self):
        self.index.close()

Finally: The following are the supporting learning materials. For friends who do [software testing], it should be the most comprehensive and complete preparation warehouse. This warehouse also accompanied me through the most difficult journey. I hope it can help you too!

Software testing interview applet

The software test question bank maxed out by millions of people! ! ! Who is who knows! ! ! The most comprehensive quiz mini program on the whole network, you can use your mobile phone to do the quizzes, on the subway or on the bus, roll it up!

The following interview question sections are covered:

1. Basic theory of software testing, 2. web, app, interface function testing, 3. network, 4. database, 5. linux

6. web, app, interface automation, 7. performance testing, 8. programming basics, 9. hr interview questions, 10. open test questions, 11. security testing, 12. computer basics

  How to obtain the full set of materials: Click the small card below to get it yourself

Guess you like

Origin blog.csdn.net/weixin_57794111/article/details/132713960