什么是自動(dòng)化測試
把人做的事情交給機(jī)器做,這就是自動(dòng)化朋鞍。而自動(dòng)化測試則是把測試工作交給了機(jī)器已添,測試環(huán)境和被測對象是不變的。下面是人工測試和自動(dòng)化測試的變化
用例 -> 自動(dòng)化用例
斷言 -> 自動(dòng)化斷言
自動(dòng)化用例和普通測試用例
自動(dòng)化測試因?yàn)樾枰o到機(jī)器去測試滥酥,所以在用例變更時(shí)酝碳,不僅要定義用例步驟,還要對應(yīng)完成用例實(shí)現(xiàn)恨狈。所以一個(gè)常常改變的系統(tǒng)不應(yīng)該為此編寫自動(dòng)化用例。
自動(dòng)化斷言和普通斷言
如上面所述呛讲,斷言也是需要我們編寫的禾怠,當(dāng)然借助現(xiàn)有的一些框架,我們可以避免很多的編寫贝搁。第二個(gè)我要說的是吗氏,如果你從事過UI、AI方面的測試工作雷逆,你會(huì)發(fā)現(xiàn)在反復(fù)執(zhí)行的過程中你會(huì)發(fā)現(xiàn)某一次會(huì)出現(xiàn)一些返回的偏差弦讽,這一偏差是由被測對象決定的。設(shè)備會(huì)在某種環(huán)境下,渲染失敗或者是異常往产,而AI本身就是一個(gè)概率的模型被碗,結(jié)果本身就是隨機(jī)的。所以我們需要編寫復(fù)雜斷言來處理這類問題嗎仿村?答案是否定的锐朴,我們應(yīng)該先人工測試保證被測對象的穩(wěn)定性。甚至我們對于這些用例回到手工測試蔼囊。
自動(dòng)化測試用例的顆粒度
在自動(dòng)化測試中焚志,被測對象和測試環(huán)境都是影響自動(dòng)化測試穩(wěn)定性的因素。所以針對這兩者畏鼓,我們可以控制用例的顆粒度來降低我們的維護(hù)成本酱酬。
假設(shè)有這樣的一個(gè)接口,支持門店名稱(name)和業(yè)務(wù)員手機(jī)號(hào)(phone)的模糊查詢云矫,接口響應(yīng)數(shù)據(jù)如下:
{
"code":200,
"data":[
{"id":1,"name":"121","sale_info":{"phone":135}},
{"id":2,"name":"12","sale_info":{"phone":1351}},
{"id":3,"name":"2","sale_info":{"phone":0135}},
{"id":4,"name":"002","sale_info":{"phone":01351}},
],
"msg": null
}
測試用例如下,我們針對不同的元數(shù)據(jù)進(jìn)行了斷言膳沽,分別是門店和門店的相關(guān)信息。
import unittest
def get_value_by_jsonpath(value,path):
"""通過jsonpath獲取數(shù)據(jù)"""
def get_api():
"""請求接口"""
class TestStoreList(unittest.TestCase):
def setUp(self):
pass
def template(self,diff_param:dict,jsonpath="$."):
url = ''
body = {"name":"","phone":""}
body.update(diff_param)
resp = get_api(url,json=body)
assert 200 == resp.status_code
if '$.' == jsonpath:
return resp.json()
return get_value_by_jsonpath(resp.json(),jsonpath)
def sql_select(self,sql):
"""數(shù)據(jù)庫查詢"""
def test_name_like(self):
"""斷言門店數(shù)據(jù)"""
names = self.template({"name":"2"},'$.data.*.name')
sql = ""
select_names = self.sql_select(sql)
assert names == select_names
def test_phone_like(self):
"""斷言門店關(guān)聯(lián)業(yè)務(wù)員數(shù)據(jù)"""
phones = self.template({"phone":135},'$.data.*.phone')
sql = ""
select_phones = self.sql_select(sql)
assert phones == select_phones
def teardown(self):
pass
下一個(gè)版本中泼差,業(yè)務(wù)員和門店從一對一變?yōu)橐粚Χ嗟那闆r我們只需修改門店相關(guān)的用例即可贵少。
自動(dòng)化的環(huán)境問題
被測環(huán)境如何保證數(shù)據(jù)穩(wěn)定性,這一問題其實(shí)是測試用例的問題堆缘,只不過在手工測試中滔灶,我們主動(dòng)避障了,造不了A數(shù)據(jù)吼肥,我們?nèi)ピ霣數(shù)據(jù)了录平。在自動(dòng)化測試中,由于程序沒有我們?nèi)四敲粗悄茏褐澹赃@個(gè)問題十分明顯斗这。但是這一問題往往是運(yùn)維的問題,不過我們可以假設(shè)我們擁有一個(gè)和線上數(shù)據(jù)庫結(jié)構(gòu)一致的數(shù)據(jù)庫啤斗,里面沒有數(shù)據(jù)表箭。我們通過setUp和teardown保證不同用例間互不干擾、和可重復(fù)執(zhí)行钮莲,而setUpClass和tearDownClass則是用于我們有一個(gè)基礎(chǔ)數(shù)據(jù)來保證環(huán)境已經(jīng)滿足一定的前提條件免钻,全部用例完成后保證環(huán)境如測試前一致,它們還是保證我們的用例互不干擾崔拥,只是維度更高极舔。
import unittest
class TestStoreList(unittest.TestCase):
@classmethod
def setUpClass(cls):
"""增加一些基礎(chǔ)數(shù)據(jù)"""
@classmethod
def tearDownClass(cls):
"""清理新增的基礎(chǔ)數(shù)據(jù),還原環(huán)境"""
def setUp(self):
"""不同用例去新增不同的測試數(shù)據(jù)"""
def test_name_like(self):
"""斷言門店數(shù)據(jù)"""
def test_phone_like(self):
"""斷言門店關(guān)聯(lián)業(yè)務(wù)員數(shù)據(jù)"""
def teardown(self):
"""不同用例去清理不同的測試數(shù)據(jù),還原環(huán)境"""
上面的討論链瓦,需要一些運(yùn)維技巧拆魏,包括如何部署數(shù)據(jù)庫、中間件、服務(wù)器渤刃、等等的一些東西拥峦。如果系統(tǒng)架構(gòu)過于復(fù)雜、硬件資源緊張溪掀、運(yùn)維能力不足事镣,可能我們不能奢望我們擁有一個(gè)可控的環(huán)境。你大概只能編寫更加復(fù)雜斷言來保證你健壯揪胃,維護(hù)成本會(huì)響應(yīng)提高璃哟。
自動(dòng)化的維護(hù)成本
從上面的講述中,我們的維護(hù)成中由維護(hù)環(huán)境和維護(hù)用例組成喊递,在用例維護(hù)中随闪,用例邏輯維護(hù)和數(shù)據(jù)維護(hù),是相互影響的(請不要將測試步驟和測試數(shù)據(jù)分離當(dāng)成是測試數(shù)據(jù)和用例分離骚勘,在自動(dòng)化測試用例中測試數(shù)據(jù)和用例是一起的) 铐伴。我們應(yīng)該更加傾向于低邏輯維護(hù)、高數(shù)據(jù)維護(hù)的這樣一種模式俏讹。高邏輯會(huì)帶來一些邏輯錯(cuò)誤当宴,從而導(dǎo)致我們使用bug來測試bug。而我們可以用過execl泽疆,數(shù)據(jù)庫户矢,造數(shù)平臺(tái)來提高我們維護(hù)數(shù)據(jù)的效率。
總結(jié)
自動(dòng)化測試并沒有和手工有巨大的不同殉疼,它的優(yōu)勢在于可以多次執(zhí)行和大量執(zhí)行(批處理是計(jì)算機(jī)相對人的優(yōu)勢)梯浪,執(zhí)行次數(shù)越多,節(jié)約工時(shí)越多瓢娜。
對于接口類的自動(dòng)化測試基本上都可以替代手工測試挂洛。對于UI測試,AI測試眠砾,嵌入式程序測試等需要人為主觀判斷的測試虏劲,自動(dòng)化的覆蓋率相對有限。自動(dòng)化測試不能完全替代手工測試褒颈。
一個(gè)良好的測試環(huán)境伙单,有利于自動(dòng)化測試的開展。
合理的編寫自動(dòng)化測試用例哈肖,一份低維護(hù)成本的測試用例,是每個(gè)測試人員都需要的念秧。