以前學習python作接口測試時,用的時requests+excel的方式來進行接口測試,後來在工做中也用unittest來作了一個項目的接口測試,接口測試用例徹底基於unittest來編寫,把大體步驟記錄一下。html
以前公司的測試並無在前期就介入項目,即便是接口測試,也是在研發人員完成項目開發後再進行的接口校驗,其實更接近於驗證一下接口功能是否正常實現了,通常這種工做我更喜歡使用postman來進行,一個一個把接口錄入postman,每一個都單獨校驗一下,最終也會造成一套測試腳本(對於沒有代碼能力又要進行接口測試的人來講簡直是神器)。後來再論壇看其餘人的經驗貼時,發現其實對於公司這種接口比較少的項目,也徹底能夠用python自帶的unittest來寫測試用例,一個接口寫做一個py文件,其實也很簡潔,相對於requests+excel的方式省去了讀取/解析excel文件的步驟,維護起來也不麻煩。python
base_data: 封裝了一些基礎數據,如固定的ip地址、端口(方便後期修改)json
common_utils: 存放了一些配置文件、讀取配置文件的方法、發送請求的方法ide
reports:存放測試報告post
test_suits: 存放接口測試用例學習
run_report.py: 最終運行文件,即調用測試用例,執行後生成報告測試
1.common_utilsui
config.ini
配置文件
[URL] # url = http://192.168.XXX:7001 url = http://192.168.XXX:8080
read_config.py
讀取配置文件的方法 # -*- coding:utf-8 -*- import configparser import os class ReadConfig: def __init__(self, filepath=None): if filepath: configpath1 = filepath else: root_dir1 = os.path.dirname(__file__) # 獲取當前腳本的目錄 configpath1 = os.path.join(root_dir1, "config.ini") # 拼接路徑 # print(root_dir1) # root_dir = os.path.dirname(os.path.abspath('.')) # 獲取當前腳本所在目錄的上一級目錄 # configpath = os.path.join(root_dir, "common_utils/config.ini") # 拼接路徑 # print(root_dir) self.cf = configparser.ConfigParser() self.cf.read(configpath1) def get_host(self, param): value = self.cf.get("URL", param) return value base_url = ReadConfig() # if __name__ == '__main__': # test = ReadConfig() # t = test.get_host("url") # print(t) # print(base_url.get_host("URL"))
send_request.py 請求方法類
# -*- coding:utf-8 -*- import requests import json from requests.exceptions import RequestException class RunMethod: """定義一個執行接口請求的類""" @staticmethod def send_get(url, data=None, header=None): response = requests.get(url=url, params=data, headers=header, timeout=20) try: if response.status_code == 200: r = response return r else: return None except RequestException: print("請求失敗") return None @staticmethod def send_post(url, data=None, header=None): response = requests.post(url=url, data=data, headers=header, timeout=20) try: if response.status_code == 200: r = response return r else: return None except RequestException: print("請求失敗") return None def run_main(self, method, url, data=None, header=None): if method == "GET": res = self.send_get(url, data, header) else: res = self.send_post(url, data, header) # return json.dumps(res, indent=2, sort_keys=False, ensure_ascii=False) return res if __name__ == '__main__': url = "http://192.168.XXX:7001/ApprLicenseInterface/saveFile.v" data = {'ATTACH_SIZE': "36243", 'ATTACH_URL': "/mnt/MDFilesPath/APPR_STUFF_ATTACH/B2018120709470002/Rectangle.png", 'ATTACH_CREATOR': "", 'PARENTID': "-1", 'ATTACH_NAME': "67d06265bb814e6aa0f8f87913ab4f4e.pdf"} t = RunMethod() print(t.run_main("GET", url, data)) print(type(t.run_main("GET", url, data)))
2.base_data編碼
base_data.py 基礎數據,從配置文件取數據
# -*- coding:utf-8 -*-
from common_utils.read_config import ReadConfig
import os
class BaseData:
def __init__(self):
self.data = ReadConfig()
def get_ip(self):
"""從配置文件中獲取固定ip"""
ip = self.data.get_host("url")
return ip
base_data = BaseData()
# print(base_data.get_ip())
3.test_suitsurl
這裏面就是存放的接口測試用例了,一個文件表明一個接口,每一個文件中根據實際狀況存在多條用例(根據傳參不一樣來組合)
注意:爲了再後面往套件中添加用例文件,爲每一個用例文件都加了test_前綴;
說下遇到的一個問題:由於接口文檔中每一個接口都有一個編號,以下
因此開始個人命名方式是 test_5.2.1.1+接口名稱,而後發如今把用例添加到測試套件時老是識別不到,後來把數字去掉才能夠,至今不知道什麼緣由致使的。。。
一個例子 # -*- coding:utf-8 -*- import unittest from common_utils.send_request import RunMethod from base_data.base_data import * import json run = RunMethod() class Test(unittest.TestCase): """ 5.2.1.三、依職能查驗用證:經過目錄編碼以及身份證件號碼獲取證照""" @classmethod def setUpClass(cls): cls.url = base_data.get_ip() + "/XXX/licenseList/identity.v" @classmethod def tearDownClass(cls): pass def test01(self): """參數正常""" data = {"licenseDirNum":"123456789", "identityNumbers":"120101198001010098"} r = run.run_main("GET", self.url, data) res = r.json() print(json.dumps(res, indent=2, sort_keys=False, ensure_ascii=False)) self.assertEqual("200", res["status"]) self.assertNotEqual([], res["data"]["dataList"]) # 判斷dataList不爲空 def test02(self): """licenseDirNum爲空""" data = {"licenseDirNum":"", "identityNumbers":"120101198001010098"} r = run.run_main("GET", self.url, data) res = r.json() print(json.dumps(res, indent=2, sort_keys=False, ensure_ascii=False)) self.assertEqual("傳入的參數:(licenseDirNum)不能爲空", res["desc"]) self.assertTrue(res["data"] is None) # 判斷返回結果的data值爲空 self.assertIsNone(res["data"]) # 判斷返回結果的data值爲空 # self.assertNotEqual([], res["data"]["dataList"]) def test03(self): """identityNumbers爲空""" data = {"licenseDirNum": "123456789", "identityNumbers": ""} r = run.run_main("GET", self.url, data) res = r.json() print(json.dumps(res, indent=2, sort_keys=False, ensure_ascii=False)) self.assertEqual("傳入的參數:(identityNumbers)不能爲空", res["desc"]) self.assertTrue(res["data"] is None) # 判斷返回結果的data值爲空 if __name__ == '__main__': suite = unittest.TestSuite() # 調用unittest的TestSuite(),理解爲管理case的一個容器(測試套件) suite.addTest(Test('test01')) # 向測試套件中添加用例,"TestMethod"是上面定義的類名,"test01"是用例名 runner = unittest.TextTestRunner() runner.run(suite) # 執行套件中的用例
4.run_report.py
# coding: utf-8 # author: hmk import HTMLTestRunner import unittest import time, os root_dir = os.path.dirname(os.path.abspath(__file__)) # 獲取當前腳本的目錄 case_dir = root_dir + '/test_suits' # 根據項目所在路徑,找到用例所在的相對項目的路徑 # case_dir1 = 'E:/5.coding\電子證照庫接口/test_suits\電子證照類' print(root_dir) print(case_dir) suits = unittest.defaultTestLoader.discover(case_dir, pattern='test_*.py', top_level_dir=None) # 加載用例,用例文件名最好不要有數字,不然致使識別不到 suit = unittest.TestLoader().discover(case_dir) # 加載用例 """ 1.case_dir即測試用例所在目錄 2.pattern='test_*.py' :表示用例文件名的匹配原則,「*」表示任意多個字符 3.top_level_dir=None:測試模塊的頂層目錄。若是沒頂層目錄(也就是說測試用例不是放在多級目錄 中),默認爲 None """ if __name__ == '__main__': now_time = time.strftime("%Y-%m-%d %H-%M-%S") filename = root_dir + '/reports/' + now_time + '_result.html' # 定義報告文件 # fp = open(filename, 'wb') # runner = HTMLTestRunner.HTMLTestRunner(stream=fp,title='電子證照庫接口測試報告',description='測試結果以下: ') # runner.run(suit) # fp.close() # 普通方式打開文件 with open(filename, 'wb') as fp: """使用withopen操做文件""" runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title='電子證照庫接口測試報告', description='測試結果以下: ') runner.run(suits)
最後執行run_report.py便可運行所有接口用例,獲得測試報告