一篇文章带你了解接口自动化
一篇文章帶你了解接口自動(dòng)化
在之前的文章里我們已經(jīng)學(xué)習(xí)了Python,unitTest,pyTest,Allure等自動(dòng)化框架
在這篇文章中我們將借助這些自動(dòng)化框架和實(shí)際案例來(lái)講解如何針對(duì)接口進(jìn)行自動(dòng)化處理
我們這篇文章將從以下角度展開講解:
- 常用類Requests
- 接口自動(dòng)化基礎(chǔ)
- 接口自動(dòng)化實(shí)例
常用類Requests
首先我們需要了解一個(gè)在接口自動(dòng)化中經(jīng)常使用的工具類
Requests庫(kù)基本信息
我們?cè)谑褂媒涌谧詣?dòng)化時(shí)一定會(huì)調(diào)用到不同類型的接口,而Requests庫(kù)可以幫助我們快速調(diào)用接口:
- Requests 是?Python語(yǔ)?編寫,基于urllib,采?Apache2 Licensed開源協(xié)議的 HTTP 庫(kù)
- 它? urllib 更加?便,可以節(jié)約我們?量的?作,完全滿?HTTP測(cè)試需求
我們需要了解到Requests庫(kù)是第三方庫(kù),所以我們需要下載后使用:
# 我們直接在Terminal里采用pip指令下載Requests庫(kù)即可
pip install requests
# 我們可以采用show命令查看是否安裝成功
pip show requests
我們通常會(huì)使用到的關(guān)于Requests的方法主要包含以下五種:
# 首先我們注意我們需要導(dǎo)入Requests庫(kù)才可以使用
# Get
Requests.get()
# Post
Requests.post()
# Put
Requests.put()
# Delete
Requests.delete()
Requests庫(kù)基本使用
下面我們針對(duì)Requests庫(kù)的使用來(lái)做基本的講解:
- Requests庫(kù)可以調(diào)用不同的類型方法來(lái)針對(duì)不同請(qǐng)求類型發(fā)送接口請(qǐng)求
- Requests庫(kù)在發(fā)送接口請(qǐng)求后,后端會(huì)返回一個(gè)Response,我們可以接受并查看信息
下面我們首先針對(duì)Requests庫(kù)的發(fā)送請(qǐng)求進(jìn)行講解:
# 首先我們需要導(dǎo)包使用
import requests
# 在正式開始講解之前我們需要了解Requests所使用的方法中的一些參數(shù)
# url:請(qǐng)求路徑
# params:get特有的參數(shù)賦值方法,意思是在url的?之后的參數(shù)賦值
# json:通用的參數(shù)賦值方法,可以用于復(fù)雜的格式也可以用于字典格式
# data:請(qǐng)求體為form表單參數(shù),通常用于字典類型的比較簡(jiǎn)單的格式
# header:請(qǐng)求頭參數(shù),通常是Authorization驗(yàn)證登錄信息或者參數(shù)傳輸格式信息等
# files:文件格式,使用字典傳輸,且字典中含有'file'鍵名稱
# 首先我們先來(lái)看一下常用的Get請(qǐng)求
# Requests.get(url,params/json)
r = requests.get('http://httpbin.org/get')
# 如果我們想要添加參數(shù)進(jìn)行傳輸,我們可以直接在url后面添加?+參數(shù)信息等
r = requests.get('http://httpbin.org/get?name=germey&age=20')
# 我們也可以采用params參數(shù)或者json參數(shù)進(jìn)行傳輸
data = {
'name':'germey',
'age':22
}
r = requests.get('http://httpbin.org/get',params=data)
r = requests.get('http://httpbin.org/get',json=data)
# 下面我們了解一下Post請(qǐng)求,Put和Delete操作和Post操作完全相同,這里不做介紹
# Requests.get(url,json)
r = requests.post('http://httpbin.org/post')
# 和Get方法不同的是,Post不能采用params也不能采用url拼接,只能采用json進(jìn)行傳輸
data = {
"name":"germey",
"age":"22"
}
r = requests.post('http://httpbin.org/post',data=data)
# 除了基本的url和json之外,我們?cè)谡?qǐng)求過(guò)程中還需要很多參數(shù)類型
# 例如header頭,我們的大部分操作都需要做登陸驗(yàn)證,而登錄一般會(huì)含有一個(gè)Authorization屬性,后面value值為Token值,這里我們講述
# 但是除了Authorization屬性外,我們還可能會(huì)傳輸參數(shù)類型Content-Type等其他信息
# 我們通常將header寫為字典格式進(jìn)行傳輸
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0',
'my-test':'Hello'
}
r = requests.get('http://httpbin.org/get',headers=headers)
# 我們?cè)趥鬏斶^(guò)程中也經(jīng)常傳輸文件類型,我們通常需要讀取文件并將其存儲(chǔ)為Python中的文件才可以使用
# 我們需要注意以二進(jìn)制方式讀取文件
# 我們?cè)趐ost方法中需要傳輸字典,字典key值為'file'是默認(rèn)名詞
files = {'file':open('favicon.ico','rb')}
# 我們調(diào)用post方法并使用files參數(shù)進(jìn)行文件上傳
r = requests.post('http://httpbin.org/post',files=files)
# 我們還需要注意一些特殊的網(wǎng)站,如果該網(wǎng)站的證書沒(méi)有被CA機(jī)構(gòu)信任,程序?qū)?huì)出錯(cuò),提示SSL證書驗(yàn)證錯(cuò)誤
# 那么我們?cè)谠L問(wèn)時(shí),只需要將verify參數(shù)設(shè)置為False即可
r = requests.get('https://www.12306.cn',verify=False)
# 針對(duì)特別防范的網(wǎng)站,當(dāng)我們大量進(jìn)行數(shù)據(jù)爬取或者重復(fù)使用時(shí),可能會(huì)觸發(fā)該網(wǎng)站的自衛(wèi)系統(tǒng)將我們當(dāng)前IP進(jìn)行屏蔽
# 我們可以通過(guò)使用代理來(lái)防止這種情況(IP可以在網(wǎng)上購(gòu)買)
proxies = {
'http': 'http://161.35.4.201:80',
'https': 'https://161.35.4.201:80'
}
r = requests.get('http://httpbin.org/get', proxies=proxies)
在講述完Requests庫(kù)的發(fā)送請(qǐng)求后,我們可以針對(duì)Requests請(qǐng)求后的Response響應(yīng)進(jìn)行講述:
# 我們?cè)诎l(fā)送請(qǐng)求后服務(wù)器會(huì)對(duì)我們的請(qǐng)求進(jìn)行響應(yīng),這就是所獲得的Response,所有請(qǐng)求都會(huì)獲取到該響應(yīng)
# 我們下面來(lái)介紹一些我們常用的response類型的方法
# 獲取狀態(tài)碼
response.status_code
# JSON形式的響應(yīng)內(nèi)容
response.json()
# 文本形式的響應(yīng)內(nèi)容
response.text
# 請(qǐng)求url
response.url
# 查看響應(yīng)頭部字符編碼
response.encoding
# 頭信息
response.headers
# cookie信息
response.cookies
# 我們通常獲得這些信息之后可以進(jìn)行查看,我們可以通過(guò)print直接打印查看
print(response.status_code)
# 但更多情況下,我們通過(guò)這些信息來(lái)做斷言判斷是否符合我們預(yù)期
assert 200 == response.status_code
assert "成功" in response.text
# 當(dāng)然我們?cè)诒匾闆r下我們還需要獲取到對(duì)應(yīng)的值去使用
# 例如我們通常需要一個(gè)Token來(lái)表示我們處于登陸狀態(tài),那么我們就需要在執(zhí)行登陸操作時(shí)將token值獲取并保存下來(lái)
self.token = r.json().get("token")
# 如果我們需要cookie,我們也可以直接獲取cookies并將其保存在一個(gè)列表中
response = requests.get("百度一下,你就知道")
for key, value in response.cookies.items():
print(key + '=' + value)
接口自動(dòng)化基礎(chǔ)
下面我們來(lái)講解接口自動(dòng)化的一些基礎(chǔ)信息
接口測(cè)試
既然我們要學(xué)習(xí)接口自動(dòng)化,那么我們肯定首先需要了解接口測(cè)試:
- 使用工具或代碼代替人對(duì)接口進(jìn)行測(cè)試的技術(shù)
- 其根本目的是為了防止開發(fā)修改代碼時(shí)引入新的問(wèn)題
那么我們的接口測(cè)試主要針對(duì)哪些方面:
- 我們的項(xiàng)目分為前端和后端
- 前端僅僅是調(diào)用接口的一種方式,其根本還是后端的處理
- 所以我們的接口測(cè)試就是針對(duì)后端所書寫的方法進(jìn)行測(cè)試,測(cè)試其是否符合我們的需求
我們測(cè)試人員針對(duì)接口測(cè)試的主要時(shí)間段是在哪里:
-
開發(fā)進(jìn)行系統(tǒng)測(cè)試提測(cè)前,可以先進(jìn)行接口自動(dòng)化腳本的編寫
-
開發(fā)進(jìn)行系統(tǒng)測(cè)試提測(cè)后,優(yōu)先進(jìn)行系統(tǒng)測(cè)試用例的執(zhí)行,再進(jìn)行接口自動(dòng)化腳本的編寫
-
所以我們接口測(cè)試的主要時(shí)間段針對(duì)于前后端聯(lián)調(diào)的時(shí)間進(jìn)行接口測(cè)試
接口測(cè)試基本操作
下面我們來(lái)講解接口測(cè)試的基本操作順序:
# 1.選取自動(dòng)化測(cè)試用例
# 我們一般會(huì)在前后端開發(fā)時(shí)進(jìn)行測(cè)試用例的書寫,我們僅需要選取我們所測(cè)試模塊的測(cè)試用例即可
# 2.搭建自動(dòng)化測(cè)試環(huán)境
# 這個(gè)主要根據(jù)公司本身,一般由主管進(jìn)行搭建,員工拉取書寫更新上傳即可
# 3.搭建自動(dòng)化測(cè)試框架
# 這個(gè)主要也是公司進(jìn)行選取,不過(guò)一般都是python+pytest+allure基本框架加上一些輔助框架
# 4.代碼實(shí)現(xiàn)自動(dòng)化
# 這個(gè)就是我們接口測(cè)試自動(dòng)化主要書寫的部分
# 5.輸出測(cè)試報(bào)告
# 我們一般會(huì)采用allure進(jìn)行美觀測(cè)試報(bào)告生成
# 6.實(shí)現(xiàn)持續(xù)集成
# 我們接口測(cè)試的目的其實(shí)是為了在本次開發(fā)時(shí)使當(dāng)前開發(fā)不影響之前功能的使用,所以我們的接口自動(dòng)化需要保證效率重復(fù)使用等多方面
我們?cè)谶M(jìn)行接口測(cè)試時(shí)可以通過(guò)三種方式獲得接口:
-
在測(cè)試頁(yè)面使用F12查看調(diào)用接口信息
-
采用Charles等抓包工具查看接口信息
-
向項(xiàng)目經(jīng)理/后端人員索要接口文檔信息
最后我們稍微提一下如果我們使用手動(dòng)接口測(cè)試,我們一般會(huì)使用Postman工具進(jìn)行測(cè)試,我們這里不做詳解
接口自動(dòng)化實(shí)例
接下來(lái)我們通過(guò)一個(gè)接口自動(dòng)化實(shí)例來(lái)講解接口自動(dòng)化
接口自動(dòng)化框架信息
我們?cè)诮佑|接口自動(dòng)化代碼之前,我們首先需要了解這個(gè)框架主要需要什么:
# 首先假設(shè)我們創(chuàng)建了一個(gè)Pro_viv文件來(lái)當(dāng)作主目錄
# 首先我們需要一個(gè)api文件夾
# 我們會(huì)將我們所需要調(diào)用的Api接口進(jìn)行封裝(Requests庫(kù)相關(guān)的信息)
# 然后我們需要一個(gè)script文件夾
# 我們需要將我們所使用的case進(jìn)行存儲(chǔ),其實(shí)就是我們pytest中所使用的測(cè)試用例,我們的數(shù)據(jù)調(diào)用也是在這里進(jìn)行調(diào)用
# 然后我們需要一個(gè)data文件夾
# 我們會(huì)將我們所需要使用的jpg或json等信息文件存儲(chǔ)進(jìn)該文件夾
# 最后我們還需要一個(gè)report文件夾
# 我們會(huì)將所生成的allure報(bào)告文檔存放在該文件夾下
# 除了文件夾外,我們還需要兩個(gè)文件來(lái)進(jìn)行一些信息整理
# 首先我們需要一個(gè)config.py
# 我們會(huì)使用該文件來(lái)存放一些通用的路徑或其他信息
# 我們還需要一個(gè)pytest.ini
# 這是pytest的配置文件,我們可以在里面修改pytest相關(guān)的信息
接口自動(dòng)化實(shí)例展示
那么下面我們將通過(guò)多個(gè)需求案例來(lái)逐步了解接口自動(dòng)化的使用
登錄接口
我們首先給出需求信息:
# 地址:http://kdtx-test.itheima.net/api/login
# 方法:Post
# 請(qǐng)求數(shù)據(jù):
# 請(qǐng)求頭:Content-Type: application/json
# 請(qǐng)求體:{"username":”admin", "password": " admin123","code":"2", "uuid":"驗(yàn)證碼接口返回?cái)?shù)據(jù)"}
我們首先需要書寫接口,所以我們需要在api文件下創(chuàng)建login.py進(jìn)行接口書寫:
# api 文件夾 - login.py
# 接口封裝時(shí),重點(diǎn)是依據(jù)接口文檔封裝接口信息
# 需要使用的測(cè)試數(shù)據(jù)是從測(cè)試用例傳遞的、接口方法被調(diào)用時(shí)需要返回對(duì)應(yīng)的響應(yīng)結(jié)果
# 所以我們?cè)跁鴮懲杲涌诜椒ê螅覀冞€需要到script文件夾下創(chuàng)建test文件來(lái)創(chuàng)建case來(lái)執(zhí)行pytest
# 導(dǎo)包
import requests
# 創(chuàng)建接口類
class LoginAPI:
# 初始化
def __init__(self):
# 指定url基本信息
self.url_verify = "http://kdtx-test.itheima.net/api/captchaImage"
self.url_login = "http://kdtx-test.itheima.net/api/login"
# 驗(yàn)證碼
def get_verify_code(self):
return requests.get(url=self.url_verify)
# 登錄
# 我們?cè)诘卿洉r(shí)需要請(qǐng)求信息,我們這里添加一個(gè)參數(shù),當(dāng)我們使用case時(shí)傳參并調(diào)用
def login(self, test_data):
return requests.post(url=self.url_login, json=test_data)
當(dāng)我們書寫完接口信息之后,我們就可以到script文件夾下創(chuàng)建test文件進(jìn)行測(cè)試用例書寫:
# script 文件夾 - verify.py
Class TestLogin:
uuidValue = None
# 驗(yàn)證碼測(cè)試
def test01_get_verify_code1(self):
# 獲取驗(yàn)證碼
res_v = self.login_api.get_verify_code()
# 登錄驗(yàn)證
def test02_login1(self):
# 這里我們直接將信息寫為列表進(jìn)行賦值處置
login_data = {
"username": "admin",
"password": "admin123",
"code": "2",
"uuid": "f3334fd726bf4155b787198c701786b6"
}
res_l = self.login_api.login(test_data=login_data)
# 驗(yàn)證碼測(cè)試2
def test03_get_verify_code1(self):
# 獲取驗(yàn)證碼
res_v = self.login_api.get_verify_code()
# 一些信息的打印
print(res_v.status_code)
print(res_v.json())
# 打印uuid數(shù)據(jù),這是我們?cè)诘卿洉r(shí)所需要使用的數(shù)據(jù)
print(res_v.json().get("uuid"))
# 我們可以采用一個(gè)類變量來(lái)將uuid存儲(chǔ)起來(lái)進(jìn)行使用
self.uuidValue = res_v.json().get("uuid")
# 登陸驗(yàn)證2
def test04_login(self):
# 由于我們的uuid是通過(guò)get_verify_code獲得的驗(yàn)證碼,我們可以通過(guò)pytest連續(xù)執(zhí)行兩條case并獲取uuid進(jìn)行使用
login_data = {
"username": "admin",
"password": "admin123",
"code": "2",
"uuid": self.uuidValue
}
res_l = self.login_api.login(test_data=login_data)
課程接口
我們首先給出需求信息:
# 課程模塊接口封裝:核心在于依據(jù)接口文檔實(shí)現(xiàn)接口信息封裝、重點(diǎn)關(guān)注接口如何被調(diào)用
# 接口信息:
# URL:http://kdtx-test.itheima.net/api/clues/course
# 方法:Post
# 請(qǐng)求數(shù)據(jù):
# 請(qǐng)求頭:{ "Content-Type ": "application/json ", "Authorization": "xxx " }
# 請(qǐng)求體:{ "name": "測(cè)試開發(fā)提升課01", "subject": "6","price": 899,"applicablePerson": "2", "info": "測(cè)試開發(fā)提升課01"}
我們首先需要書寫接口,所以我們需要在api文件下創(chuàng)建course.py進(jìn)行接口書寫:
# api 文件夾 - course.py
# 我們將在該接口類中實(shí)現(xiàn)多個(gè)接口,我們將書寫除了上述需求信息外的其他接口
# 導(dǎo)包
import requests
# 創(chuàng)建接口類
class CourseAPI:
# 初始化
def __init__(self):
self.url_add_course = "http://kdtx-test.itheima.net/api/clues/course"
self.url_select_course = "http://kdtx-test.itheima.net/api/clues/course/list"
# 我們需要注意:
# 我們合同的操作均需要在登錄前提下進(jìn)行操作
# 而我們判斷是否登錄的條件就是在headers請(qǐng)求頭中是否存在符合要求的token
# 所以我們下述的接口方法中,除了我們所需要的數(shù)據(jù)信息外,我們還需要添加headers,并提供Authorization信息
# 課程添加
def add_course(self, test_data, token):
return requests.post(url=self.url_add_course, json=test_data, headers={"Authorization": token})
# 查詢課程列表
def select_course(self, test_data, token):
# 這里我們可以采用url拼接,也可以采用params來(lái)傳遞參數(shù),
# return requests.get(url=self.url_select_course,params=params,headers={"Authorization": token})
return requests.get(url=self.url_select_course + f"/{test_data}", headers={"Authorization": token})
# 修改課程
def update_course(self, test_data, token):
return requests.put(url=self.url_add_course, json=test_data, headers={"Authorization": token})
# 刪除課程
def delete_course(self, course_id, token):
return requests.delete(url=self.url_add_course + f"/{course_id}", headers={"Authorization": token})
當(dāng)我們書寫完接口信息之后,我們就可以到script文件夾下創(chuàng)建test文件進(jìn)行測(cè)試用例書寫:
# 導(dǎo)包
import config
from api.login import LoginAPI
from api.course import CourseAPI
from api.contract import ContractAPI
# 創(chuàng)建測(cè)試類
class TestContractBusiness:
# 初始化(由于我們需要使用登錄時(shí)的Token,所以我們進(jìn)行存儲(chǔ))
token = None
# 前置處理
def setup(self):
# 實(shí)例化接口對(duì)象
self.login_api = LoginAPI()
self.course_api = CourseAPI()
self.contract_api = ContractAPI()
# 后置處理
def teardown(self):
pass
# 1、登錄成功
def test01_login_success(self):
# 獲取驗(yàn)證碼
res_v = self.login_api.get_verify_code()
# 登錄
login_data = {
"username": "admin",
"password": "admin123",
"code": "2",
"uuid": res_v.json().get("uuid")
}
res_l = self.login_api.login(test_data=login_data)
# 提取登錄成功之后的token數(shù)據(jù)并保存在類的屬性中
TestContractBusiness.token = res_l.json().get("token")
# 2、課程新增成功
def test02_add_course(self):
add_data = {
"name": "測(cè)試開發(fā)提升課01",
"subject": "6",
"price": 899,
"applicablePerson": "2",
"info": "測(cè)試開發(fā)提升課01"
}
response = self.course_api.add_course(test_data=add_data, token=TestContractBusiness.token)
print(response.json())
合同接口
我們首先給出需求信息:
# 請(qǐng)求頭:{ "Content-Type ": " multipart/form-data ", "Authorization": "xxx " }
# 請(qǐng)求體:{" file " : 合同文件"}
# 接口信息:
# 新增合同:
# 地址:http://kdtx-test.itheima.net/api/contract
# 方法:Post
# 請(qǐng)求數(shù)據(jù):
# 請(qǐng)求頭:{ "Content-Type ": "application/json ", "Authorization": "xxx " }
# 請(qǐng)求體:{ "name": "測(cè)試888", "phone": "13612345678", "contractNo": "HT10012003", "subject": "6", "courseId": " 99", "channel": "0", "activityId": 77, "fileName": "xxx"}
我們首先需要書寫接口,所以我們需要在api文件下創(chuàng)建contract.py進(jìn)行接口書寫:
# 導(dǎo)包
import requests
# 創(chuàng)建接口類
class ContractAPI:
# 初始化
def __init__(self):
self.url_upload = "http://kdtx-test.itheima.net/api/common/upload"
self.add_contrat = "http://kdtx-test.itheima.net/api/contract"
# 合同上傳接口
def upload_contract(self, test_data, token):
# 我們的合同需要一份文件信息上傳,所以我們參數(shù)這里使用到了file
# 其實(shí)我們的headers頭部的Content-Type信息也被修改,但由于該信息是根據(jù)傳輸內(nèi)容更新的,所以我們不需要設(shè)置
return requests.post(url=self.url_upload, files={"file": test_data}, headers={"Authorization": token})
# 合同新增
def add_contract(self, test_data, token):
# 這里就是很正常的新增
return requests.post(url=self.add_contrat, json=test_data, headers={"Authorization": token})
當(dāng)我們書寫完接口信息之后,我們就可以到script文件夾下創(chuàng)建test文件進(jìn)行測(cè)試用例書寫:
# 導(dǎo)包
import config
from api.login import LoginAPI
from api.course import CourseAPI
from api.contract import ContractAPI
# 創(chuàng)建測(cè)試類
class TestContractBusiness:
# 初始化
token = None
# 前置處理
def setup(self):
# 實(shí)例化接口對(duì)象
self.login_api = LoginAPI()
self.course_api = CourseAPI()
self.contract_api = ContractAPI()
# 后置處理
def teardown(self):
pass
# 1、登錄成功
def test01_login_success(self):
# 獲取驗(yàn)證碼
res_v = self.login_api.get_verify_code()
# 登錄
login_data = {
"username": "admin",
"password": "admin123",
"code": "2",
"uuid": res_v.json().get("uuid")
}
res_l = self.login_api.login(test_data=login_data)
# 提取登錄成功之后的token數(shù)據(jù)并保存在類的屬性中
TestContractBusiness.token = res_l.json().get("token")
# 2、上傳合同成功
def test02_upload_contract(self):
# 這里我們需要將對(duì)應(yīng)的文件采用二進(jìn)制讀取并且轉(zhuǎn)化為file類型將其作為參數(shù)傳參
f = open(config.BASE_PATH + "/data/test.pdf", "rb")
# 這里的test_data在Api中作為files的file被傳遞
response = self.contract_api.upload_contract(test_data=f, token=TestContractBusiness.token)
print(response.json())
# 3、合同新增成功
def test03_add_contract(self):
# contractNo: 數(shù)據(jù)唯一
add_data = { "name": "測(cè)試888", "phone": "13612345678", "contractNo": "HT20230007", "subject": "6", "courseId": " 99", "channel": "0", "activityId": 77, "fileName": "xxx"}
response = self.contract_api.add_contract(test_data=add_data, token=TestContractBusiness.token)
print(response.json())
單接口測(cè)試
下面我們來(lái)講解針對(duì)于單個(gè)接口進(jìn)行多測(cè)試用例測(cè)試的方法:
# 我們這里以Login的API為基準(zhǔn)
# 我們需要采用不同的測(cè)試用例來(lái)進(jìn)行測(cè)試并判斷是否滿足需求
我們首先給出測(cè)試用例圖表:
然后我們采用代碼進(jìn)行接口自動(dòng)化測(cè)試用例書寫:
# 導(dǎo)包
from api.login import LoginAPI
# 創(chuàng)建測(cè)試類
class TestLoginAPI:
# 初始化
uuid = None
# 前置處理
# 我們將uuid驗(yàn)證碼作為所有case方法執(zhí)行前的前置操作進(jìn)行執(zhí)行并存儲(chǔ)使用
def setup(self):
# 實(shí)例化接口類
self.login_api = LoginAPI()
# 獲取驗(yàn)證碼
response = self.login_api.get_verify_code()
# 提取驗(yàn)證碼接口返回的uuid參數(shù)值
TestLoginAPI.uuid = response.json().get("uuid")
# 后置處理
def teardown(self):
pass
# 下面我們通過(guò)多個(gè)Case的書寫來(lái)模擬多場(chǎng)景情況
# 我們下面Case的基本邏輯沒(méi)有發(fā)生修改,僅僅是針對(duì)參數(shù)進(jìn)行了處理
# 登錄成功
def test01_success(self):
login_data = {
"username": "manager",
"password": "123456",
"code": "2",
"uuid": TestLoginAPI.uuid
}
response = self.login_api.login(test_data=login_data)
# 我們使用斷言來(lái)判斷是否符合需求,若符合需求pytest會(huì)通過(guò)案例,若不符合會(huì)進(jìn)行報(bào)錯(cuò)
assert 200 == response.status_code # 斷言響應(yīng)狀態(tài)碼為200
assert '成功' in response.text # 斷言響應(yīng)數(shù)據(jù)包含'成功'
assert 200 == response.json().get("code") # 斷言響應(yīng)json數(shù)據(jù)中code值
# 登錄失敗(用戶名為空)
def test02_without_username(self):
login_data = {
"username": "",
"password": "123456",
"code": "2",
"uuid": TestLoginAPI.uuid
}
response = self.login_api.login(test_data=login_data)
# 我們使用斷言來(lái)判斷是否符合需求,若符合需求pytest會(huì)通過(guò)案例,若不符合會(huì)進(jìn)行報(bào)錯(cuò)
assert 200 == response.status_code # 斷言響應(yīng)狀態(tài)碼為200
assert '成功' in response.text # 斷言響應(yīng)數(shù)據(jù)包含'成功'
assert 200 == response.json().get("code") # 斷言響應(yīng)json數(shù)據(jù)中code值
# 登錄失敗(未注冊(cè)用戶)
def test03_username_not_exist(self):
login_data = {
"username": "jack666",
"password": "123456",
"code": "2",
"uuid": TestLoginAPI.uuid
}
response = self.login_api.login(test_data=login_data)
# 我們使用斷言來(lái)判斷是否符合需求,若符合需求pytest會(huì)通過(guò)案例,若不符合會(huì)進(jìn)行報(bào)錯(cuò)
assert 200 == response.status_code # 斷言響應(yīng)狀態(tài)碼為200
assert '成功' in response.text # 斷言響應(yīng)數(shù)據(jù)包含'成功'
assert 200 == response.json().get("code") # 斷言響應(yīng)json數(shù)據(jù)中code值
參數(shù)化測(cè)試
我們?cè)谇懊嫱ㄟ^(guò)書寫多個(gè)Case來(lái)進(jìn)行同一接口的自動(dòng)化測(cè)試,但這種方法會(huì)導(dǎo)致代碼冗余
所以我們通常會(huì)通過(guò)pytest的參數(shù)化設(shè)置來(lái)統(tǒng)一數(shù)據(jù)將其放入Case用例中按順序依次執(zhí)行來(lái)減少代碼冗余:
# 我們可以將數(shù)據(jù)單獨(dú)存放在文件頂層
# 我們所傳入的數(shù)據(jù)需要采用列表作為外層,采用字典作為數(shù)據(jù)參數(shù)進(jìn)行存儲(chǔ)
# 導(dǎo)包
from api.login import LoginAPI
import pytest
import json
# 測(cè)試數(shù)據(jù)
test_data = [
("manager", "123456", 200, '成功', 200),
("", "123456", 200, '錯(cuò)誤', 500),
("jack666", "123456", 200, '錯(cuò)誤', 500),
]
class TestLoginAPI:
# 初始化
uuid = None
# 前置處理
def setup(self):
# 實(shí)例化接口類
self.login_api = LoginAPI()
# 獲取驗(yàn)證碼
response = self.login_api.get_verify_code()
# 提取驗(yàn)證碼接口返回的uuid參數(shù)值
TestLoginAPI.uuid = response.json().get("uuid")
# 后置處理
def teardown(self):
pass
# 多Case登錄驗(yàn)證
# 這里我們使用了我們上面所定義的test_data作為數(shù)據(jù)源來(lái)進(jìn)行參數(shù)化處理
# 我們可以將我們所需要更替的數(shù)值全部采用參數(shù)化處理,使處理數(shù)據(jù)變得多樣化
# 這里所使用的parametrize是pytest的內(nèi)容,我們?cè)谏掀恼乱呀?jīng)講過(guò),如果不了解可以去查看
@pytest.mark.parametrize("username, password, status, message, code",test_data)
def test01_success(self, username, password, status, message, code):
# 這里的username,password使用參數(shù)化
login_data = {
"username": username,
"password": password,
"code": "2",
"uuid": TestLoginAPI.uuid
}
response = self.login_api.login(test_data=login_data)
# 這里的斷言判斷均使用參數(shù)化,因?yàn)椴煌瑮l件下所產(chǎn)生的response數(shù)據(jù)是不同的
assert status == response.status_code
assert message in response.text
assert code == response.json().get("code")
接口自動(dòng)化配置解釋
最后我們需要解釋我們?cè)谧铋_始所提及到的兩個(gè)接口配置信息
全局信息配置文件
我們?cè)谧铋_始提及到了在我們的文件目錄下創(chuàng)建了一個(gè)Config.py文件
下面我們來(lái)解釋一下該文件的主要作用:
# 我們通常在該文件下定義我們?nèi)侄夹枰褂玫臄?shù)據(jù)信息,來(lái)減少我們代碼的冗余
# 例如我們?cè)谥暗慕涌诨驕y(cè)試用例中都需要使用到的url,我們可以在這里定義其項(xiàng)目url前綴,然后我們只需要書寫對(duì)應(yīng)的接口路徑即可
# 又或者說(shuō)由于我們之前的文件上傳沒(méi)有固定的文件目錄,我們需要從當(dāng)前文件下去推斷data文件夾在哪個(gè)位置
# 但是如果我們項(xiàng)目發(fā)生改動(dòng),或者我們借鑒該代碼去書寫其他部分的文件,我們就需要去重新推斷data文件夾在哪個(gè)位置
# 所以我們可以通過(guò)config.py直接獲得絕對(duì)路徑下的data目錄的位置,然后我們只需要進(jìn)行拼接就可以獲得到我們所需要的數(shù)據(jù)信息
所以我們的config.py文件可以這樣去定義:
# config.py文件
# 導(dǎo)包
import os
# 設(shè)置項(xiàng)目環(huán)境域名
BASE_URL = "http://kdtx-test.itheima.net"
# 獲取項(xiàng)目根路徑
BASE_PATH = os.path.dirname(__file__)
當(dāng)然我們對(duì)應(yīng)的接口代碼和測(cè)試用例代碼也需要進(jìn)行修改:
# 首先針對(duì)API文件,我們需要去修改我們的url路徑信息
def __init__(self):
# 指定url基本信息
# self.url_verify = "http://kdtx-test.itheima.net/api/captchaImage"
self.url_verify = config.BASE_URL + "/api/captchaImage"
# self.url_login = "http://kdtx-test.itheima.net/api/login"
self.url_login = config.BASE_URL + "/api/login"
# 針對(duì)文件上傳時(shí)的路徑我們也可以去修改
def test03_upload_contract(self):
# f = open("../data/test.pdf", "rb")
f = open(config.BASE_PATH + "/data/test.pdf", "rb")
response = self.contract_api.upload_contract(test_data=f, token=TestContractBusiness.token)
print(response.json())
框架設(shè)置配置文件
我們之前還提到了一個(gè)pytest.ini文件,該文件其實(shí)就是針對(duì)pytest執(zhí)行用例的初始化進(jìn)行設(shè)置:
# 該文件其實(shí)屬于pytest的學(xué)習(xí)范疇,我們?cè)谶@里簡(jiǎn)單介紹一下
[pytest]
# 表示我們?cè)赥erminal執(zhí)行pytest時(shí)的默認(rèn)執(zhí)行配置
# 這里我們采用-s表示詳情信息展示,采用--alluredir表示采用allure生成測(cè)試報(bào)告并生成在report文件夾下
addopts=-s --alluredir report
# 這里表示我們所需要執(zhí)行的測(cè)試用例的文件范圍
testpaths=./script
# 這里規(guī)定了配置測(cè)試搜索的模塊文件名稱
python_files=test*
# 這里規(guī)定了我們所執(zhí)行的測(cè)試類的類名規(guī)范
python_classes=Test*
# 這里規(guī)定了我們所執(zhí)行的測(cè)試方法的方法名規(guī)范
python_functions=test*
結(jié)束語(yǔ)
這篇文章中詳細(xì)介紹了以pytest為框架的接口自動(dòng)化實(shí)現(xiàn)的基本信息,希望能為你帶來(lái)幫助
下面給出我學(xué)習(xí)和書寫該篇文章的一些參考文章,大家也可以去查閱:
- 黑馬課程:001_認(rèn)識(shí)接口測(cè)試_嗶哩嗶哩_bilibili
- 知乎文章:python中requests庫(kù)使用方法詳解 - 知乎 (zhihu.com)
- CSDN:requests庫(kù)的使用(一篇就夠了)_上善若水。。的博客-CSDN博客
- 稀土掘金:軟件測(cè)試/測(cè)試開發(fā)丨學(xué)習(xí)筆記之接口自動(dòng)化測(cè)試 - 掘金 (juejin.cn)
總結(jié)
以上是生活随笔為你收集整理的一篇文章带你了解接口自动化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Log4j入门使用
- 下一篇: 数据结构与算法 | 图(Graph)