先來一張圖,看看整個Po架構的實現:
operatePages:操作頁面,也就是把每一個操作頁面,寫成一個類。
pages:用來存放公共配置文件的一個目錄。比如基礎類,后續所有類都會用到基礎類。
reports:用來存放生成的測試報告。
testCases:用例存放目錄。用來存放測試用例的目錄。
1.我們先看page類的實現
from selenium.webdriver.support.wait import WebDriverWait #from selenium.webdriver.support import expected_conditions as EC #頁面基類 class HomePage(): #初始化頁面屬性 def __init__(self,url,driver): self.url = url self.dr = driver #封裝元素定位方式 def find_element(self,*loc): ###----- 確保元素是可見的。 try: #以下入參本身是元組,不需要加* #WebDriverWait(self.dr,20).until(EC.visibility_of_element_located(loc)) #以下入參為元組的元素,需要加* WebDriverWait(self.dr,20).until(lambda dr:dr.find_element(*loc).is_displayed()) return self.dr.find_element(*loc) except: print(*loc+"元素在頁面中未找到!")
整個page類中,我們隊瀏覽器的驅動和地址進行了初始化動作,因為后續的用例在執行時都會使用該方法。
在基礎類Homepage類中,我們把元素定位的方法進行了改寫,后續的所有元素定位都可以使用基礎類中的find_element方法。
二、我們針對登陸頁面寫一個類,該類繼承繼承類的一些屬性和方法,下面我們來看整個類的實現:
from selenium.webdriver.common.by import By from time import sleep import sys sys.path.append("../pages/") from homePage import *
class LoginPage(HomePage): #元素定位器,定位頁面的元素 #用戶名 username_loc = (By.ID,"mobilePhone") #密碼 passwd_loc = (By.ID,"password") #登陸按鈕 loginBtn_loc = (By.CSS_SELECTOR,"a.btn.btn-block.fs-16") #退出鏈接 logoutBtn_loc = (By.CSS_SELECTOR,"a.fc-blue.mr-5") #用戶名為空的提示信息 userNull_loc = (By.CSS_SELECTOR,"#error > span") #密碼為空的提示信息 passWordNull_loc = (By.CSS_SELECTOR,"#error > span") #打開登陸頁面 def openLoginPage(self): self.dr.get(self.url) sleep(0.5) self.dr.refresh() self.dr.maximize_window() sleep(0.05) #操作元素 #輸入用戶名 def input_userName(self,userName): self.find_element(*self.username_loc).send_keys(userName) #輸入密碼 def input_passWord(self,passWord): self.find_element(*self.passwd_loc).send_keys(passWord) #點擊登陸按鈕 def click_loginBtn(self): self.find_element(*self.loginBtn_loc).click() #獲取登陸成功后的提示信息 def get_assertText(self): return self.find_element(*self.logoutBtn_loc).text #用戶名為空的提示信息 def get_userNullText(self): return self.find_element(*self.userNull_loc).text #密碼為空的提示信息 def get_passWordNullText(self): return self.find_element(*self.passWordNull_loc).text
1.operatepages類繼承的是Homepage基礎類;
2.我們在登陸頁面,我們把所有的登陸頁面需要操作的方法都封裝成方法,好處是可以方便用例層去調用。類似模塊的作業,當調用時可以直接傳遞對應的參數就好了。。
3.封裝斷言文本信息方法 比如 登陸成功后的信息、用戶名為空的信息、密碼為空的情況
三、testLogin.py文件實現代碼:
from selenium import webdriver from time import sleep import unittest,sys sys.path.append("../operatePages/") sys.path.append("../pages/") sys.path.append("./") from operateLoginPage import *
from homePage import * #導入xlrd模塊 import xlrd #1、打開excel data = xlrd.open_workbook(r"E:\untitled\testCases\參數化數據.xlsx") #讀取用戶名和密碼所在的頁面的數據 sheet1 = data.sheet_by_index(0) #獲取用戶名 userNames = sheet1.col_values(0) #獲取密碼 passWords = sheet1.col_values(1) #獲取預期結果 exceptResults = sheet1.col_values(2) class TestLogin(unittest.TestCase): def setUp(self): self.url = "https://www.gjfax.com/toLogin" self.dr = webdriver.Chrome() self.dr.implicitly_wait(20) #實例化一個operateLoginPage類的對象 self.loginPage = LoginPage(self.url,self.dr) #測試正常登陸 def testLogin(self): #打開登陸頁面 self.loginPage.openLoginPage() #輸入用戶名 self.loginPage.input_userName(userNames[1]) #輸入密碼 self.loginPage.input_passWord(passWords[1]) #點擊登陸 self.loginPage.click_loginBtn() #斷言 self.assertEqual(exceptResults[1],self.loginPage.get_assertText()) #測試用戶名為空 def test_user_null(self): #打開登陸頁面 self.loginPage.openLoginPage() #輸入用戶名 self.loginPage.input_userName(userNames[2]) #輸入密碼 self.loginPage.input_passWord(passWords[2]) #點擊登陸 self.loginPage.click_loginBtn() #斷言 self.assertEqual(exceptResults[2],self.loginPage.get_userNullText()) #測試密碼為空 def test_password_null(self): #打開登陸頁面 self.loginPage.openLoginPage() #輸入用戶名 self.loginPage.input_userName(userNames[3]) #輸入密碼 self.loginPage.input_passWord(passWords[3]) #點擊登陸 self.loginPage.click_loginBtn() #斷言 self.assertEqual(exceptResults[3],self.loginPage.get_passWordNullText()) def tearDown(self): self.dr.quit() if __name__=="__main__": unittest.main()
四、總執行文件:
import unittest from HTMLTestRunner import HTMLTestRunner import time import sys #臨時改變工作路徑 sys.path.append("./operatePages/") sys.path.append("./pages/") from operateLoginPage import *
from homePage import *
if __name__ == "__main__": #定義測試用例所在的路徑 casesPath = "./testCases/" #定義測試報告所在的路徑 reportPath = "./reports/" #定義測試報告的名稱 reportName = time.strftime("%Y-%m-%d %H%M%S",time.localtime()) + '.html' #定義測試報告所在的路徑和名稱 reportPathName = reportPath + reportName #把測試用例組裝到unittest的discover容器 discover = unittest.defaultTestLoader.discover(casesPath,"*.py") #打開測試報告,並賦予讀寫權限 fp = open(reportPathName,"wb") #把測試結果寫進測試報告,並裝載到HTHMLTestRunner模塊 run = HTMLTestRunner(stream=fp,title="ecshop自動化測試報告",description="用例執行情況") #運行腳本 run.run(discover) #關閉打開的測試報告 fp.close()
純文本郵件:
#!/usr/bin/python3 import smtplib from email.mime.text import MIMEText from email.header import Header # 第三方 SMTP 服務 mail_host="smtp.qq.com" #設置服務器 mail_user="xxxxx@qq.com" #用戶名 mail_pass="ctludyhhtzecbggg" #口令 sender = 'xxxxx@qq.com' receivers = ['xxxx@163.com'] # 接收郵件,可設置為你的QQ郵箱或者其他郵箱 message = MIMEText('Python 郵件發送測試...', 'plain', 'utf-8') message['From'] = Header("xxx自動化提升班", 'utf-8') message['To'] = Header("測試", 'utf-8') subject = 'xxxx自動化提升班 -- 郵件發送測試' message['Subject'] = Header(subject, 'utf-8') try: smtpObj = smtplib.SMTP() smtpObj.connect(mail_host) smtpObj.login(mail_user,mail_pass) smtpObj.sendmail(sender, receivers, message.as_string()) print ("郵件發送成功") except smtplib.SMTPException: print ("無法發送郵件")
帶附件郵件:
from HTMLTestRunner import HTMLTestRunner from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.header import Header import smtplib import unittest import time import os import sys sys.path.append("./operatePages/") sys.path.append("./pages/") #定義發送郵件 def send_mail(file_new,fileName): f = open(file_new, 'rb').read() att = MIMEText(f, 'base64', 'utf-8') #att = MIMEText(f, 'plain', 'utf-8') att["Content-Type"] = 'application/octet-stream' #附件名稱 att["Content-Disposition"] = 'attachment;filename='+fileName msgRoot = MIMEMultipart("related") #郵件標題 msgRoot['Subject'] = Header('ECSHOP自動化測試報告', 'utf-8') msgRoot['from'] = 'xxxx@qq.com' msgRoot['to'] = 'xxxxx@163.com' #msgRoot['from'] = '發送郵件的郵箱用戶名' #msgRoot['to'] = '接收郵件的郵箱用戶名' msgRoot.attach(att) #使用QQ郵箱進行郵件發送 try: smtp = smtplib.SMTP() smtp.connect('smtp.qq.com',25) smtp.login('xxxxx@qq.com', 'ctludyhhtzecbggg') smtp.sendmail('xxxxxxxxxx@qq.com', 'xxxxx@163.com', msgRoot.as_string()) #smtp.login('發送郵件的郵箱用戶名', '郵箱的登錄密碼') #smtp.sendmail('發送郵件的郵箱用戶名', '接收郵件的郵箱用戶名', msgRoot.as_string()) smtp.quit() print("郵件發送成功!") except: print("郵件發送失敗!") #查找目錄 def new_report(testreport): lists = os.listdir(testreport) lists.sort(key=lambda fn : os.path.getmtime(testreport + "\\" + fn)) file_new = os.path.join(testreport,lists[-1]) print(file_new) return file_new if __name__ == '__main__': #定義測試用例的存放路徑 test_dir = "./testCases/" #把測試用例加入 discover 容器 discover = unittest.defaultTestLoader.discover(start_dir=test_dir,pattern='*.py') #定義測試報告的存放路徑 testReportDir = "./reports/" #定義測試報告的名字 nowTime = time.strftime("%Y-%m-%d%H%M%S", time.localtime()) fileName = nowTime+".html" #定義測試路徑和測試報告名字 testReportDir_FileName = testReportDir + fileName #打開文件,並賦予可寫權限 fp = open(testReportDir_FileName,"wb") #把測試結果寫進測試報告,並裝載到HTHMLTestRunner模塊 runner = HTMLTestRunner(stream = fp ,title = "ERP自動化測試報告",description="用例執行情況:") #運行測試用例 runner.run(discover) #關閉文件 fp.close() #發送郵件 new_report = new_report(testReportDir) send_mail(new_report,fileName)
整個架構圖:
operatePages:操作頁面,也就是把每一個操作頁面,寫成一個類。
pages:用來存放公共配置文件的一個目錄。比如基礎類,后續所有類都會用到基礎類。
reports:用來存放生成的測試報告。
testCases:用例存放目錄。用來存放測試用例的目錄。