Pytest+Request+Allure+Jenkins實(shí)現(xiàn)接口自動化
- 利用
Pytest+Request+Allure+Jenkins
實(shí)現(xiàn)接口自動化; - 實(shí)現(xiàn)一套腳本多套環(huán)境執(zhí)行;
- 利用參數(shù)化數(shù)據(jù)驅(qū)動模式,實(shí)現(xiàn)接口與測試數(shù)據(jù)分離
- 使用
logger
定制實(shí)現(xiàn)自動化測試日志記錄
實(shí)現(xiàn)步驟:
框架結(jié)構(gòu):
1、接口自動化項(xiàng)目代碼編寫(先在window實(shí)現(xiàn))
1.1 項(xiàng)目準(zhǔn)備
先在window安裝響應(yīng)的環(huán)境依賴
- 安裝python3.7(要保證pip能用,一般安裝python3.7會自動安裝pip)
- 安裝pytest框架---- pip install pytest
- 安裝request庫---- pip install request
- 安裝openpyxl庫(測試數(shù)據(jù)保存在excel中,需要依賴讀取excel的庫)---- pip install openpyxl
- 安裝pycharm(編寫python腳本工具)
注意:可能還需要一些依賴的東西,項(xiàng)目步驟里會依據(jù)需要進(jìn)行安裝
1.2 設(shè)計(jì)基于pytest的測試框架結(jié)構(gòu)
在pycharm中開發(fā)構(gòu)建項(xiàng)目結(jié)構(gòu)
common:存放公共方法
config:存放環(huán)境配置信息
lib:存放第三方庫
main:框架主入口
report:存放allure測試報(bào)告
test_case:存放測試用例
test_data:存放測試數(shù)據(jù)
1.3 實(shí)現(xiàn)接口公共請求發(fā)送能力
從這一步開始正式編寫代碼
封裝http請求的公共能力(封裝request庫,變成自己的公共處理能力),放到common目錄下。
# encoding: utf-8 import requests import urllib3 # from urllib3.exceptions import InsecureRequestWarning urllib3.disable_warnings() # 加這句不會報(bào)錯(requests證書警告) # requests.packages.urllib3.disable_warnings(InsecureRequestWarning) class HTTPRequests(object): def __init__(self, url): self.url = url self.req = requests.session() # 依據(jù)自己公司的請求頭默認(rèn)值配置 self.head = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.2; WOW64; Trident/7.0; rv:11.0) like Gecko', 'Accept': 'image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/xaml+xml, ' 'application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, ' 'application/msword, */*', 'Accept-Language': 'zh-CN'} # 封裝自己的get請求,獲取資源 def get(self, uri='', params='', data='', headers=None, cookies=None, verify=False): if headers is None: headers = self.head # print("請求頭是:{}".format(headers)) url = self.url + uri response = self.req.get(url, params=params, data=data, headers=headers, cookies=cookies, verify=verify) return response # 封裝自己的post請求,獲取資源 def post(self, uri='', params='', data='', headers=None, cookies=None, verify=False): if headers is None: headers = self.head url = self.url + uri response = self.req.post(url, params=params, data=data, headers=headers, cookies=cookies, verify=verify) return response # 封裝自己的put請求,獲取資源 def put(self, uri='', params='', data='', headers=None, cookies=None, verify=False): if headers is None: headers = self.head url = self.url + uri response = self.req.put(url, params=params, data=data, headers=headers, cookies=cookies, verify=verify) return response # 封裝自己的delete請求,獲取資源 def delete(self, uri='', params='', data='', headers=None, cookies=None, verify=False): if headers is None: headers = self.head url = self.url + uri response = self.req.delete(url, params=params, data=data, headers=headers, cookies=cookies, verify=verify) return response
1.4 抽離測試環(huán)境配置信息
這個步驟的目的有三個
- 為了配置三個不同環(huán)境(測試、開發(fā)、生產(chǎn))的URL,每個環(huán)境接口測試的URL是不一樣的,設(shè)置這樣一個枚舉類,方便后面的程序根據(jù)不同的環(huán)境,獲取不同環(huán)境的URL,里面的URL依據(jù)自己公司的地址修改,放到config目錄
- 獲取token需要登錄,這里可以設(shè)置一個全局的賬號密碼,這個賬號密碼獲取的token可以給整個接口自動化使用
- 配置獲取token的uri,這個uri三個環(huán)境的是一致的,登錄的接口依據(jù)環(huán)境只是URL不同,URI還是一致的。
# encoding: utf-8 import enum class URLConf(enum.Enum): """環(huán)境配置信息""" url_mapping = { 'dev': 'https://www.dev.com', 'test': 'https://www.test.com', 'prod': 'https://www.prod.com' } # token固定的用戶名密碼,固定用"/"分割用戶名和密碼 email_user = { 'dev': 'dev@qq.com', 'test': 'zidonghua@qq.com/96e79218965eb72c92a549dd5a330112', 'prod': 'prod@qq.com' } login_uri = r'/api/auth/login/account/v1'
1.5 創(chuàng)建conftest.py放置一些公共的fixture
1、pytest_addoption,設(shè)置了只允許輸入dev/test/prod三個參數(shù),以區(qū)分測試、開發(fā)、生產(chǎn)三個環(huán)境
2、get_env的fixture,它的作用是你在命令行執(zhí)行接口自動化時(shí),可以輸入--env test將對應(yīng)的環(huán)境信息傳入進(jìn)去
3、http的fixture,這里依據(jù)--env test傳入的環(huán)境信息,去枚舉類里獲取對應(yīng)環(huán)境的URL,然后返回一個http的session,供測試案例使用
4、get_token_head,依據(jù)--env test傳入的環(huán)境信息,調(diào)用獲取token方法,并將token放置到請求頭head里返回(token一般放在請求頭里,這里依據(jù)自己公司的請求,返回對應(yīng)的token信息就可以了)
# encoding: utf-8 # 代碼來源:全棧測開訓(xùn)練營 import logging import os import pytest from common.http_request import HTTPRequests from config.url_config import URLConf datadir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "test_data") logger = logging.getLogger('conftest日志') def pytest_addoption(parser): # choices 只允許輸入的值的范圍 parser.addoption( "--env", action="store", default='test', choices=['dev', 'test', 'prod'], help="set env" ) # 獲取命令行參數(shù)的fixture @pytest.fixture(scope='session') def get_env(request): # print("fixutre..................") return request.config.getoption('--env') # 聲明一個返回http請求對象的fixture,所有用例在一個session中 # @pytest.fixture(scope='module', autouse=True) @pytest.fixture(autouse=True) def http(request): env = request.getfixturevalue("get_env") url_mapping = URLConf.url_mapping.value url = url_mapping.get(f'{env}') http = HTTPRequests(url) return http @pytest.fixture(scope='session') def get_token_head(request): env = request.getfixturevalue("get_env") url_mapping = URLConf.url_mapping.value url = url_mapping.get(f'{env}') http = HTTPRequests(url) user = URLConf.email_user.value user_list = user.get(f'{env}').split("/") username = user_list[0] password = user_list[1] param = {'clientType': 2, 'language': 'en', 'loginId': username, 'loginPassword': password} logger.info("請求的url=={}".format(url)) response = http.post(uri=r'/api/auth/login/account/v1', data=param) logger.info("獲取的返回值是:".format(response.text)) token = None if response.status_code == 200: token = response.json().get('result')['token'] else: token = 'get token fail' head = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.2; WOW64; Trident/7.0; rv:11.0) like Gecko', 'Accept': 'image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/xaml+xml, ' 'application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, ' 'application/msword, */*', 'Accept-Language': 'zh-CN', 'Authorization': token} yield head
1.6 將測試數(shù)據(jù)放到excel中
我們的測試數(shù)據(jù)是放在excel中,注意,這里有prod\test\dev三個目錄,對應(yīng)三個環(huán)境的測試數(shù)據(jù),我這里只創(chuàng)建了test測試環(huán)境的測試數(shù)據(jù)。這里的測試數(shù)據(jù)需要包含兩部分:
- 你調(diào)用接口傳入的所有參數(shù);
- 你要斷言的所有信息,因?yàn)槟銈鞯膮?shù)不同,返回的內(nèi)容就不同,你斷言的內(nèi)容也就不相同了。
那么這時(shí)候,就需要一個讀取excel的公共方法了,放到common里
# 創(chuàng)建解析excel的方法 import logging from openpyxl import load_workbook logger = logging.getLogger("讀取excel") class ParseExcel(object): def __init__(self, excelPath, sheetName): self.wb = load_workbook(excelPath) self.sheet = self.wb[sheetName] self.maxRowNum = self.sheet.max_row # 依據(jù)傳入的數(shù)字,決定獲取幾列excel數(shù)據(jù) def getDataFromSheet(self, num): dataList = [] for line in self.sheet.rows: tmplist = [] for i in range(num): tmplist.append(line[i].value) dataList.append(tmplist) print("dadddddd:{}".format(dataList)) return dataList[2:]
這里,還需要再test_data中,創(chuàng)建一個文件,為了獲取前面test_data依據(jù)環(huán)境創(chuàng)建的dev/test或prod文件目錄
1.7 開始編寫自動化測試案例了
測試案例中有幾個點(diǎn),需要解釋一下:
1、authBaseDir,這個就是根據(jù)test_data/test拼接出來的獲取測試數(shù)據(jù)的目錄
2、allure.feature,在測試報(bào)告中,會展現(xiàn)這個接口名稱,這個名稱最好與你公司的開發(fā)寫的接口模塊保持一致,方便后續(xù)查找問題
3、allure.story 這里也要與開發(fā)寫的具體某個接口的名稱保持一致。
4、pytest.mark.parametrize,這里就是運(yùn)用的DDT數(shù)據(jù)驅(qū)動的模式,從excel中一條一條的獲取數(shù)據(jù),然后執(zhí)行同一條接口測試用例,excel中比如有3條數(shù)據(jù),那么就表示這個案例依據(jù)每一條數(shù)據(jù)的參數(shù),總共執(zhí)行了三次
# encoding: utf-8 """ Account Api模塊 """ import logging import os import allure import pytest from common.get_data_url import get_data_url from common.parse_excel import ParseExcel datadir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "test_data") data_url = get_data_url() # 獲取到test_data\test的目錄,如果是prod環(huán)境,那么就是獲取test_data\prod目錄 authBaseDir = os.path.join(datadir, data_url) logger = logging.getLogger("Account Api模塊日志") @allure.feature("AccountApi模塊") @pytest.mark.webtest class TestAccountApi(object): """Query Related Achievements: /api/auth/account/achievement/related/query/v1 """ Query_Related_Achievements_dir = os.path.join(authBaseDir, 'Query_Related_Achievements.xlsx') logger.info("Query_Related_Achievements測試數(shù)據(jù)的路徑是:{}".format(Query_Related_Achievements_dir)) parse = ParseExcel(Query_Related_Achievements_dir, 'Sheet1') Query_Related_Achievements_params = parse.getDataFromSheet(5) @allure.story("Query Related Achievements(查詢用戶成就信息)") @pytest.mark.parametrize("clientType,language,retCode,istoken,result", Query_Related_Achievements_params) def test_001_Query_Related_Achievements(self, get_token_head, http, clientType, language, retCode, istoken, result): uri = '/api/auth/account/achievement/related/query/v1' params = {"clientType": clientType, "language": language} if istoken == 'yes': header = get_token_head response = http.get(uri=uri, params=params, headers=header) json_req = response.json() logger.info("Query_Related_Achievements有token的返回值是:{}".format(json_req)) assert json_req.get('retCode') == 200 assert json_req.get('result')[0]['smallImg'] == result else: response = http.get(uri=uri, params=params) json_req = response.json() logger.info("Query_Related_Achievements沒有token的返回值是:{}".format(json_req)) assert json_req.get('retCode') == 401 assert json_req.get('message') == result
1.8 集成allure
寫到這里,是不是發(fā)現(xiàn)前面的allure.feature是不是用不了呢?這是因?yàn)槲覀冞€沒有集成allure進(jìn)去。
1、下載allure
,放到lib目錄下,使你的工程具備allure的能力。
2、pip install allure-pytest
安裝pytest對應(yīng)的allure包
1.9 這時(shí)候就可以創(chuàng)建一些執(zhí)行策略了
1、先在main中創(chuàng)建一個pytest.ini文件,設(shè)置一些執(zhí)行參數(shù)
2、在main中創(chuàng)建執(zhí)行策略
- 先在run_pytest方法中,執(zhí)行案例并生成allure的json格式的報(bào)告文件,這里可以帶--env prod將對應(yīng)環(huán)境信息傳入,這里沒有傳是因?yàn)槟J(rèn)是test環(huán)境,不傳入的話就是執(zhí)行的test環(huán)境測試數(shù)據(jù)
- general_report方法時(shí)將生成的json格式的報(bào)告,最終生成html文件放置到report下面的目錄中
- 創(chuàng)建一個線程,先執(zhí)行run_pytest,再執(zhí)行g(shù)eneral_report,避免json文件沒有生成,這樣生成html文件的報(bào)告數(shù)據(jù)可能不全,甚至沒有。
# encoding: utf-8 """ 所有案例執(zhí)行并生成allure測試報(bào)告的執(zhí)行策略 """ import os import sys import threading import pytest sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../') from common.report import Report project_root = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) report_dir = os.path.join(project_root, 'report') # 存放測試結(jié)果的目錄,會生成一推json文件 result_dir = os.path.join(report_dir, 'allure_result') allure_report = os.path.join(report_dir, 'allure_report') report = Report() # 定義搜索條件,搜索所有以test開頭的用例 tag = 'test' def run_pytest(): # --clean-alluredir # pytest.main(['-vv', '-s', '-m', 'webtest', f'--alluredir={result_dir}', '--clean-alluredir']) # 執(zhí)行前清除allure_result數(shù)據(jù),避免生成報(bào)告時(shí),會把上次執(zhí)行的數(shù)據(jù)帶進(jìn)去 pytest.main(['-vv', '-s', '-k', f'{tag}', f'--alluredir={result_dir}', '--clean-alluredir']) def general_report(): # 調(diào)用cmd方法 report.allure,根據(jù)windows或linux環(huán)境判斷 # 然后執(zhí)行生成報(bào)告的方法generate # --clean 覆蓋路徑,將上次的結(jié)果覆蓋掉 cmd = "{} generate {} -o {} --clean".format(report.allure, result_dir, allure_report) # 執(zhí)行命令行命令,并通過read()方法將命令的結(jié)果返回 print(os.popen(cmd).read()) if __name__ == '__main__': # 創(chuàng)建兩個線程,分別執(zhí)行兩個方法 run = threading.Thread(target=run_pytest) gen = threading.Thread(target=general_report) run.start() # 先執(zhí)行第一個線程,這個線程執(zhí)行完才會執(zhí)行下面的線程和主線程 run.join() gen.start() gen.join()
1.10 自動化執(zhí)行生成結(jié)果
在windows下,右鍵執(zhí)行main下面的run_test_allure_html.py(就是上一個步驟的python文件),然后打開report/allure_report/index.html看看報(bào)告是否生成成功
2. jenkins環(huán)境搭建(linux環(huán)境)
好了,到這一步,在windows下我們已經(jīng)執(zhí)行成功,現(xiàn)在我們要集成到j(luò)enkins環(huán)境去,并搭建在linux環(huán)境下。
1、將代碼上傳到公司的git(沒有g(shù)it的自己搭建一套吧)
2、找一臺linux機(jī)器(自己去自己公司找資源)
3、在linux下安裝jenkins(我是放到tomcat中)、python3、pytest、allure、openpyxl(這些步驟在網(wǎng)上可以搜索到,這里不贅述了)
4、啟動linux下的tomcat,然后在window下打開jenkins的服務(wù)地址
5、創(chuàng)建一個自由風(fēng)格的job
6、Job需要填寫的具體內(nèi)容有:
A、選擇丟棄舊的構(gòu)建(保留的構(gòu)建天數(shù)依據(jù)自己的情況選擇)
B、“限制項(xiàng)目的運(yùn)行節(jié)點(diǎn)”依據(jù)自己的情況選擇(我這里給我的jenkins主服務(wù)器取了一個叫l(wèi)inux的標(biāo)簽,我的機(jī)器也是linux機(jī)器)
C、git--將git上的代碼拉下來
D、“執(zhí)行shell”,這里把代碼從git拉到了jenkins的執(zhí)行目錄里,一般在linux下的root/.jenkins里,在執(zhí)行shell時(shí),最好chmod修改下整個工程的目錄權(quán)限,因?yàn)橛锌赡芤驒?quán)限問題執(zhí)行不了
E、構(gòu)建后的操作:這里需要再jenkins里安裝allure插件才能看到allure Report,第一個Path,這里寫的是allure生成的json文件的目錄,所以是report/allure_result,第二個Report path指的是生成的index.html文件的目錄,所以是report/allure_report
立即構(gòu)建并查看報(bào)告
上面的job建成后,就可以點(diǎn)擊立即構(gòu)建,執(zhí)行了。執(zhí)行完后,點(diǎn)擊allure Report查看最終的報(bào)告。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
python3+mysql查詢數(shù)據(jù)并通過郵件群發(fā)excel附件
這篇文章主要為大家詳細(xì)介紹了python3+mysql查詢數(shù)據(jù),并通過郵件群發(fā)excel附件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02教你用python實(shí)現(xiàn)12306余票查詢
今天就和大家一起來討論一下python實(shí)現(xiàn)12306余票查詢(pycharm+python3.7),一起來感受一下python爬蟲的簡單實(shí)踐,需要的朋友可以參考下2021-06-06Python操作word文檔插入圖片和表格的實(shí)例演示
這篇文章主要給大家介紹了關(guān)于Python操作word文檔插入圖片和表格的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10超詳細(xì)注釋之OpenCV實(shí)現(xiàn)視頻實(shí)時(shí)人臉模糊和人臉馬賽克
這篇文章主要介紹了OpenCV實(shí)現(xiàn)視頻實(shí)時(shí)人臉模糊和人臉馬賽克,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09在Python3.74+PyCharm2020.1 x64中安裝使用Kivy的詳細(xì)教程
這篇文章主要介紹了在Python3.74+PyCharm2020.1 x64中安裝使用Kivy的詳細(xì)教程,本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08詳解TensorFlow2實(shí)現(xiàn)線性回歸
這篇文章主要介紹了TensorFlow2實(shí)現(xiàn)線性回歸的詳細(xì)解析,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09Django REST framework 單元測試實(shí)例解析
這篇文章主要介紹了Django REST framework 單元測試實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11Python通過調(diào)用mysql存儲過程實(shí)現(xiàn)更新數(shù)據(jù)功能示例
這篇文章主要介紹了Python通過調(diào)用mysql存儲過程實(shí)現(xiàn)更新數(shù)據(jù)功能,結(jié)合實(shí)例形式分析了Python調(diào)用mysql存儲過程實(shí)現(xiàn)更新數(shù)據(jù)的具體步驟與相關(guān)操作技巧,需要的朋友可以參考下2018-04-04