Page Object是Selenium自動化測試項目開發實踐的最佳設計模式之一,通過對界面元素的封裝減少冗余代碼,同時在后期維護中,若元素定位發生變化,只需要調整頁面元素封裝的代碼,提高測試用例的可維護性。
本項目以163郵箱登錄為例,163登錄腳本(非PO模式)請查看博客中的隨筆信息。
1、項目目錄結構及相關介紹
test_programe 測試項目
- driver:用於存放驅動
- mail:用於存放163登錄項目的測試用例、測試報告以及測試數據等
- run_all_test.py:用於運行項目自動化用例
mail目錄
- data:存放測試數據
- report:存放HTML測試不報告,其中該目錄下的image目錄用於存放測試過程中的截圖
- test_case:用於存放測試用例
test_case目錄
- model:存放配置函數及公共類
- page_object:用於存放頁面對象
- login_case.py:測試對象用例
2、編寫公共模塊:
編寫驅動文件...\test_programe\mail\test_case\model\driver.py
1 from selenium.webdriver import Remote 2 from selenium import webdriver 3 #啟動瀏覽器驅動 4 def browser(): 5 driver = webdriver.Chrome() 6 ''' 7 #可以啟動到遠程主機中,運行自動化測試 8 host = '127.0.0.1:4444' #運行主機:端口號(本機默認:127.0.0.1:4444) 9 dc = {'browserName': 'chrome'} #指定瀏覽器 10 driver = Remote(command_execute='http://' + host + '/wd/hub', 11 desired_capabilities=dc) 12 ''' 13 return driver 14 ''' 15 #用於測試該腳本是否有效 16 if __name__ == '__main__': 17 dr = browser() 18 '''
編寫測試公共類...\test_programe\mail\test_case\model\myunit.py

from time import sleep from .function import insert_img import unittest from .driver import browser class MyTest(unittest.TestCase): def setUp(self): self.driver = browser() self.driver.implicitly_wait(10) self.driver.maximize_window() def tearDown(self): self.driver.quit()
定義截圖函數...\test_programe\mail\test_case\model\function.py

1 from selenium import webdriver 2 import os 3 #截圖函數 4 def insert_img(driver, file_name): 5 base_dir = os.path.dirname(os.path.dirname(__file__)) 6 #print(base_dir) 7 base_dir = str(base_dir) 8 #print(base_dir) 9 base_dir = base_dir.replace('\\','/') 10 #print(base_dir) 11 base = base_dir.split('/mail')[0] 12 #print(base) 13 file_path = base + '/mail/report/image/' + file_name 14 driver.get_screenshot_as_file(file_path) 15 16 ''' 17 #用於驗證該腳本是否有效 18 if __name__ == '__main__': 19 driver = webdriver.Chrome() 20 driver.get('http://www.baidu.com') 21 insert_img(driver, 'baidu.jpg') 22 driver.quit() 23 '''
3、編寫Page Object
創建基礎類...\test_programe\mail\test_case\page_object\base.py

1 from selenium import webdriver 2 from selenium.webdriver.common.by import By 3 from time import sleep 4 import unittest 5 #基本層 6 class Base(object): 7 8 9 def __init__(self, driver, base_url = 'http://mail.163.com'): 10 self.driver = driver 11 self.base_url = base_url 12 self.timeout = 30 13 14 def _open(self, url): 15 url_ = self.base_url + url 16 #print(url_) 17 self.driver.maximize_window() 18 self.driver.get(url_) 19 sleep(2) 20 assert self.driver.current_url == url_, 'Did ont land on %s' % url_ 21 22 def open(self): 23 self._open(self.url) 24 25 #*參數個數不是固定的(By.ID, 'kw') 26 def find_element(self, *loc): 27 return self.driver.find_element(*loc) 28 29 def iframe(self, iframeid): 30 return self.driver.switch_to.frame(iframeid) 31 32 def iframe_out(self): 33 return self.driver.switch_to.default_content() 34 35
創建163郵箱登錄對象類...\test_programe\mail\test_case\page_object\login_page.py

1 from selenium.webdriver.common.action_chains import ActionChains 2 from selenium.webdriver.common.by import By 3 from time import sleep 4 from .base import Base 5 6 #頁面對象(PO)登錄頁面 7 class LoginPage(Base): 8 url = '/' 9 login_iframe_loc = 'x-URS-iframe' 10 login_username_text_loc = (By.NAME, 'email') 11 login_password_text_loc = (By.NAME, 'password') 12 login_button_loc = (By.ID, 'dologin') 13 login_erro_hint_loc = (By.CLASS_NAME, 'ferrorhead') 14 15 #把每一個元素封裝成一個方法 16 def login_iframe(self): 17 self.iframe(self.login_iframe_loc) 18 19 def login_iframe_out(self): 20 self.iframe_out() 21 22 def login_username(self, text): 23 self.find_element(*self.login_username_text_loc).send_keys(text) 24 25 def login_password(self, text): 26 self.find_element(*self.login_password_text_loc).send_keys(text) 27 28 def login_button(self): 29 self.find_element(*self.login_button_loc).click() 30 31 def login_error_hint(self): 32 self.login_iframe() 33 return self.find_element(*self.login_erro_hint_loc).text 34 self.login_iframe_out() 35 36 def login_action(self, username, password): 37 self.login_iframe() 38 self.login_username(username) 39 self.login_password(password) 40 self.login_button() 41 self.login_iframe_out()
創建163郵箱登錄成功后對象類...\test_programe\mail\test_case\page_object\mail_page.py

1 from selenium.webdriver.common.action_chains import ActionChains 2 from selenium.webdriver.common.by import By 3 from time import sleep 4 from .base import Base 5 6 class MailPage(Base): 7 url = '/' 8 login_success_user_loc = (By.ID, 'spnUid') 9 10 def login_success_user(self): 11 return self.find_element(*self.login_success_user_loc).text
4、編寫測試用例
創建mail登錄類...\test_programe\mail\test_case\login_case.py

1 from time import sleep 2 import unittest, random, sys 3 from model import myunit, function 4 from page_object.login_page import LoginPage 5 from page_object.mail_page import MailPage 6 sys.path.append('./model') 7 sys.path.append('./page_obj') 8 9 class LoginTest(myunit.MyTest): 10 11 def test_login_user_pwd_null(self): 12 '''用戶名、密碼為空登錄''' 13 po = LoginPage(self.driver) 14 po.open() 15 po.login_action('','') 16 sleep(2) 17 self.assertEqual(po.login_error_hint(),'請輸入帳號') 18 function.insert_img(self.driver, 'user_pwd_null.jpg') 19 20 def test_login_pwd_null(self): 21 '''密碼為空登錄''' 22 po = LoginPage(self.driver) 23 po.open() 24 po.login_action('abc','') 25 sleep(2) 26 self.assertEqual(po.login_error_hint(),'請輸入密碼') 27 function.insert_img(self.driver, 'pwd_null.jpg') 28 29 def test_login_user_pwd_error(self): 30 '''用戶名或密碼錯誤''' 31 po = LoginPage(self.driver) 32 po.open() 33 character = random.choice('zyxwvutsrqponmlkjihgfedcba') 34 username = "test" + character 35 po.login_action(username,"$#%#") 36 sleep(2) 37 #print(po.login_error_hint()) 38 self.assertEqual(po.login_error_hint(),'帳號或密碼錯誤') 39 function.insert_img(self.driver, "user_pwd_error.jpg") 40 41 def test_login_success(self): 42 '''用戶名、密碼正確,登錄成功''' 43 po = LoginPage(self.driver) 44 po.open() 45 user = "ldq791918813" 46 po.login_action(user,"xiuxiu060801zhu") 47 sleep(2) 48 po2 = MailPage(self.driver) 49 #print(po2.login_success_user()) 50 self.assertEqual(po2.login_success_user(),user+"@163.com") 51 function.insert_img(self.driver, "success.jpg")
5、執行測試用例
創建用例執行代碼...\test_programe\

1 import unittest, time 2 from HTMLTestRunner import HTMLTestRunner 3 from email.mime.text import MIMEText 4 from email.header import Header 5 import smtplib, os 6 7 #發送測試報告,需要配置你的郵箱賬號 8 def send_mail(file_new): 9 f = open(file_new, 'rb') 10 mail_body = f.read() 11 f.close() 12 msg = MIMEText(mail_body, 'html', 'utf-8') 13 msg['Subject'] = Header("自動化測試報告", 'utf-8') 14 msg['From']= 'ldq791918813@163.com' 15 msg['To']= '791918813@qq.com' 16 smtp = smtplib.SMTP() 17 smtp.connect("smtp.163.com") 18 smtp.login("ldq791918813@163.com", "密碼") 19 smtp.sendmail("ldq791918813@163.com","791918813@qq.com",msg.as_string()) 20 smtp.quit() 21 print('email has send out!') 22 23 #查找測試報告目錄,找到最新生成的測試報告文件 24 def new_report(testreport): 25 lists = os.listdir(testreport) 26 lists.sort(key=lambda fn: os.path.getmtime(testreport + '\\' + fn)) 27 file_new = os.path.join(testreport, lists[-1]) 28 print(file_new) 29 return file_new 30 31 #指定測試用例為當前文件夾下的test_case目錄 32 test_dir = './mail/test_case' 33 test_report = 'D:\\sublimePython\\test_programe\\mail\\report' 34 discover = unittest.defaultTestLoader.discover(test_dir, pattern = '*_case.py') 35 36 if __name__ == "__main__": 37 38 now = time.strftime("%Y-%m-%d %H_%M_%S") 39 filename = test_report + '/' + now + 'result.html' 40 fp = open(filename, 'wb') 41 #runner = unittest.TextTestRunner() 42 runner = HTMLTestRunner(stream=fp, 43 title='測試報告', 44 description="運行環境:windows 7, Chrome") 45 runner.run(discover) 46 fp.close() 47 48 new_report = new_report(test_report) 49 send_mail(new_report)
6、HTML測試報告:
7、截圖信息: