web自動化測試中的PO模式(一)---將公共數據分離出來


1、PO模式的思想

  1. 原理:
    1. 將頁面的元素定位和元素行為封裝成一個page類
    2. 類的屬性:元素的定位
    3. 類的行為:元素的操作 
  2. 頁面對象和測試用例分離
  3. 測試用例:
    1. 調用所需要頁面對象中的行為,組成測試用例
    2. 測試用例中,只需要含有頁面函數的調用和斷言,不應該出現元素定位等其他的操作,如果寫測試用例中出現需要其他的額外的操作,可以想辦法封裝到頁面對象或者元素定位中
  4. 好處:
    1. 當某個頁面的元素發生變化,只需要修改該頁面對象中的代碼即可,測試用例不需要修改
    2. 提高代碼的重用率,結構清晰,維護代碼容易
    3. 測試用例發生變化是,不需要或者只需要修改少數頁面對象代碼即可

2、使用unittest框架實現PO模式

  1. 新建一個包,命名為PageObjects,包中用來封裝各個頁面的功能
    1. 頁面對象封裝的類中,函數用來實現頁面的功能,在類的初始化函數中,使用傳參(driver)的方式完成,頁面只需要實現對應功能即可,具體傳入什么樣的測試,在測試用例的前置條件中實現,可以提高函數的重用率
      1. 頁面對象封裝函數
         1 from selenium.webdriver.support import expected_conditions as EC
         2 from selenium.webdriver.support.wait import WebDriverWait
         3 from selenium.webdriver.common.by import By
         4 class LoginPage:
         5     def __init__(self,driver):
         6         self.driver=driver
         7 
         8     def login(self,username,pwd,remember_user=True):
         9         # 等待定位元素出現
        10         WebDriverWait(self.driver,10).until(EC.visibility_of_element_located((By.XPATH,"//input[@name='phone']")))
        11         # 輸入用戶名
        12         self.driver.find_element_by_xpath("//input[@name='phone']").send_keys(username)
        13         # 輸入密碼
        14         self.driver.find_element_by_xpath("//input[@name='password']").send_keys(pwd)
        15         # 定位記住手機號元素
        16         remember_ele=self.driver.find_element_by_xpath("//input[@name='remember_me']")
        17         # 判斷時候記住手機號
        18         if remember_user==True:
        19             remember_ele.checked=True
        20         else:
        21             remember_ele.checked=False
        22         # 點擊登錄
        23         self.driver.find_element_by_xpath("//button[text()='登錄']").click()
      2. 測試用例調用頁面對象函數,代碼如下

        1     def test_login_success(self):
        2         # 2、步驟
        3         # 實例化LoginPage類
        4         lg=LoginPage(self.driver)
        5         # 調用login方法
        6         lg.login("登錄賬號","登錄密碼")
        7         # 3、斷言
        8         self.assertTrue(IndexPage(self.driver).isExist_logout_ele())
      3. Index_page頁面封裝函數代碼
        from selenium.webdriver.support import expected_conditions as EC
        from selenium.webdriver.support.wait import WebDriverWait
        from selenium.webdriver.common.by import By
        class IndexPage:
            def __init__(self,driver):
                self.driver=driver
        
            def isExist_logout_ele(self):
                try:
                    WebDriverWait(self.driver,10).until(EC.visibility_of_element_located((By.XPATH,"//a[text()='退出']")))
                    return True
                except:
                    return False
      4. 測試用例的前置條件代碼
        import unittest
        from selenium import webdriver
        from PageObjects.login_page import LoginPage
        from PageObjects.index_page import IndexPage
        class TestLogin(unittest.TestCase):
        
            def setUp(self):
                # 1、前置條件
                url="http://ip:host/Index/login.html"
                self.driver=webdriver.Chrome()
                self.driver.maximize_window()
                self.driver.get(url)
      5. 運行測試用例可以在測試用例最后面使用一下代碼,然后運行該代碼
        if __name__ == '__main__':
            unittest.main()
      6. 運行結果如下,表示運行成功  
  2. 新建一個包,命名為TestCases,包中用來寫測試用例,測試用例中用到那個頁面對象中的函數時,只需要調用頁面對象中的函數就可以了
  3. 新建一個包,命名為TestDatas,用來寫測試數據,將測試數據的類導入到測試用例模塊中,進行使用,這樣的話,測試數據便於管理,測試數據添加、修改、刪除不用修改測試用例
    1. 在TestCases下面新建一個公用的數據管理.py文件Common_Datas.py和模塊數據的.py文件login_datas.py,如下t圖:

        

      #Common_Datas.py
      web_login_url="http://ip:port/Index/login.html"
      
      #login_datas.py
      #正常場景---測試數據
      success_data={"user":"18000123456","pwd":"123456"}
      
      # 異常用例--手機號格式不正確(大於11位,小於11位,為空,不在號碼段)
      error_data=[
          {"user": "180001234561", "pwd": "123456","check":"請輸入正確的手機號"},
          {"user": "1800012345", "pwd": "123456","check":"請輸入正確的手機號"},
          {"user": "10684723485", "pwd": "123456","check":"請輸入正確的手機號"},
          {"user": "", "pwd": "123456","check":"請輸入手機號"},
          {"user": "18000123456", "pwd": "","check":"請輸入密碼"},
          {"user": "", "pwd": "","check":"請輸入手機號"},
      ]

       

    2. 在測試用例模塊使用數據管理模塊中的數據
       1 import unittest
       2 from selenium import webdriver
       3 from PageObjects.login_page import LoginPage
       4 from PageObjects.index_page import IndexPage
       5 from TestDatas import Common_Datas as CD
       6 from TestDatas import login_datas as ld
       7 from ddt import ddt,data
       8 
       9 @ddt
      10 class TestLogin(unittest.TestCase):
      11     @classmethod
      12     def setUpClass(cls):
      13         # 1、前置條件
      14         cls.driver=webdriver.Chrome()
      15         cls.driver.maximize_window()
      16         cls.driver.get(CD.web_login_url)
      17         # 實例化LoginPage類
      18         cls.lg=LoginPage(cls.driver)
      19     @classmethod
      20     def tearDownClass(cls):
      21         cls.driver.quit()
      22 
      23     def tearDown(self):
      24         self.driver.refresh()
      25         pass
      26     # 正常用例--登錄成功
      27     def test_login_1_success(self):
      28         # 2、步驟
      29 
      30         # 調用login方法
      31         self.lg.login(ld.success_data['user'],ld.success_data['pwd'])
      32         # 3、斷言
      33         self.assertTrue(IndexPage(self.driver).isExist_logout_ele())
      34     # 異常用例--手機號碼格式不正確(大於11位,小於11位,為空,不在號碼段)  ddt
      35     @data(*ld.error_data)
      36     def test_login_0_user_wrongFormat(self,item):
      37         self.lg.login(item['user'],item['pwd'])
      38         self.assertEqual(self.lg.get_errorMsg_form_loginArea(),item['check'])

      備注:

      setUpClass(cls)函數和tearDownClass(cls)只在整個用例開始和結束時運行一次,必須使用@classmethod來修飾,如上面的異常測試用例有6條,在用例開始前和結束時只運行一次 
      setUp(self)函數和tearDown(self)在每個測試用例開始和結束時運行,如果使用這兩個函數,上面的6條用例,每運行一個,就會運行一次這兩個函數,總共運行6次
      tearDown(self)可以和setUpClass(cls)函數和tearDownClass(cls)函數結合使用,如上面的界面刷新self.driver.refresh()和頁面關閉cls.driver.quit()
    3. 測試用例類型相同的測試數據可以設計在一起,使用ddt在測試用例運行時分別執行測試用例
    4. 使用unittest框架,運行測試用例,如下:
       1 import unittest
       2 from TestCases.test_login import TestLogin
       3 from HTMLTestRunnerCN import HTMLTestReportCN
       4 # 創建一個容器,用來存測試用例
       5 suite=unittest.TestSuite()
       6 # 加載測試用例的類的實例
       7 loader=unittest.TestLoader()
       8 # 將測試用例加載到suite容器中
       9 suite.addTest(loader.loadTestsFromTestCase(TestLogin))
      10 # 打開文件,用來寫測試報告
      11 with open("test_result.html",'wb') as file:
      12 
      13     # runner=unittest.TextTestRunner(verbosity=1)
      14 
      15     runner=HTMLTestReportCN( stream=file, verbosity=2, title="web自動化測試", description="第一個web自動化測試", tester="wsk")
      16     # 運行測試用例
      17     runner.run(suite)
    5. 運行結果,如下圖:

       

       在寫測試用例時,如果使用unittest框架可以使用函數名來控制代碼的執行順序,如:

      ok test_login_0_user_wrongFormat_6 (TestCases.test_login.TestLogin)  --------------------  0  
      ok test_login_1_success (TestCases.test_login.TestLogin)------------------------------------------1    前面都一樣,0比1小,先運行

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM