【unittest單元測試框架】(9)認識Page Object
阿新 • • 發佈:2021-11-17
認識Page Object
Page Object 是 UI 自動化測試專案開發實踐的最佳設計模式之一,它的主要特點體現在對介面互動細節的封裝上,使測試用例更專注於業務的操作,從而提高測試用例的可維護性。 當為 Web 頁面編寫測試時,需要操作該 Web 頁面上的元素。然而,如果在測試程式碼中直接操作 Web 頁面上的元素,那麼這樣的程式碼是極其脆弱的,因為 UI 會經常變動。 page 物件的一個基本經驗法則是:凡是人能做的事,page 物件通過軟體客戶端都能做到。因此,它應當提供一個易於程式設計的介面,並隱藏視窗中底層的部件。當訪問一個文字框時,應該通過一個訪問方法(Accessor Method)實現字串的獲取與返回,複選框應當使用布林值,按鈕應當被表示為行為導向的方法名。page 物件應當把在 GUI 控制元件上所有查詢和操作資料的行為封裝為方法。 一個好的經驗法則是,即使改變具體的元素,page 物件的介面也不應當發生變化。 儘管該術語是 page 物件,但並不意味著需要針對每個頁面建立一個這樣的物件。例如,頁面上有重要意義的元素可以獨立為一個 page 物件。經驗法則的目的是通過給頁面建模,使其對應用程式的使用者變得有意義。 Page Object 是一種設計模式,在自動化測試開發中應遵循這種設計模式來編寫程式碼。 Page Object 應該遵循以下原則進行開發:- Page Object 應該易於使用。
- 有清晰的結構,如 PageObjects 對應頁面物件,PageModules 對應頁面內容。
- 只寫測試內容,不寫基礎內容。
- 在可能的情況下防止樣板程式碼。
- 不需要自己管理瀏覽器。
- 在執行時選擇瀏覽器,而不是類級別。
- 不需要直接接觸 Selenium。
# -*- coding:utf-8 -*- # filename: base.py # author: hello.yin # date: 2021/11/17 15:50 import time 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_)# xpath定位 def by_xpath(self, xpath): return self.driver.find_element_by_xpath(xpath) # class定位 def by_class(self, class_name): return self.driver.find_element_by_class_name(class_name) # name定位 def by_name(self, name): return self.driver.find_element_by_name(name) # 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 def get_text(self, xpath): return self.by_xpath(xpath).text # 執行js指令碼 def js(self, script): self.driver.execute_script(script)
建立 BasePage 類作為所有 Page 類的基類,在 BasePage 類中封裝一些方法,這些方法是我們在做自動化時經常用到的。
- open()方法用於開啟網頁,它接收一個 url 引數,預設為 None。如果 url 引數為None,則預設開啟子類中定義的 url。稍後會在子類中定義 url 變數。
- by_id()和 by_name()方法。我們知道,Selenium 提供的元素定位方法很長,這裡做了簡化,只是為了在子類中使用更加簡便。
- get_title()和 get_text()方法。這些方法是在寫自動化測試時經常用到的方法,也可以定義在 BasePage 類中。需要注意的是,get_text()方法需要接收元素定位,這裡預設為 XPath 定位。
# -*- coding:utf-8 -*- # filename: baidu_page.py # author: hello.yin # date: 2021/11/17 16:12 from base import BasePage class BaiduPage(BasePage): """ 百度 Page 層,百度頁面封裝操作到的元素""" url = "https://www.baidu.com" def search_input(self, search_key): self.by_id("kw").clear() self.by_id("kw").send_keys(search_key) def search_button(self): self.by_id("su").click()建立 BaiduPage.py 類繼承 BasePage 類,定義 url 變數,供父類中的 open()方法使用。這裡可能會有點繞,所以舉個例子:小明的父親有一輛電動玩具汽車,電動玩具汽車需要電池才能跑起來,但小明的父親並沒有為電動玩具汽車安裝電池。小明繼承了父親的這輛電動玩具汽車,為了讓電動玩具汽車跑起來,小明購買了電池。在這個例子中,open()方法就是“電動玩具汽車”,open()方法中使用的 self.url 就是“電池”,子類中定義的 url 是為了給父類中的 open()方法使用的。 在 search_input()和 search_button()方法中使用了父類的 self.by_id()方法來定位元素,比原生的 Selenium 方法簡短了不少。 在測試用例中,使用 BaiduPage 類及它所繼承的父類中的方法。 因為前面封裝了元素的定位,所以在編寫測試用例時會方便不少,當需要用到哪個 Page類時,只需將它傳入瀏覽器驅動,就可以使用該類中提供的方法了。
# -*- coding:utf-8 -*- # filename: test_BaiduPage.py # author: hello.yin # date: 2021/11/17/ 16:23 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(self): page = BaiduPage(self.driver) page.open() page.search_input("selenium") page.search_button() sleep(3) self.assertEqual(page.get_title(), "selenium_百度搜索") @classmethod def tearDownClass(cls): cls.driver.quit() if __name__ == "__main__": unittest.main(verbosity=2)
執行結果:
Testing started at 16:32 ... C:\Users\yzp\AppData\Local\Programs\Python\Python37\python.exe "C:\Program Files\JetBrains\PyCharm 2018.2\helpers\pycharm\_jb_unittest_runner.py" --path D:/00test/base_practice/page_object/page/test_BaiduPage.py Launching unittests with arguments python -m unittest D:/00test/base_practice/page_object/page/test_BaiduPage.py in D:\00test\base_practice\page_object\page Ran 1 test in 11.866s OK Process finished with exit code 0
本部落格所有文章僅用於學習、研究和交流目的,歡迎非商業性質轉載。
本文來自部落格園,作者:hello_殷,轉載請註明原文連結:https://www.cnblogs.com/yinzuopu/p/15568013.html
本文版權歸作者和部落格園共有,歡迎轉載,但必須給出原文連結,並保留此段宣告,否則保留追究法律責任的權利。