Httprunner2 實戰踩坑記錄

語言: CN / TW / HK

\\\\\

基於Httprunner(2.5.7版本)的介面自動化,在我們專案上持續運用、打磨了近2年的時間,把使用過程中的一些心得/遇到的問題及對應的解決方案/思路,做一個介紹(目前我們專案case規模2400+,執行時長1分鐘左右,成功率99.99%,見下圖)。

效率是不是很不錯?問題主要包含如下幾類:

錯誤提示

exception stage: parse tests

1. 問題描述

這個錯誤是使用httprunner過程中經常遇到的,出現這個錯誤的場景非常多,都是對yaml檔案解析出現了錯誤。

2. 產生問題的可能原因:

①.  yaml中使用了未定義的變數。

②.  在使用變數時未使用符號$。

③.  在呼叫debugtalk.py中的方法時缺少{}或者()。

④.  格式問題,相同的層級的變數,縮排不同。

⑤.  引用的引數定義錯誤

在解析yaml檔案中通過符號$引用的變數時,在原始檔parser.py中,會對變數進行校驗,只取以$開頭+字母數字下劃線的部分。

如下,在yaml檔案中引用了一個變數$title-tup

在對這個檔案進行解析時,會對名稱 $title-tup進行正則校驗,校驗完後變數就變成了$title,如下圖所示,而實際檔案中是找不到這個變數$title對應的值的,所以就會出現錯誤。

錯誤提示

ResponseObject does not have attribute: parsed_body

1. 問題描述:

如果在yaml檔案中使用了jsonpath 提取器提取要校驗的內容,此時有可能會報上述錯誤

2. 產生問題的原因:

ResponseObject 找不到 parsed_body 屬性,這是框架本身的一個小BUG,但是這個框架作者一直沒去維護更新。

3. 解決方案:

找到httprunner原始碼response.py檔案, 將第62行self.parsed_body()改成self.json。

斷言沒有執行

也沒有報錯

1. 問題描述:

當你的介面返回值是一個集合或者list等,需要判斷結果中包含某些值時,可能會在yaml中寫多個contains斷言,這些斷言的方法相同,要校驗的值check也相同,只有期望值expect不同,此情況下你會發現這樣的校驗在報告中只記錄了最後一條斷言的結果,如下圖所示:

執行結果:

2. 產生問題原因:

由於在api檔案中,可能會定義一些預設的斷言,在testcases檔案中引用api中的yaml檔案時,可能會存在與api檔案中相同的響應的斷言,為了使得2檔案對相同部分的斷言不重複,在httprunner的原始碼parser.py檔案中,對斷言資訊進行解析時,會將斷言的方法以及check資訊合併到一起作為一個key,expect作為值賦給一個字典,迴圈所有的斷言,當遇到第一個contains時,會在字典中新增這個key,並賦值為$fwed1,當迴圈到第二個contains斷言時,字典中有相同的key了,就會把字典中的值修改為$fwed2,這樣就導致在實際執行時,第一個contains斷言沒有執行,只執行了第二個contains斷言。原始碼如下:

3. 解決方案:

①. 如果check可以取到更細粒度的值,那麼直接取到要斷言的值,保證斷言的方法以及check都不重複。

②. 如果要check的值是無序的,無法精確取到下一層級的值,可以在debugtalk.py中自定義一個新的方法,對集合進行整體進行校驗。

錯誤提示

Failed to extract attribute from response!

遇到這個錯誤,多數是以下兩種原因:

1. 介面返回的資料跟期望的不一樣,你要提取的變數不存在,此時要檢查一下是不是接口出錯了,或者提取資訊寫錯了。

2.斷言第一個引數裡不包含從介面響應中提取的值。

①. 問題描述:

如下圖所示,斷言方法check_sql中第一個引數中不包含從響應中提取的值,就會出錯。

②. 解決方案:

修改斷言的第一個引數值,引數中包含從響應中提取的值

自定義方法

形參問題

1. 自定義方法作為斷言方法,形參格式應該跟內建的斷言方法保持一致:

①. 形參個數要求是2個

②. 第一個形參是要check的值,第二個是expect值,二者不可以錯位。

2. 通過$去呼叫自定義函式時,如果傳入的引數是字串,這個引數不可以用引號引起來。

①.  問題描述:

如下圖所示,自定義函式update_redis,函式形參是一個字串型別,所以在yaml檔案中傳值時,傳入了一個key,型別是字串型別,用雙引號引起來了。實際執行這條用例時,這個方法就會被忽略掉,不執行。

②. 產生問題原因:

當解析到這個方法時,在parser.py檔案中會通過正則表示式進行校驗來判斷此處是一個函式還是一個引數,如下圖,判斷是否是一個函式,規則如下:

從上述匹配規則可以看出來,匹配的是以${開頭,}結尾的,中間可以包含數字、字母、下劃線、$、-、.、= ,當用例中函式引數加了引號就會被標記為非function型別,實際執行時就不會執行函式呼叫了。

③. 解決方案:

方案一:直接寫變數,不用引號,函式呼叫時,就是字串型別。

方案二:定義一個變數,引用此變數。

多執行緒實現

當case量很大時(如千級別及以上規模),原有單程序的方式,case執行時長通常是難以接受的。為此,研究原始碼發現,只需修改原始碼根目錄中的api.py檔案中的_run_suite方法,用如下程式碼替換:

說明:

1. 其中max_workers代表執行緒池數量

2. 需要匯入如下包

from concurrent.futures.thread import ThreadPoolExecutor
from concurrent import futures

3. 使用多執行緒的話,建議一個介面的用例放在同一個yml檔案中,介面與介面之間用例要解耦

提高報告的開啟效率

當case量很大時,如果報告中展示全量case執行結果的話,報告本身開啟也會非常慢,並且失敗的case查詢也很費勁,實戰中建議大家報告中只展示失敗的CASE(通常應該會非常少)。較為簡單的修改方法是,copy一份原始碼目錄中 httprunner/report/template.html (例如命名為template_fail.html),增加成功case的過濾功能,如下圖:

說明:

1. 上圖只截取了開始標籤,結尾註意標籤的閉合

2. 用例執行的時候加上

—report-template=template_fail.html(建議使用絕對路徑)引數,不加的話,還是預設展示全量case

Httprunner的簡介中說到,HttpRunner 是一款面向 HTTP(S) 協議的通用測試框架,只需編寫維護一份YAML/JSON指令碼,即可實現自動化測試,但是當你真正使用時,會發現僅僅會用其定義好的關鍵字、斷言方法並不能滿足我們的需求,且會遇到各種各樣的問題,當你遇到百度不出來,各種嘗試也找不到問題原因時,可以通過debug原始碼來找到問題的答案。