[Selenium Learning] Page Object Design Pattern

Chapter table of contents

Preface

1. Understanding

2. Advantages

3. Implement Paget Object

1.Paget Object simple example

2. Improve Paget Object encapsulation

Summarize


Preface

Page Object is one of the best design patterns for UI automation test project development practice. Its main feature is reflected in the encapsulation of interface interaction details, making test cases more focused on business operations, thereby improving the maintainability of test cases.

1. Understanding

        In Page Object mode, each web page in the application is represented as a separate class or object. Page Object contains all the methods and properties needed to interact with the page, such as finding elements, clicking buttons, filling out forms, and retrieving data.

        By using Page Objects, testers can create more organized and reusable code and reduce the amount of duplicate code. Page Objects also make it easier to test updates. If the UI of your application changes, you only need to make the changes in the corresponding Page Object class.

2. Advantages

1. Improve readability

Using Page Objects, test code becomes more readable and easier to understand. Testers can easily write readable code in Page Objects without having to directly manipulate the browser's underlying API. This makes the test code easier to maintain and debug, while also reducing the complexity of the test code.

2. Improve maintainability

Using Page Objects, testers can separate UI elements and test code, thereby improving code maintainability. If a UI element changes, the tester only needs to make the change in the corresponding Page Object class without having to find and update all the code related to the element in the test code. This can greatly reduce code maintenance costs and time.

3. Improve scalability

Using Page Objects, testers can easily add new test cases and new pages. Since each page has a corresponding Page Object class, you only need to create a new Page Object class to add test cases for the new page. This makes the test automation framework more flexible and scalable.

4. Reduce the amount of duplicate code

Using Page Objects, testers can abstract common blocks of code into Page Objects and reuse them when needed. This reduces the amount of duplication of test code and increases code reusability. Additionally, this reduces errors in the test code and improves the quality of the test code.

3. Implement Paget Object

        ​ ​ ​ ​ Below we will introduce the use of this design pattern through examples.

1.Paget Object simple example

        Taking Baidu search as the column, suppose we have the following test code:
...

def test_baidu_search_case1(self):
    self.driver.get(self.base_url)
    self.driver.find_element(By.ID, "kw").send_keys("selenium")
    self.driver.find_element(By.ID, "su").click()
def test_baidu_search_case2(self):
    self.driver.get(self.base_url)
    self.driver.find_element(By.ID, "kw").send_keys("unittest")
    self.driver.find_element(By.ID, "su").click()
def test_baidu_search_case3(self):
    self.driver.get(self.base_url)
    self.driver.find_element(By.ID, "kw").send_keys("page object")
    self.driver.find_element(By.ID, "su").click()

...
        The biggest problem with this code is that the positioning and operation of elements are reused in three test cases. this will bring
A big problem is that when the positioning of an element changes, for example, id=kw becomes invalid, the positioning method should be adjusted in time.
At this time, you need to make modifications to each of the three test cases.
        Suppose that our automation project has hundreds of test cases, and the UI is likely to change frequently, which will increase the maintenance cost of automated test cases.
        The design idea of ​​Page Object is to layer element positioning and element operations, which brings the most direct benefits.
The only advantage is that when elements change, you only need to maintain the element positioning of the page layer, and do not need to care about which test cases are used.
These elements are used in . When writing test cases, you don't need to care about how the elements are positioned.
        ​​​​Create the baidu_page.py file with the following content:
# _*_ coding:utf-8 _*_
"""
name:zhangxingzai
date:2023/4/3
"""

from selenium.webdriver.common.by import By


class BaiduPage():
    def __init__(self, driver):
        self.driver = driver

    def search_input(self, search_key):
        self.driver.find_element(By.ID, "kw").send_keys(search_key)

    def search_button(self):
        self.driver.find_element_by_id("su").click()
        First, create the BaiduPage class, receive the parameter driver in the __init__() initialization method and assign it to self.driver.
Then, encapsulate the search_input() method and search_button() method respectively to locate and operate the elements. The package here is only
For elements that may be manipulated on a page, in principle, one element is encapsulated into a method. When the element is positioned
When the method changes, you only need to maintain the method here, without caring about which test cases this method is used by.
# _*_ coding:utf-8 _*_
"""
name:zhangxingzai
date:2023/4/3
"""

import unittest
from selenium import webdriver
from baidu_page import BaiduPage


