Python接口自動(dòng)化測(cè)試的實(shí)現(xiàn)
1)環(huán)境準(zhǔn)備:
接口測(cè)試的方式有很多,比如可以用工具(jmeter,postman)之類,也可以自己寫代碼進(jìn)行接口測(cè)試,工具的使用相對(duì)來(lái)說(shuō)都比較簡(jiǎn)單,重點(diǎn)是要搞清楚項(xiàng)目接口的協(xié)議是什么,然后有針對(duì)性的進(jìn)行選擇,甚至當(dāng)工具不太適合項(xiàng)目時(shí)需要自己進(jìn)行開發(fā)。
在我們項(xiàng)目的初期,我們采用的是jmeter進(jìn)行接口測(cè)試,當(dāng)時(shí)覺得這個(gè)工具上手簡(jiǎn)單,團(tuán)隊(duì)成員學(xué)習(xí)成本低,并且接口測(cè)試的腳本稍微調(diào)整一下還可以用來(lái)做性能測(cè)試。
不過(guò)隨著項(xiàng)目規(guī)模、團(tuán)隊(duì)人數(shù)的不斷增長(zhǎng),漸漸的這個(gè)工具有適應(yīng)不了當(dāng)前項(xiàng)目的需求了,為此我們項(xiàng)目也重新開發(fā)了相關(guān)接口自動(dòng)化的平臺(tái)。但是,但是。。??赡苁俏易尨蠹抑卸咎?,現(xiàn)在很多同學(xué)一提到接口測(cè)試關(guān)聯(lián)到j(luò)meter,為此,我深深感到不安。畢竟jmeter只是個(gè)工具,換個(gè)項(xiàng)目換個(gè)協(xié)議你是否還能玩轉(zhuǎn)接口測(cè)試呢?session和cookie有什么區(qū)別?工具又是怎么實(shí)現(xiàn)的呢?
比如session如何保存,接口依賴如何處理,case如何管理及執(zhí)行順序,測(cè)試數(shù)據(jù)如何管理等等題,這個(gè)過(guò)程也有助于我們更加深刻的理解接口測(cè)試和http協(xié)議。
本文主要采用python語(yǔ)言,python中http協(xié)議接口相關(guān)的庫(kù)有urllib,urllib2以及reqeusts庫(kù),這其中reqeusts庫(kù)用來(lái)起來(lái)最方便,因此我也主要采用requests庫(kù)來(lái)做http協(xié)議的接口測(cè)試。首先來(lái)看下需要哪些環(huán)境信息:
一、安裝python
mac下自帶安裝了python,這個(gè)不多說(shuō)了。
二、安裝虛擬環(huán)境:
我們?cè)谝慌_(tái)機(jī)器上可以安裝多個(gè)python版本,為了使每個(gè)版本的環(huán)境相互不受干擾,可以安裝虛擬環(huán)境,安裝方法如下:
1、安裝virtualenv:pip install virtualenv
2、新建名為venv的虛擬環(huán)境:virtualenv venv
3、進(jìn)入新環(huán)境:source venv/bin/activate
4、退出:deactivate
三、安裝requests庫(kù):
>>>pip install requests
ps:用python做http協(xié)議的接口測(cè)試會(huì)用到這個(gè)庫(kù)。
四、http測(cè)試工具:
一個(gè)使用 Python + Flask 編寫的 HTTP 請(qǐng)求和響應(yīng)服務(wù),該服務(wù)主要用于測(cè)試 HTTP 庫(kù)。后續(xù)測(cè)試我們都基于這個(gè)網(wǎng)站。
五、在本地搭建httpbin:
考慮到測(cè)試時(shí)要不斷訪問 httpbin 網(wǎng)站,請(qǐng)求過(guò)多擔(dān)心被拉到黑名單,我們自己在本志搭建一套httpbin服務(wù)。
1、安裝:pip install gunicorn
2、安裝:pip install httpbin
3、啟動(dòng):gunicorn httpbin:app
至此,環(huán)境搭建已經(jīng)完畢,可以開始玩了~
(2)requests.get()
環(huán)境搭建好后,接下來(lái)我們先來(lái)了解一下requests的一些簡(jiǎn)單使用,主要包括:
requests常用請(qǐng)求方法使用,包括:get,postrequests庫(kù)中的Session、Cookie的使用其它高級(jí)部分:認(rèn)證、代理、證書驗(yàn)證、超時(shí)配置、錯(cuò)誤異常處理等。
本節(jié)首先來(lái)了解一下requests庫(kù)中如何發(fā)送get請(qǐng)求:
一、看下方法定義:
1、到官方文檔去了下requests.get()方法的定義,如下:
2、點(diǎn)擊右上角的【source】,看一下它的源碼如下:
看到最后一行return,get方法最后是通過(guò)調(diào)用 requests.request方法實(shí)現(xiàn)的,其實(shí)在其它的請(qǐng)求方法如post,put,head,delete等方法都是調(diào)用的request方法,然后把請(qǐng)求方法的類型傳遞給request方法第一個(gè)參數(shù)。
3、HTTP協(xié)議是一個(gè)基于請(qǐng)求/響應(yīng)模式的、無(wú)狀態(tài)的,應(yīng)用層協(xié)議。既然有請(qǐng)求,就有響應(yīng),來(lái)看下resquest中常用的響應(yīng)信息:
二、get方法簡(jiǎn)單使用:
1、不帶參數(shù)的get:
# -*- coding:utf-8 -*- #不帶參數(shù)的get import requests import json host = "http://httpbin.org/" endpoint = "get" url = ''.join([host,endpoint]) r = requests.get(url) #response = r.json() print type(r.text) print (eval(r.text))
輸出:
{ 'origin': '183.14.133.88', 'headers': { 'Connection': 'close', 'Host': 'httpbin.org', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'User-Agent': 'python-requests/2.18.1' }, 'args': { }, 'url': 'http: //httpbin.org/get' }
2、 帶參數(shù)的get:
# -*- coding:utf-8 -*- #帶參數(shù)的get import requests import json host = "http://httpbin.org/" endpoint = "get" url = ''.join([host,endpoint]) params = {"show_env":"1"} r = requests.get(url=url,params=params) print r.url
輸出:
http://httpbin.org/get?show_env=1 { 'origin': '183.14.133.88', 'headers': { 'X-Request-Id': 'ebe922b4-c463-4fe9-9faf-49748d682fd7', 'Accept-Encoding': 'gzip, deflate', 'X-Forwarded-Port': '80', 'Total-Route-Time': '0', 'Connection': 'close', 'Connect-Time': '0', 'Via': '1.1vegur', 'X-Forwarded-For': '183.14.133.88', 'Accept': '*/*', 'User-Agent': 'python-requests/2.18.1', 'X-Request-Start': '1504755961007', 'Host': 'httpbin.org', 'X-Forwarded-Proto': 'http' }, 'args': { 'show_env': '1' }, 'url': 'http: //httpbin.org/get?show_env=1' }
3、帶header的get:
# -*- coding:utf-8 -*- import requests import json host = "http://httpbin.org/" endpoint = "get" url = ''.join([host,endpoint]) headers = {"User-Agent":"test request headers"} r = requests.get(url) r = requests.get(url,headers=headers) #response = r.json() print (eval(r.text))['headers']['User-Agent']
輸出:
test request headers
4、同時(shí)帶參數(shù)和header:
# -*- coding:utf-8 -*- import requests import json host = "http://httpbin.org/" endpoint = "get" url = ''.join([host,endpoint]) headers = {"User-Agent":"test request headers"} params = {"show_env":"1"} r = requests.get(url) r = requests.get(url,headers=headers,params=params) #response = r.json() print (eval(r.text))['headers']['User-Agent'] print r.url
輸出:
test request headers http://httpbin.org/get?show_env=1
(3)requests.post()
一、方法定義
二、post方法簡(jiǎn)單使用
1、帶數(shù)據(jù)的post
2、帶header的post
3、帶json的post
4、帶參數(shù)的post
5、普通文件上傳
6、定制化文件上傳
7、多文件上傳
一、方法定義:
1、到官方文檔去了下requests.post()方法的定義,如下:
2、源碼:
3、常用返回信息:
二、post方法簡(jiǎn)單使用:
1、帶數(shù)據(jù)的post:
# -*- coding:utf-8 -*- import requests import json host = "http://httpbin.org/" endpoint = "post" url = ''.join([host,endpoint]) data = {'key1':'value1','key2':'value2'} r = requests.post(url,data=data) #response = r.json() print (r.text)
輸出:
{ "args": {}, "data": "", "files": {}, "form": { "key1": "value1", "key2": "value2" }, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Content-Length": "23", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", "User-Agent": "python-requests/2.18.1" }, "json": null, "origin": "183.14.133.88", "url": "http://httpbin.org/post" }
2、帶header的post:
# -*- coding:utf-8 -*- import requests import json host = "http://httpbin.org/" endpoint = "post" url = ''.join([host,endpoint]) headers = {"User-Agent":"test request headers"} # r = requests.post(url) r = requests.post(url,headers=headers) #response = r.json()
輸出:
{ "args": {}, "data": "", "files": {}, "form": {}, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Content-Length": "0", "Host": "httpbin.org", "User-Agent": "test request headers" }, "json": null, "origin": "183.14.133.88", "url": "http://httpbin.org/post" }
3、帶json的post:
# -*- coding:utf-8 -*- import requests import json host = "http://httpbin.org/" endpoint = "post" url = ''.join([host,endpoint]) data = { "sites": [ { "name":"test" , "url":"www.test.com" }, { "name":"google" , "url":"www.google.com" }, { "name":"weibo" , "url":"www.weibo.com" } ] } r = requests.post(url,json=data) # r = requests.post(url,data=json.dumps(data)) response = r.json()
輸出:
{ "args": {}, "data": "{\"sites\": [{\"url\": \"www.test.com\", \"name\": \"test\"}, {\"url\": \"www.google.com\", \"name\": \"google\"}, {\"url\": \"www.weibo.com\", \"name\": \"weibo\"}]}", "files": {}, "form": {}, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Content-Length": "140", "Content-Type": "application/json", "Host": "httpbin.org", "User-Agent": "python-requests/2.18.1" }, "json": { "sites": [ { "name": "test", "url": "www.test.com" }, { "name": "google", "url": "www.google.com" }, { "name": "weibo", "url": "www.weibo.com" } ] }, "origin": "183.14.133.88", "url": "http://httpbin.org/post" }
4、帶參數(shù)的post:
# -*- coding:utf-8 -*- import requests import json host = "http://httpbin.org/" endpoint = "post" url = ''.join([host,endpoint]) params = {'key1':'params1','key2':'params2'} # r = requests.post(url) r = requests.post(url,params=params) #response = r.json() print (r.text)
輸出:
{ "args": { "key1": "params1", "key2": "params2" }, "data": "", "files": {}, "form": {}, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Content-Length": "0", "Host": "httpbin.org", "User-Agent": "python-requests/2.18.1" }, "json": null, "origin": "183.14.133.88", "url": "http://httpbin.org/post?key2=params2&key1=params1" }
5.普通文件上傳:
# -*- coding:utf-8 -*- import requests import json host = "http://httpbin.org/" endpoint = "post" url = ''.join([host,endpoint]) #普通上傳 files = { 'file':open('test.txt','rb') } r = requests.post(url,files=files) print (r.text)
輸出:
{ "args": {}, "data": "", "files": { "file": "hello world!\n" }, "form": {}, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Content-Length": "157", "Content-Type": "multipart/form-data; boundary=392865f79bf6431f8a53c9d56c62571e", "Host": "httpbin.org", "User-Agent": "python-requests/2.18.1" }, "json": null, "origin": "183.14.133.88", "url": "http://httpbin.org/post" }
6.定制化文件上傳:
# -*- coding:utf-8 -*- import requests import json host = "http://httpbin.org/" endpoint = "post" url = ''.join([host,endpoint]) #自定義文件名,文件類型、請(qǐng)求頭 files = { 'file':('test.png',open('test.png','rb'),'image/png') } r = requests.post(url,files=files) print (r.text)heman793
7.多文件上傳:
# -*- coding:utf-8 -*- import requests import json host = "http://httpbin.org/" endpoint = "post" url = ''.join([host,endpoint]) #多文件上傳 files = [ ('file1',('test.txt',open('test.txt', 'rb'))), ('file2', ('test.png', open('test.png', 'rb'))) ] r = requests.post(url,files=files) print (r.text)
8.流式上傳:
# -*- coding:utf-8 -*- import requests import json host = "http://httpbin.org/" endpoint = "post" url = ''.join([host,endpoint]) #流式上傳 with open( 'test.txt' ) as f: r = requests.post(url,data = f) print (r.text)
輸出:
{ "args": {}, "data": "hello world!\n", "files": {}, "form": {}, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Content-Length": "13", "Host": "httpbin.org", "User-Agent": "python-requests/2.18.1" }, "json": null, "origin": "183.14.133.88", "url": "http://httpbin.org/post" }
(4)Cookie&Session
掌握了前面幾節(jié)的的內(nèi)容,就可以做一些簡(jiǎn)單的http協(xié)議接口的請(qǐng)求發(fā)送了,但是這些還不夠。HTTP協(xié)議是一個(gè)無(wú)狀態(tài)的應(yīng)用層協(xié)議,也就是說(shuō)前后兩次請(qǐng)求是沒有任何關(guān)系的,那如果我們測(cè)試的接口之前有相互依賴關(guān)系怎么辦呢(比如我要在博客園發(fā)文章,是需要先登錄的),這時(shí)我們就要用到cookie和session技術(shù)來(lái)保持客戶端與服務(wù)器端連接的狀態(tài),這也就是本節(jié)要介紹的內(nèi)容:
一、Cookie:
1、獲取cookie:
# -*- coding:utf-8 -*- #獲取cookie import requests import json url = "https://www.baidu.com/" r = requests.get(url) #將RequestsCookieJar轉(zhuǎn)換成字典 c = requests.utils.dict_from_cookiejar(r.cookies) print r.cookies print c for a in r.cookies: print a.name,a.value
輸出:
<RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]> {'BDORZ': '27315'} BDORZ 27315
2、發(fā)送Cookie
# -*- coding:utf-8 -*- #發(fā)送cookie到服務(wù)器 import requests import json host = "http://httpbin.org/" endpoint = "cookies" url = ''.join([host,endpoint]) #方法一:簡(jiǎn)單發(fā)送 # cookies = {"aaa":"bbb"} # r = requests.get(url,cookies=cookies) # print r.text #方法二:復(fù)雜發(fā)送 s = requests.session() c = requests.cookies.RequestsCookieJar() c.set('c-name','c-value',path='/xxx/uuu',domain='.test.com') s.cookies.update(c)
二、Session
1、保持會(huì)話同步:
# -*- coding:utf-8 -*- import requests import json host = "http://httpbin.org/" endpoint = "cookies" url = ''.join([host,endpoint]) url1 = "http://httpbin.org/cookies/set/sessioncookie/123456789" r = requests.get(url) print r.text print "------" s = requests.session() #初始化一個(gè)session對(duì)象 s.get(url1) #cookie的信息存在了session中 r = s.get(url) print r.text
輸出:
{ "cookies": {} } ------ { "cookies": { "sessioncookie": "123456789" } }
2、保存繪畫信息:
# -*- coding:utf-8 -*- import requests import json host = "http://httpbin.org/" endpoint = "headers" url = ''.join([host,endpoint]) header1 = {"testA":"AAA"} header2 = {"testB":"BBB"} s = requests.session() #初始化一個(gè)session對(duì)象 s.headers.update(header1) #已經(jīng)存在于服務(wù)中的信息 r = s.get(url,headers=header2) #發(fā)送新的信息 print r.text
輸出:
{ "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Host": "httpbin.org", "Testa": "AAA", "Testb": "BBB", "User-Agent": "python-requests/2.18.1" } }
3.刪除已存在的會(huì)話信息,保存為None
# -*- coding:utf-8 -*- import requests import json host = "http://httpbin.org/" endpoint = "headers" url = ''.join([host,endpoint]) header1 = {"testA":"AAA"} header2 = {"testB":"BBB"} s = requests.session() #初始化一個(gè)session對(duì)象 s.headers.update(header1) #已經(jīng)存在于服務(wù)中的信息 r = s.get(url,headers=header2) #發(fā)送新的信息 print r.text print '--------' s.headers['testA'] = None #刪除會(huì)話里的信息testA r1 = s.get(url,headers = header2) print r1.text
{ "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Host": "httpbin.org", "Testa": "AAA", "Testb": "BBB", "User-Agent": "python-requests/2.18.1" } } -------- { "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Host": "httpbin.org", "Testb": "BBB", "User-Agent": "python-requests/2.18.1" } }
4、提供默認(rèn)數(shù)據(jù):
s = requests.Session() s.auth = ('user', 'pass') s.headers.update({'x-test': 'true'}) # both 'x-test' and 'x-test2' are sent s.get('http://httpbin.org/headers', headers={'x-test2': 'true'})
參考:
http://docs.python-requests.org/en/master/user/quickstart/#cookies
http://docs.python-requests.org/en/master/user/advanced/#session-objects
(5)其他(認(rèn)證&代理&超時(shí)設(shè)置)
一、認(rèn)證
1、基本認(rèn)證:
# -*- coding:utf-8 -*- import requests url = "http://httpbin.org/basic-auth/user/passwd" r1 = requests.get(url) print "未提供用戶名密碼:" + str(r1.status_code) #Basic Authentication r2 = requests.get(url,auth=('user','passwd')) print "已提供用戶名密碼:" + str(r2.status_code)
輸出:
未提供用戶名密碼:401
已提供用戶名密碼:200
2、數(shù)字認(rèn)證:
>>> from requests.auth import HTTPDigestAuth >>> url = 'http://httpbin.org/digest-auth/auth/user/pass' >>> requests.get(url, auth=HTTPDigestAuth('user', 'pass')) <Response [200]>
3、OAuth認(rèn)證:
參考:http://docs.python-requests.org/en/master/user/authentication/
二、代理
1、方法一:proxy參數(shù):
import requests proxies = { "https": "http://41.118.132.69:4433" } r = requests.post("http://httpbin.org/post", proxies=proxies) print r.text
2、方法二:設(shè)置環(huán)境變量:
$ export HTTP_PROXY="http://10.10.1.10:3128" $ export HTTPS_PROXY="http://10.10.1.10:1080" $ python >>> import requests >>> requests.get('http://example.org')
3、HTTP Basic Auth使用代理方法:http://user:password@host/
proxies = {'http': 'http://user:pass@10.10.1.10:3128/'}
三、證書驗(yàn)證
1、SSL證書(HTTPS):
import requests #跳過(guò)12306 的證書驗(yàn)證,把 verify 設(shè)置為 False: r = requests.get('https://kyfw.12306.cn/otn/', verify=False) print r.text
2、客戶端證書:
>>> requests.get('https://kennethreitz.org', cert=('/path/client.cert', '/path/client.key')) <Response [200]>
or
s = requests.Session() s.cert = '/path/client.cert'
四、超時(shí)配置
1 、利用timeout參數(shù)來(lái)配置最大請(qǐng)求時(shí)間:
r = requests.get('https://github.com', timeout=5)
2、設(shè)置timeout=None,告訴請(qǐng)求永遠(yuǎn)等待響應(yīng),而不將請(qǐng)求作為超時(shí)值傳遞
r = requests.get('https://github.com', timeout=None)
五、錯(cuò)誤異常:
1、所有Requests顯式拋出的異常都繼承自:requests.exctptions.RequestException
2、遇到網(wǎng)絡(luò)問題(如:DNS查詢失敗,拒絕連接等)時(shí),requests會(huì)拋出一個(gè)ConnectionError異常
3、遇到罕見的無(wú)效HTTP響應(yīng)時(shí),Request則會(huì)拋出一個(gè)HTTPError異常
4、若請(qǐng)求超時(shí),則拋出一個(gè)Timeout異常
5、若請(qǐng)求超過(guò)了最大的重寫向次數(shù),則會(huì)拋出一個(gè)TooManyRedirects異常
(6)unittest-單個(gè)用例管理:
上面主要介紹了環(huán)境搭建和requests庫(kù)的使用,可以使用這些進(jìn)行接口請(qǐng)求的發(fā)送。但是如何管理接口案例?返回結(jié)果如何自動(dòng)校驗(yàn)?這些內(nèi)容光靠上面五節(jié)是不行的,因此從本節(jié)開始我們引入python單元測(cè)試框架 unittest,用它來(lái)處理批量用例管理,校驗(yàn)返回結(jié)果,初始化工作以及測(cè)試完成后的環(huán)境復(fù)原工作等等。
一、單個(gè)用例管理起來(lái)比較簡(jiǎn)單,參考如下圖,單個(gè)用例一般多用在調(diào)試的時(shí)候:
二、代碼如下:
# -*- coding:utf-8 -*- # 單個(gè)用例執(zhí)行 # 1、導(dǎo)入模塊 import unittest # 2、繼承自u(píng)nittest.TestCase類 class TestOne(unittest.TestCase): # 3、配置環(huán)境:進(jìn)行測(cè)試前的初始化工作 def setUp(self): print '\ncases before' pass # 4、定義測(cè)試用例,名字以“test”開頭 def test_add(self): '''test add method''' print 'add...' a = 3 + 4 b = 7 # 5、定義assert斷言,判斷測(cè)試結(jié)果 self.assertEqual(a, b) def test_sub(self): '''test sub method''' print 'sub...' a = 10 - 5 b = 4 self.assertEqual(a, b) # 6、清理環(huán)境 def tearDown(self): print 'case after' pass # 7、該方法會(huì)搜索該模塊下所有以test開頭的測(cè)試用例方法,并自動(dòng)執(zhí)行它們 if __name__ == '__main__': unittest.main()
輸出:
Ran 2 tests in 0.001s OK cases before add... case after cases before sub... case after Process finished with exit code 0
(8)unittest-生成測(cè)試報(bào)告:
用例的管理問題解決了后,接下來(lái)要考慮的就是報(bào)告我問題了,這里生成測(cè)試報(bào)告主要用到HTMLTestRunner.py 這個(gè)模塊,下面簡(jiǎn)單介紹一下如何使用:
一、下載HTMLTestRunner下載:
這個(gè)模塊不能通過(guò)pip安裝,只能下載安裝,下載地址如下:
python2.x版本:http://tungwaiyip.info/software/HTMLTestRunner.html
python3.x版本:http://hzqldjb.blog.51cto.com/9587820/1590802
二、mac下配置:
1、終端進(jìn)入python環(huán)境
2、輸入:
import sys print sys.path
3、找到site-packages文件夾的路徑并將下載的HTMLTestRunner.py文件拷貝到此的文件夾下
4、在python環(huán)境下,輸入 import HTMLTestRunner 不報(bào)錯(cuò)即安裝成功
三、使用該模塊生成報(bào)告:
1、目錄結(jié)構(gòu)
- case包下面有baidu,httpbin兩個(gè)包
- 每個(gè)包下面分別有兩個(gè)測(cè)試的py文件
- 每個(gè)test_00x.py文件里各有2個(gè)test case
- run_all_case.py文件:用來(lái)執(zhí)行所有的test case且生成測(cè)試報(bào)告
2、運(yùn)行后生成報(bào)告如下:
3、run_all_case.py代碼如下:
# -*- coding:utf-8 -*- import unittest import os import time import HTMLTestRunner # 用例路徑 case_path = os.path.join(os.getcwd()) # 報(bào)告存放路徑 report_path = os.path.join(os.getcwd(), 'report') print report_path def all_case(): discover = unittest.defaultTestLoader.discover(case_path, pattern="test*.py", top_level_dir=None) print discover return discover if __name__ == '__main__': # 1、獲取當(dāng)前時(shí)間,這樣便于下面的使用。 now = time.strftime("%Y-%m-%d-%H_%M_%S", time.localtime(time.time())) # 2、html報(bào)告文件路徑 report_abspath = os.path.join(report_path, "result_"+now+".html") # 3、打開一個(gè)文件,將result寫入此file中 fp = open(report_abspath, "wb") runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title=u'接口自動(dòng)化測(cè)試報(bào)告,測(cè)試結(jié)果如下:', description=u'用例執(zhí)行情況:') # 4、調(diào)用add_case函數(shù)返回值 runner.run(all_case()) fp.close()
到此這篇關(guān)于Python接口自動(dòng)化測(cè)試的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Python接口自動(dòng)化測(cè)試內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python3+Requests+Excel完整接口自動(dòng)化測(cè)試框架的實(shí)現(xiàn)
- 利用Python如何實(shí)現(xiàn)數(shù)據(jù)驅(qū)動(dòng)的接口自動(dòng)化測(cè)試
- python接口自動(dòng)化測(cè)試之接口數(shù)據(jù)依賴的實(shí)現(xiàn)方法
- Python http接口自動(dòng)化測(cè)試框架實(shí)現(xiàn)方法示例
- Python+unittest+requests+excel實(shí)現(xiàn)接口自動(dòng)化測(cè)試框架
- Python實(shí)現(xiàn)http接口自動(dòng)化測(cè)試的示例代碼
- python使用pytest接口自動(dòng)化測(cè)試的使用
- Python接口自動(dòng)化測(cè)試框架運(yùn)行原理及流程
- python接口自動(dòng)化測(cè)試數(shù)據(jù)和代碼分離解析
- Python+Requests+PyTest+Excel+Allure?接口自動(dòng)化測(cè)試實(shí)戰(zhàn)
- Python+requests+unittest執(zhí)行接口自動(dòng)化測(cè)試詳情
- python使用requests+excel進(jìn)行接口自動(dòng)化測(cè)試的實(shí)現(xiàn)
相關(guān)文章
python對(duì) MySQL 數(shù)據(jù)庫(kù)進(jìn)行增刪改查的腳本
這篇文章主要介紹了python對(duì) MySQL 數(shù)據(jù)庫(kù)進(jìn)行增刪改查的腳本,幫助大家更好的利用python處理數(shù)據(jù)庫(kù),感興趣的朋友可以了解下2020-10-10python中p-value的實(shí)現(xiàn)方式
今天小編就為大家分享一篇python中p-value的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-12-12Python namedtuple命名元組實(shí)現(xiàn)過(guò)程解析
這篇文章主要介紹了Python namedtuple命名元組實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01python 數(shù)據(jù)提取及拆分的實(shí)現(xiàn)代碼
這篇文章主要介紹了python 數(shù)據(jù)提取及拆分的實(shí)現(xiàn)代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08Python中如何快速解析JSON對(duì)象數(shù)組
由于瀏覽器可以迅速地解析JSON對(duì)象,它們有助于在客戶端和服務(wù)器之間傳輸數(shù)據(jù),本文將描述如何使用Python的JSON模塊來(lái)傳輸和接收J(rèn)SON數(shù)據(jù)2023-09-09Django 批量插入數(shù)據(jù)的實(shí)現(xiàn)方法
這篇文章主要介紹了Django 批量插入數(shù)據(jù)的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01python爬取淘寶商品詳情頁(yè)數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了python爬取淘寶商品詳情頁(yè)數(shù)據(jù)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02