接口測試是面試測試崗位基本都會問到的問題,但是對於一些剛做測試的小伙伴可能並不是很熟悉,也有可能了解接口測試,但是完全不知道接口自動化怎么做。下面我們大概介紹一下。 首先我們需要知道接口自動化測試的目的是為了節約手工測試接口的時間或者減少不必要的重復工作,或者為了監控線上接口是否運行正常等情況的發生。在我們日常的接口測試工作中大多數小伙伴可能都是用一個接口工具:fiddler、postman、jmeter、soapui等等來進行一個簡單的接口測試,當然工具的選擇這個看大家的喜好,但是我們都會發現一個特點,這些工具如果僅僅是工具的使用我們都不能夠根據自己的業務等特殊情況進行修改,具有一定的局限性,並且一些只能一次測試一個,最最最關鍵的是這個無法體現我們的逼格,是不是有種感覺就是沒辦法體現我們自己的價值,如果面試使用這些好像無法要出高工資。那下面我們就從這簡單的第一步開始,讓我們從簡單的提高自己開始。 如果使用一門語言來做接口測試,我會毫不猶豫的選擇python,他的高效不是一般的。我們先看下面使用python測試慕課網登陸的一個簡單例子:
import requests
import json
url = "http://m.imooc.com/passport/user/login"
data = {"username":"185xxxxxx","password":"111111","verify":"", "referer":"http://m.imooc.com"}
res = requests.post(url, data).json() print res
看到上面的代碼有點像樣子了,如果在實際項目中我們要測試一個登陸接口那么我們只需要將上面的代碼拿過來,然后將我們的url更換一下,然后將用戶名和密碼信息換一下就ok,但是我們會發現一個問題,這個代碼看着沒有復用性,而且實際存在的價值並不是很高,所以我們可以將上面的代碼進行一個簡單的封裝,把封裝成一個函數,我們需要傳入url、data就可以了,然后我們每次需要測試接口時調用這個函數就能夠完成我們的測試,結果如下:
import requests import json def post_main(url=None,data=None): #參數必須按照url、data順序傳入 res = requests.post(url=url,data=data).json() return res
這樣看起來是不是覺得順手一點點了呢?此時我們的代碼確實沒什么問題了,但是看着好像少了點東西,不知道你是否覺得?因為在我們常見的接口中不止是有post類型的接口,我們還有get類型的接口,那么我們是不是要根據不同類型的接口做不同的封裝呢?那我們做get的接口是如何進行測試的呢?看下面代碼:
import requests import json res = requests.get(url).json() print res
看見上面的代碼和之前我們寫的代碼是不是發現了一些區別,其實在python中使用requests庫進行接口時我們唯一的區別就是實用post、get兩個函數,他們就分別對應了測試post類型和get類型的接口,同樣的我們將get接口的函數進行一個簡單的封裝,那么就成了下面的樣子:
import requests def get_main(url=None,data=None): res = None res = requests.get(url=url,data=data).json() return res
通過上面的代碼和之前封裝的代碼我們是不是就簡單的把我們常見的post和get兩個類型的接口進行了一個封裝,我們如果下次需要測試接口只需要去調用這個就可以了呢?但是我們發現一個問題如果我們需要調用,每次還需要知道我們接口類型,然后來調用不同的方法,這樣是不是有點麻煩呢?那我們應該怎么去簡化整個過程呢?我們是不是可以將我們這倆函數封裝在一起然后有一個主要的入口,然后其他的地方來進行調用?答案肯定是可以的,我們只需要封裝一個主函數就行,這個函數主要功能是做什么呢?他主要是用來辨別你接口是什么類型的,然后去調用不同類型的接口。那就變成了下面這樣:
import requests def post_main(url,data): #參數必須按照url、data、header順序傳入 res = None res = requests.post(url=url,data=data).json() return res #get接口主入口 def get_main(url,data): res = None res = requests.get(url=url,data=data).json() return res #調用postman def run_main(method,url=None,data=None): res = None if method == 'Post': res = post_main(url, data) else: res = get_main(url, data) return res
看到這里是不是有那么點明白的感覺?其實我們只需要將我們的兩個函數封裝起來就ok了,但是其實看到這里我們覺得還是少點什么?能不能把整個封裝成一個類呢?答案肯定是可以的,看下面:
#-*- coding: utf-8 -*- #author: mushishi #Date:2017年11月7日 import requests import json class RunMethod: #傳入參數 url data header def post_main(self,url,data): #參數必須按照url、data順序傳入 res = None res = requests.post(url=url,data=data).json() return res #get接口主入口 def get_main(self,url,data): res = None res = requests.get(url=url,data=data).json() return res #調用postman def run_main(self,method,url=None,data=None): res = None if method == 'Post': res = self.post_main(url, data) else: res = self.get_main(url, data) return res if __name__=='__main__': data = {"username":"185xxxxxx","password":"111111","verify":"", "referer":"http://m.imooc.com"} t = RunMethod() print t.run_main('Post','http://m.imooc.com/passport/user/login',data)
這個整段代碼是不是就變成了我們剛開始測試很low的那代碼的封裝呢?對的,但是有沒有思考過一個問題,這樣看起來雖然有點樣子了,但是是不是還缺少點什么呢?我們能不能夠按照一條case一條case那樣執行呢?好比我登陸時傳入不同的用戶信息,然后返回不同結果,有不同的斷言呢?肯定可以,我們這里簡單引入一個unittest的框架,具體看下面:
#-*- coding: utf-8 -*- #author: mushishi #Date:2017年11月7日 import unittest class TestDemo(unittest.TestCase): def test_one(self): #這是第一條case print "這是第一條case" def test_two(self): #這是第二條case print "這是第二條case" if __name__ == '__main__': suite = unittest.TestSuite() suite.addTest(TestDemo('test_one')) suite.addTest(TestDemo('test_two')) unittest.TextTestRunner().run(suite)
這里 我們能夠看到一個簡單的unittest的簡單架子,首先我們是引入了一個unittest包,然后創建類的時候繼承了這個unittest.TestCase這個方法,在下面我們只需要編寫我們的case就可以了,在程序的執行入口,我們將兩個case添加到一個組件中,然后去運行這個組件就ok了。雖然架子有了,我們要怎么把我們的requests的基礎模版和我們的unittest結合起來呢?其實我們只需要在我們的unittest類開始將我們的RunMethod類引入然后使用就好,然后結果變成了下面這個樣子:
#-*- coding: utf-8 -*- #author: mushishi #Date:2017年11月7日 import unittest from base.runmethod import RunMethod class TestDemo(unittest.TestCase): @classmethod def setUpClass(cls): cls.run_method = RunMethod() def test_one(self): data = {"username":"185xxxxxx","password":"111111","verify":"", "referer":"http://m.imooc.com"} res = self.run_method.run_main('Post','http://m.imooc.com/passport/user/login',data) print res def test_two(self): data = {"username":"185xxxxx","password":"111111","verify":"", "referer":"http://m.imooc.com"} res = self.run_method.run_main('Post','http://m.imooc.com/passport/user/login',data) print res if __name__ == '__main__': suite = unittest.TestSuite() suite.addTest(TestDemo('test_one')) suite.addTest(TestDemo('test_two')) unittest.TextTestRunner().run(suite)
看到 這里好像有那么點意思了,但是美中不足的是好像我們還沒有測試報告那我們需要如何去生成一個測試報告呢?這里我們就需要運用我另外一個東西HTMLTestRunner.py,這個文件可以在網上下載,我們這里可以直接使用,同樣的我們只需要將HTMLTestRunner這個引入就好,接着上面的代碼我們往下看:
import HTMLTestRunner import unittest from base.runmethod import RunMethod class TestDemo(unittest.TestCase): @classmethod def setUpClass(cls): cls.run_method = RunMethod() def test_one(self): data = {"username":"185xxxxxx","password":"111111","verify":"", "referer":"http://m.imooc.com"} res = self.run_method.run_main('Post','http://m.imooc.com/passport/user/login',data) print res def test_two(self): data = {"username":"185xxxxx","password":"111111","verify":"", "referer":"http://m.imooc.com"} res = self.run_method.run_main('Post','http://m.imooc.com/passport/user/login',data) print res if __name__ == '__main__': suite = unittest.TestSuite() suite.addTest(TestDemo('test_one')) suite.addTest(TestDemo('test_two')) #定義報告路徑 filename = 'test.html' #定義報告文件權限,wb,表示有讀寫權限 fp = file(filename,'wb') runner = HTMLTestRunner.HTMLTestRunner( stream = fp, title ='MushishiTest', description = '測試報告') #執行測試 runner.run(suite) #關閉文件,否則會無法生成文件 fp.close()
上面看着沒什么變化,這里我們只是將unittest創建的測試組件放在了HTMLTestRunner中去運行,這樣運行后就有我們的結果了呢?
思考:這就真的達到了我們接口的自動化了么?答案肯定是否定的。那具體怎么實現呢?
作者: Mushishi_Xu
鏈接:http://www.imooc.com/article/21104
來源:慕課網
本文原創發布於慕課網 ,轉載請注明出處,謝謝合作!