class TestBaidu(unittest.TestCase):

    def setUp(self):
        self.driver = webdriver.Firefox()
        self.baidu_url = 'https://www.baidu.com'

    def test_baidu_search_case1(self):
        self.driver.get(self.baidu_url)
        bd = BaiduPage(self.driver)
        bd.search_input("selenium")
        bd.search_button()

    def test_baidu_search_case2(self):
        self.driver.get(self.baidu_url)
        bd = BaiduPage(self.driver)
        bd.search_input("unittest")
        bd.search_button()

    def test_baidu_search_case3(self):
        self.driver.get(self.baidu_url)
        bd = BaiduPage(self.driver)
        bd.search_input("page object")
        bd.search_button()

    def tearDown(self):
        self.driver.close()


if __name__ == '__main__':
    unittest.main
        ​ ​ ​ First, import the BaiduPage class in the test, and then pass in the driver for the BaiduPage class in each test case.
In this way, you can easily use the methods it encapsulates to design specific test cases. The purpose of this is to test
Eliminate element positioning in use cases. If you want to operate the Baidu input box, then just call the search_input() method and pass in
Just search for keywords, and you don't need to care about how the Baidu input box is positioned.

2. Improve Paget Object encapsulation

        There are still some problems with the above code. For example, in the past, a test case only required writing 4 to 5 lines of code, but now it has to be encapsulated in the Page layer for each element to be operated, and then referenced in the specific test case. . In order to make the encapsulation of the Page layer more convenient, we make some improvements.
        ​​​​Create a base.py file with the following content.
# _*_ coding:utf-8 _*_
"""
name:zhangxingzai
date:2023/4/3
"""

from selenium.webdriver.common.by import By


class BasePage:
    """
    基础 Page 层,封装一些常用方法
    """

    def __init__(self, driver):

        self.driver = driver

    # 打开页面
    def open(self, url=None):
        if url is None:
            self.driver.get(self.url)
        else:
            self.driver.get(url)

    # id 定位
    def by_id(self, id_):
        return self.driver.find_element(By.ID, id_)

    # name 定位
    def by_name(self, name):
        return self.driver.find_element(By.NAME, name)

    # class 定位
    def by_class(self, class_name):
        return self.driver.find_element(By.CLASS_NAME, class_name)

    # XPath 定位
    def by_xpath(self, xpath):
        return self.driver.find_element(By.XPATH, xpath)

    # CSS 定位
    def by_css(self, css):
        return self.driver.find_element(By.CSS_SELECTOR, css)

    # 获取 title
    def get_title(self):
        return self.driver.title

    # 获取页面 text,仅使用 XPath 定位
    def get_text(self, xpath):
        return self.by_xpath(xpath).text

    # 执行 JavaScript 脚本
    def js(self, script):
        self.driver.execute_script(script)
        ​​​Create the BasePage class as the base class for all Page classes, and encapsulate some methods in the BasePage class. These methods
It is what we often use when doing automation.
        ​​​​​Modify the baidu_page.py file below:
# _*_ coding:utf-8 _*_
"""
name:zhangxingzai
date:2023/4/3
"""

from base import BasePage


class BaiduPage(BasePage):
    """百度 Page 层,百度页面封装操作到的元素"""
    url = "https://www.baidu.com"

    def search_input(self, search_key):
        self.by_id("kw").send_keys(search_key)

    def search_button(self):
        self.by_id("su").click()
        In the search_input() and search_button() methods, the self.by_id() method of the parent class is used to locate the element, for example
The native Selenium methods are much shorter.
        In the test case, use the methods in the BaiduPage class and the parent class it inherits:
# _*_ coding:utf-8 _*_
"""
name:zhangxingzai
date:2023/4/3
"""

import unittest
from time import sleep
from selenium import webdriver
from baidu_page import BaiduPage


class TestBaidu(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Firefox()

    def test_baidu_search_case(self):
        page = BaiduPage(self.driver)
        page.open()
        page.search_input("selenium")
        page.search_button()
        sleep(2)
        self.assertEqual(page.get_title(), "selenium_百度搜索")

    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()


if __name__ == '__main__':
    unittest.main(verbosity=2)
        Because the positioning of elements is encapsulated in the front, it will be much more convenient when writing test cases. When you need to use which Page
class, you only need to pass it into the browser driver and you can use the methods provided in the class.

Summarize

The Page Object pattern is a very useful test automation design pattern that can improve the readability, maintainability and scalability of the test code. It can also reduce the complexity and duplication of the test code and improve the quality and efficiency of the test code. .

Guess you like

Origin blog.csdn.net/weixin_73348410/article/details/129846359