摘要:文章通過(guò)設(shè)計(jì)特定測(cè)試場(chǎng)景,編寫(xiě)測(cè)試用例數(shù)據(jù),基于Python的Unittest框架,采用PO模式實(shí)現(xiàn)通用操作封裝,使用ddt裝飾器實(shí)現(xiàn)遍歷測(cè)試數(shù)據(jù)并批量執(zhí)行。所實(shí)現(xiàn)的自動(dòng)化測(cè)試檢驗(yàn)了人力資源管理系統(tǒng)中,以系統(tǒng)管理員身份登錄時(shí),添加政治類(lèi)別操作可能出現(xiàn)的幾種情況。該測(cè)試過(guò)程能夠自動(dòng)截圖,并通過(guò)斷言比較測(cè)試用例的正確性,同時(shí)將生成的測(cè)試報(bào)告發(fā)送到指定郵箱。
關(guān)鍵詞:Python;Unittest框架;PO對(duì)象;ddt裝飾器;自動(dòng)化測(cè)試
中圖分類(lèi)號(hào):TP311.53 文獻(xiàn)標(biāo)識(shí)碼:A
文章編號(hào):1009-3044(2024)17-0055-04 開(kāi)放科學(xué)(資源服務(wù))標(biāo)識(shí)碼(OSID) :
0 引言
作為保證軟件質(zhì)量的重要手段,軟件測(cè)試在日新月異的軟件開(kāi)發(fā)中愈發(fā)重要。自動(dòng)化測(cè)試是將以人為驅(qū)動(dòng)的測(cè)試行為轉(zhuǎn)化為機(jī)器執(zhí)行的過(guò)程,即模擬手工測(cè)試步驟,通過(guò)執(zhí)行以程序語(yǔ)言編制的測(cè)試腳本自動(dòng)地測(cè)試軟件,涵蓋了所有測(cè)試階段。自動(dòng)化測(cè)試具有跨平臺(tái)兼容性,且與進(jìn)程無(wú)關(guān)。廣義的自動(dòng)化測(cè)試強(qiáng)調(diào)整個(gè)測(cè)試過(guò)程都由計(jì)算機(jī)系統(tǒng)完成,范圍更廣;狹義的自動(dòng)化測(cè)試主要指通過(guò)某個(gè)自動(dòng)化工具自動(dòng)執(zhí)行特定測(cè)試任務(wù),處理范圍較小。
自動(dòng)化測(cè)試適用于回歸測(cè)試,因?yàn)橹貜?fù)單一的數(shù)據(jù)錄入或擊鍵等測(cè)試操作會(huì)造成不必要的時(shí)間和人力浪費(fèi)。測(cè)試人員通常需要借助自動(dòng)化測(cè)試工具對(duì)程序進(jìn)行理解和對(duì)設(shè)計(jì)文檔進(jìn)行驗(yàn)證。采用自動(dòng)化測(cè)試工具還有利于生成測(cè)試報(bào)告文檔,保持版本的連貫性。自動(dòng)化工具也能夠確定測(cè)試用例的覆蓋路徑,確定測(cè)試用例集對(duì)程序邏輯流程和控制流程的覆蓋。本文以系統(tǒng)管理員身份登錄人資管理系統(tǒng),驗(yàn)證添加政治面貌類(lèi)別操作。
1 Unittest 框架
Unittest框架是Python自帶的一種單元測(cè)試框架,具備編寫(xiě)用例、組織用例、執(zhí)行用例、輸出報(bào)告等自動(dòng)化框架的條件。該框架可以實(shí)現(xiàn)批量執(zhí)行用例,提供豐富的斷言知識(shí),還可以生成報(bào)告。Unittest框架的核心要素包括:TestCase(測(cè)試用例),TestSuite(測(cè)試套件),TextTestRunner(以文本形式運(yùn)行測(cè)試用例),Tes?tLoader(批量執(zhí)行測(cè)試用例-搜索指定文件夾內(nèi)指定字母開(kāi)頭的模塊),F(xiàn)ixture(固定裝置(兩個(gè)固定的函數(shù),一個(gè)初始化時(shí)使用,一個(gè)結(jié)束時(shí)使用)) 。在使用Unittest框架創(chuàng)建測(cè)試用例時(shí),首先要導(dǎo)入unittest包,新建的測(cè)試類(lèi)需繼承unittest.TestCase,并且測(cè)試方法必須以test字母開(kāi)頭[1]。
2 具體實(shí)現(xiàn)
2.1 測(cè)試環(huán)境搭建
安裝Python、Selenium 插件、PyCharm 平臺(tái),配置相關(guān)環(huán)境變量后,還需要安裝Chrome瀏覽器及對(duì)應(yīng)Chrome驅(qū)動(dòng),并確??梢猿晒Φ卿洿蜷_(kāi)人資管理系統(tǒng)。打開(kāi)PyCharm平臺(tái),創(chuàng)建一個(gè)項(xiàng)目,同時(shí)在創(chuàng)建項(xiàng)目時(shí)選擇解釋器為當(dāng)前安裝的Python[2]。
測(cè)試數(shù)據(jù)準(zhǔn)備如圖1所示。
項(xiàng)目路徑如圖2所示[3]。
2.2 封裝基本操作
首先在指定名稱文件夾下創(chuàng)建driver.py文件,封裝打開(kāi)谷歌瀏覽器操作,代碼如下:
from selenium import webdriver
def browser():
driver=webdriver.Chrome()
#打開(kāi)谷歌瀏覽器
return driver
在指定文件夾下創(chuàng)建function.py文件[4],封裝截圖方法inser_img(driver,filename),查找最新測(cè)試報(bào)告方法latest_report(report_dir),將測(cè)試報(bào)告發(fā)送到郵箱的方法send_mail(latest_report),以及讀取csv文件方法。讀取csv文件方法可以通過(guò)逐行逐列循環(huán)讀取csv文件來(lái)批量執(zhí)行測(cè)試用例,即通過(guò)數(shù)據(jù)驅(qū)動(dòng)實(shí)現(xiàn)自動(dòng)化測(cè)試某個(gè)功能,讀取csv文件代碼如下:
def get_csv_file(line):
# 文件路徑需要自己修改成自己的文件路徑
with open(r"盤(pán)符:\*\*\需被讀取的文件名.csv",encoding=′utf-8-sig′) as file:
reader=csv.reader(file)
for index,row in enumerate(reader,1):
if index==line:
return row 以及創(chuàng)建myunit.py文件,封裝啟動(dòng)測(cè)試集和結(jié)束測(cè)試集操作,代碼如下:
import unittest
from driver.driver import *
class StartEnd(unittest.TestCase):
def setUp(self):
self.driver=browser()
self.driver.implicitly_wait(10)
self.driver.maximize_window()
def tearDown(self):
self.driver.quit()
2.3 定義基礎(chǔ)類(lèi)Python 文件
創(chuàng)建基礎(chǔ)類(lèi)BasePage.py,用于被所有頁(yè)面對(duì)象類(lèi)繼承。其中,初始化方法用于打開(kāi)被測(cè)系統(tǒng)頁(yè)面,open方法用于打開(kāi)指定url地址頁(yè)面,find_element方法用于查找指定頁(yè)面元素,相關(guān)代碼如下:
from time import sleep
class Page():
def __init__(self, driver):
self.driver = driver
self. base_url = ′http://116.204.108.152: 30016/suthr/logon′
def _open(self, url):
url_ = self.base_url + url
print("Test page is %s" % url_)
self.driver.maximize_window()
self.driver.get(url_)
sleep(2)
assert self.driver.current_url == url_, ′Did not land on %s′ % url_
def open(self):
self._open(self.url)
def find_element(self, *loc):
return self.driver.find_element(*loc)
2.4 創(chuàng)建PageObject 對(duì)象
創(chuàng)建PO對(duì)象LoginPage.py文件,用于封裝登錄人資系統(tǒng)的操作;AddLeibiePage.py文件用于封裝一系列操作,包括點(diǎn)擊系統(tǒng)管理員鏈接→輸入系統(tǒng)管理員用戶名→輸入系統(tǒng)管理員密碼→點(diǎn)擊登錄按鈕→點(diǎn)擊類(lèi)別維護(hù)菜單→點(diǎn)擊政治面貌類(lèi)別子菜單→點(diǎn)擊創(chuàng)建類(lèi)別按鈕→填寫(xiě)政治類(lèi)別名稱框→填寫(xiě)描述框→點(diǎn)擊保存按鈕,以及讀取彈窗文字信息和紅底提示文字信息等。
以輸入政治類(lèi)別名稱,點(diǎn)擊保存為例,代碼如下:
from selenium.webdriver.common.by import By
from Website. test_case. page_object. BasePage im?port *
from time import sleep
class LeibieAdd(Page):
...
lbmc = (By.ID, ′dictValue′) # 定位類(lèi)別名稱輸入框
Baocun_loc = (By.XPATH, ′//*[@id="ajax-modal"]/div[3]/button[1]′) # 定位保存按鈕hongdi_loc = (By.ID,′dictValue-error′) # 定位消息提示文字信息
...
def type_lbmc(self, lbname):
self.find_element(*self.lbmc).clear()
self.find_element(*self.lbmc).send_keys(lbname)
# 輸入類(lèi)別名稱
def type_Baocun(self):
self.find_element(*self.Baocun_loc).click()
#點(diǎn)擊保存按鈕
def type_hongdi(self):
return self.find_element(*self.hongdi_loc).get_attri?bute("innerHTML")
# 讀取紅底文字信息
...
def test_zzlb_add(driver, lbname):
...
sleep(1)
add_page.type_lbmc(lbname)
sleep(1)
add_page.type_Baocun()
需要注意的是,各類(lèi)動(dòng)態(tài)增加方法時(shí)一定要加self參數(shù),并且PO類(lèi)與調(diào)用PO類(lèi)的封裝方法縮進(jìn)要一致,表示同級(jí)的關(guān)系。如果縮進(jìn)不一致,在后續(xù)測(cè)試類(lèi)調(diào)用封裝方法時(shí)會(huì)報(bào)“方法沒(méi)有定義”的錯(cuò)誤。
2.5 創(chuàng)建測(cè)試類(lèi)
使用unittest框架創(chuàng)建測(cè)試類(lèi)test_addzz.py,測(cè)試類(lèi)中每一個(gè)以test開(kāi)頭的方法就是一條測(cè)試用例。同時(shí),使用ddt裝飾器實(shí)現(xiàn)遍歷測(cè)試數(shù)據(jù),每遍歷出一條數(shù)據(jù),就往測(cè)試類(lèi)中添加一個(gè)以test開(kāi)頭的方法setattr (類(lèi),方法名,方法)[5]。
該測(cè)試類(lèi)通過(guò)調(diào)用function.py中的讀取csv文件方法get_csv_file(line)以及調(diào)用test_user_login(driver,username,password)方法,分別測(cè)試了csv文件中的3條測(cè)試數(shù)據(jù),對(duì)應(yīng)添加政治類(lèi)別中的輸入政治類(lèi)別名稱為空、重復(fù)和過(guò)長(zhǎng)的操作。測(cè)試類(lèi)能夠?qū)崿F(xiàn)測(cè)試界面的截屏,并且能夠斷言對(duì)比測(cè)試用例是否正確。關(guān)鍵代碼如下:
import unittest
from Website. test_case. model import function,myunit
from Website.test_case.page_object.AddLeibiePage import *
from Website.test_case.page_object.LoginPage im?port *
from Website. test_case. page_object. AddPage im?port *
import time
import ddt
@ddt.ddt
class AddzzTest(myunit.StartEnd):
# @unittest.skip(′skip this case′)
def test01_add_null(self):
′′′操作成功′′′
print("test case is start run...")
test_date = function.get_csv_file(2)
#創(chuàng)建參數(shù)接收測(cè)試數(shù)據(jù)
test_user_login(self.driver,′ceshi01′,′123456′)
#登錄
test_zzlb_add(self.driver,test_date[0])
#輸入測(cè)試數(shù)據(jù)
time.sleep(3)
function. inser_img(self. driver, "test01_add_null.png")
# 截屏
po = LeibieAdd(self.driver)
# 設(shè)置參數(shù)接收數(shù)據(jù)
self.assertIn(test_date[1], po.type_hongdi())
# 斷言對(duì)比測(cè)試用例是否正確
print("test case is successful test end!")
...
if __name__ == ′__main__′:
unittest.main()
2.6 生成測(cè)試報(bào)告并發(fā)送指定郵箱
為能夠生成測(cè)試報(bào)告并發(fā)送指定郵箱,須創(chuàng)建run_test.py文件,相關(guān)代碼如下:
import unittest
from Website.test_case.model.function import *
from HTMLTestRunner import HTMLTestRunner
import time
report_dir=′./test_report′
test_dir=′./test_case′
print("start run test case")
discover=unittest. defaultTestLoader. discover(test_dir,pattern="test_addzz.py")
now=time.strftime("%Y-%m-%d %H_%M_%S")
report_name=report_dir+′/′+now+′result.html′
print("start write report..")
with open(report_name,′wb′) as f:
runner=HTMLTestRunner(stream=f,title="Test Re?port" ,description="localhost login test")
runner.run(discover)
f.close()
print("find latest report")
latest_report=latest_report(report_dir)
print("send email report..")
send_mail(latest_report)
print("Test end")
3 測(cè)試結(jié)果
3.1 PyCharm 界面結(jié)果顯示
從測(cè)試工作臺(tái)可以看到,3個(gè)測(cè)試用例均通過(guò),分別測(cè)試了添加政治類(lèi)別名稱為空、添加政治類(lèi)別名稱重復(fù)和添加政治類(lèi)別名稱過(guò)長(zhǎng)這3種情況。測(cè)試結(jié)果均與預(yù)期相同,能夠彈出相應(yīng)的錯(cuò)誤提示彈窗,測(cè)試通過(guò),并成功發(fā)送測(cè)試報(bào)告郵件。界面如圖3、圖4 所示。
3.2 測(cè)試報(bào)告郵件
正確收到測(cè)試報(bào)告郵件,郵件顯示測(cè)試內(nèi)容和測(cè)試結(jié)果。界面如圖5所示。
4 總結(jié)
本文通過(guò)設(shè)計(jì)特定測(cè)試場(chǎng)景,編寫(xiě)測(cè)試用例數(shù)據(jù),實(shí)現(xiàn)了自動(dòng)化測(cè)試,檢驗(yàn)了人資管理系統(tǒng)中以系統(tǒng)管理員身份登錄時(shí),添加政治類(lèi)別操作可能出現(xiàn)的幾種情況。自動(dòng)化測(cè)試能夠自動(dòng)截圖、斷言對(duì)比測(cè)試用例的正確性,并將生成的測(cè)試報(bào)告發(fā)送到指定郵箱。
整體使用Python+Unittest+PO框架實(shí)現(xiàn)自動(dòng)化測(cè)試?;赨nittest框架,使用PO對(duì)象實(shí)現(xiàn)通用操作封裝,提高了測(cè)試腳本的可重用性;使用ddt裝飾器實(shí)現(xiàn)遍歷測(cè)試數(shù)據(jù)并批量執(zhí)行[6];同時(shí)實(shí)現(xiàn)了測(cè)試過(guò)程的自動(dòng)截圖,能夠斷言對(duì)比測(cè)試用例的正確性,并將生成的測(cè)試報(bào)告發(fā)送到指定郵箱??梢钥闯?,使用Py?thon+Unittest+PO 框架實(shí)現(xiàn)自動(dòng)化測(cè)試,能夠?qū)崿F(xiàn)自動(dòng)化測(cè)試流程的一體化,提高測(cè)試效率。
參考文獻(xiàn):
[1] 王春明.基于Unittest的Python測(cè)試系統(tǒng)[J].數(shù)字通信世界,2023(3):66-69.
[2] 李亞偉,牛士會(huì).基于Python通過(guò)unittest進(jìn)行自動(dòng)化測(cè)試[J].價(jià)值工程,2023,42(14):163-165.
[3] 蔣程燕,孟令琴.基于Python語(yǔ)言的自動(dòng)化測(cè)試應(yīng)用實(shí)例[J].工業(yè)控制計(jì)算機(jī),2021,34(10):109-110,113.
[4] 王娜.基于python的接口自動(dòng)化測(cè)試框架設(shè)計(jì)[J].電腦知識(shí)與技術(shù),2020,16(12):246-248.
[5] 方巍,吳伶琳.基于Python的Web自動(dòng)化測(cè)試的實(shí)踐[J].現(xiàn)代計(jì)算機(jī),2020(34):91-94.
[6] 單攀攀.一種基于Selenium與Unittest的Web自動(dòng)化測(cè)試框架[J].信息技術(shù)與網(wǎng)絡(luò)安全,2021,40(9):77-80.
【通聯(lián)編輯:謝媛媛】