介面測試進階之數據模板
本文關鍵字「數據模板」
大家好久不見了。今天的文章將介紹jinja2模板在介面測試數據上的應用。
這幾個月我在想,進階系列要怎麼寫。
畢竟很多情況下,我覺得寫技術文章和做培訓一樣,都會有兩個結果:
1.是需要這些知識的人看不懂。
2.是看得懂的人不需要這些知識。
而我的進階系列是希望寫給即將跨入測試開發這條路的人和剛進入這條路還沒有形成成自己的知識體系的人。當初我剛開始轉型的時候就很希望有這種資料來引導一下我。。。如果說之前的基礎系列是給想轉型測試開發的人打打基礎,那進階系列就是真正走出這一步時最需要的東西。按照我的觀點,真正走上測試開發之路的標誌應該是你能夠:
1.獨立學習一個新工具或庫。
2.獨立完成一個測試框架或工具。
3.獨立集成一個持續集成測試系統。
如果連一個框架也寫不出來,就別說測試開發了,寫框架之類的是很簡單的,難的是寫得好。
總之,文章限於篇幅,只能說是寫給有足夠自學能力的人看的。之後可能會做一些live或視頻之類來提供給更希望在有人引導下學習的人。
不管怎麼樣,進階我想從介面測試開始寫起。介面測試的需求還是挺大的。而且你能看到各大測試論壇或討論區里無數的人在寫自己的介面測試框架。但是,那些開源出來的框架大都有很大的問題,比如最嚴重的問題就是:過於複雜。你去下載一個的話,你會發現你壓根搞不懂他們寫這麼多代碼是要做什麼。而且你會發現很多人喜歡把別人寫過的東西用自己的方式再寫一遍。當然他在寫的時候提高了一定的開發能力,但對於讀者來說,那就是災難。
我寫代碼喜歡簡單,我對於測試開發的第一要求就是簡單。
喜歡直接看代碼的人可以直接看代碼,代碼在這裡,希望你喜歡:
https://github.com/zhangting85/SimpleApiTest
今天討論的問題,我用了15行代碼來實現一個解決方案。
這個問題就是,怎樣保存介面測試的測試數據。
很多測試框架選擇把數據放在:Excel里,CSV里,YAML里,源代碼里。但這些都不是我想要的,Excel太笨重,CSV很土,YAML里太難調,源代碼里太難讀。
歸根結底,要麼不靈活,要麼很難讀。
學習前提
這裡,本篇假設你具備一定的python基礎,已經讀完我專欄里的這篇:
測試人員如何學習python(發送關鍵字「介面基礎」可以收到本文)
更重要的是讀完或者至少瀏覽過這篇里推薦的三本python書和教程。
然後,還有大致理解這篇里提到的數據驅動概念
從數據驅動到各種驅動(發送關鍵字「數據驅動」可以收到本文)
另外,了解介面測試是怎麼回事兒:
介面測試基礎(發送關鍵字「介面基礎」可以收到本文)
另外,搭建環境的問題希望在看完這篇之後你已經能自己找資料解決了
如何搭環境(發送關鍵字「環境」可以收到本文)
最後,我這裡用的是python的pytest框架來組織和運行測試。
這裡假設大家對pytest有一定了解。
介面測試的數據問題
這個問題也算是由來已久了。
現在很多各種各樣的方法來解決:
寫Excel里,CSV里,YAML里,源代碼里,XML里,還有放在資料庫里,放在各種各樣的文件里。我想說的是,你在真正做一個工具時,這些都可以。關鍵是能應付你的項目需求。
這裡我給出的是一個示例,也就是我怎樣寫一個測試框架的數據管理部分。當然,這個示例還是比較精緻的。至少我再也不會選擇把數據放到上面提過的那些東西里去。。。
那麼我把數據放在哪裡?json文件里。
先來看需求,假如有這麼一個介面,
你要在HTTP請求的BODY要發送{"username":"user1","password":"password1"}這樣一個json對象來表示你登錄時使用的用戶名密碼。
那麼直接把數據寫在代碼里的話,差不多就是這樣:
import pytestimport requestsimport jsondef test_login(): url = "http://localhost:8000/login" data = json.loads({"username":"user1","password":"passowrd1"}) r = requests.post(url=url, data=data) assert r.status_code == 200if __name__ == "__main__": pytest.main()
接下來的問題是很常見的數據驅動問題,如果你要測5個用戶的登錄。
他們的用戶名密碼依次是user1/password1,user2/password2,...user5/password5.
那麼直接把數據寫在代碼里的話,大概就是這樣:
注意這裡我把http response code也寫在測試數據里了,雖然他是預期結果。但預期結果也是數據的一部分。這個test方法里其實可以測一些返回值不是200的數據。
import pytestimport requestsimport jsontestdata = [ ("user1", "password1", 200), ("user2", "password2", 200), ("user3", "password3", 200), ("user4", "password4", 200), ("user5", "password5", 200)]@pytest.mark.parametrize("user,password,expected_response_code",
testdata)def test_login(user,password,expected_response_code): url = "http://localhost:8000/login" data = json.loads({"username":"{}".format(user),"password":
"{}".format(password)}) r = requests.post(url=url, data=data) assert r.status_code == expected_response_codeif __name__ == "__main__": pytest.main()
到這裡為止,data = xxxx 這一行已經有點複雜了。
然後,一個真實請求的json里可能包含不止這麼兩個參數。比如github的登錄
可以想像如果全寫在代碼里,你的測試用例文件會變得多麼難讀。。。
舉個例子,github api里create repo可以包含14個參數,他給出的例子里用了7個參數,
長這樣:
{ "name": "Hello-World", "description": "This is your first repository", "homepage": "https://github.com", "private": false, "has_issues": true, "has_projects": true, "has_wiki": true}
如果這14個參數里有些不變,有些你要測也就是會變,你可以試一下直接寫在代碼里會形成怎樣的一個測試用例文件。。介面的描述文檔在這裡https://developer.github.com/v3/repos/
可能到這裡,大家都會想把數據驅動更進一步,把數據或者至少是一部分數據放到代碼外吧。這就是那些excel,xml,yaml,各種數據源出現的原因了。這些都能用,也都能解決一定的問題。但是,就是不靈活。
然後這是一個網友遇到的實際問題:他測的介面要求當參數A的值為true時,才向伺服器發送參數B,C和D,其他情況向伺服器發送參數E和F。
我可以說上述各種數據源都做不到這種功能。你要麼寫兩份數據,要麼只能在代碼里做分支。但這些,都在增加測試的複雜度,而我不想要複雜。
ok,現在我要解決這個問題。
測試數據中引入模板概念
模板其實對於python的web開發者來說是很熟悉的東西。Django,flask,各種web開發框架里,前端部分都在用模板解決問題。
通俗的說,模板就是在html里插入了一些特殊符號,讓HTML里可以拿到伺服器後台傳上來的變數,更進一步可以根據這些變數的值來顯示不同內容。
比如後台發現你是免費用戶,就給你顯示一堆廣告,發現你是付費用戶,這些廣告就不顯示了。
那麼,我就想,對於測試數據,可不可以也這麼搞?
顯然是可以的
數據我劃分成可變數據和不變數據兩個部分。
不變的就放在json文件里,可變的就放在測試用例里。
比如一個HTTP請求要發送{"username":"xxxx","password":"xxxx"}這個數據里除了xxxx以外,全是不變部分。至少不會經常不停的變。那麼不變部分直接寫死在json文件里。而可變部分在json文件里用模板語法代替,這個json文件看上會是這樣的:{"username":{},"password":{}}這裡{}和{}就是可變部分。不直接寫死他們的值。而是,用模板的變數代替。這個變數就是{},這個變數有兩個屬性,一個username一個password,之後我們再在測試用例里把這個變數傳遞給模板,就可以渲染出真正的測試數據。也就是說,這個可變部分,真正寫,我寫在測試用例的代碼裡面。
源代碼說好了一共只有15行:
讀取和渲染模板的類
給pytest用的fixture
在這裡我的設計思想是這樣的,針對單個介面的測試(我把介面測試分為針對單個介面的測試和針對用戶場景的端到端測試):
一個測試方法,對應一個json文件。
比如"test_user_login"這個方法,對應"test_user_login.json"這個文件,根據測試方法名去識別對應的json文件名。這裡的json模板具有jinja2模板的所有功能,也就是說,可以根據後台傳入的數據,來做if判斷。可以實現用同一份數據,在某個參數值為TRUE和FALSE時傳不同的數據給伺服器。這裡的所謂後台,其實就是指我們在測試用例里傳給json模板的數據值。這部分數據也是我前面說的可變數據。
好,關於if else的具體例子我就略了,相信讀者理解了模板和相關的庫後可以很容易寫出來。我會在後期慢慢把例子加在我這個github的samples目錄里。現在已經加了最基本的測試數據模板渲染例子。
另外我的庫里使用hug來編寫測試用的rest api,代碼極其簡單,強烈推薦這個庫給大家。
比如這樣,就實現了一個get的api和一個post的api,每個介面3行代碼,畢竟搞python就是要搞一些簡單的東西來用嘛。
差不多就這些了。祝大家新年快樂。
TAG:全球大搜羅 |