接口測(cè)試講義
1. 接口測(cè)試的類型
主要包含三種測(cè)試:
- Web接口測(cè)試,
- 應(yīng)用程序接口(API, application programming interface)測(cè)試,
- 數(shù)據(jù)庫測(cè)試。
實(shí)際上意義就是UI界面到數(shù)據(jù)庫之間,數(shù)據(jù)流經(jīng)過的所有過程。
LAMP(Linux Apache MySQL PHP)/LNMP(Linux Nginx MySQL PHP):只有 Web 服務(wù)器,沒有應(yīng)用服務(wù)器。
- Web 瀏覽器 到 Web 服務(wù)器: Web 接口測(cè)試,測(cè)試 請(qǐng)求和響應(yīng)。
- Web 服務(wù)器 到 數(shù)據(jù)庫服務(wù)器:應(yīng)用接口測(cè)試,測(cè)試 PHP。
Linux / Windows + Java / Asp.net(C#) + Apache/Nginx + Tomcat/IIS + MySQL/Oracle/SQL server
- Web 瀏覽器 到 Web 服務(wù)器: Web 接口測(cè)試,測(cè)試 請(qǐng)求和響應(yīng)。
- Web 服務(wù)器 到 應(yīng)用服務(wù)器:契約服務(wù),WebService,JavaAPI,WebAPI,WCF,.net Remoting:測(cè)試 Java 或者 C# 處理業(yè)務(wù)邏輯(JavaEE/ ASP.NET MVC),通俗講測(cè)試 Service。
- 應(yīng)用服務(wù)器 到 數(shù)據(jù)庫服務(wù)器:數(shù)據(jù)處理服務(wù),測(cè)試 Java 或者 C# 處理數(shù)據(jù),把數(shù)據(jù)讀取到數(shù)據(jù)庫。
我們需要關(guān)注的是 Web 接口測(cè)試。
Web 接口測(cè)試的方法:
- Python 或者 Java,C# 編程,觸發(fā)請(qǐng)求,讀取響應(yīng),分析得到的響應(yīng)數(shù)據(jù)進(jìn)行與源數(shù)據(jù)的對(duì)比。
- 用工具:Postman 或者 SoapUI(不推薦)
Postman 原本是一個(gè) Chrome 瀏覽器的插件,現(xiàn)在已經(jīng)提供了 Windows、MacOS 和Linux 的獨(dú)立安裝版本。接下來用Windows的版本來進(jìn)行安裝和使用。
2. Postman 的安裝
下載 Postman 的安裝包,分為 32位 和 64位。https://www.getpostman.com
安裝 Postman
-
注冊(cè)用戶(Sign Up) 并登錄 (Sign In)
Snap23.png -
可以在多臺(tái)電腦登錄,做過的測(cè)試會(huì)自動(dòng)同步。
Snap24.png -
安裝完并且登錄以后可以開始測(cè)試。
Snap25.png
3. Web 接口的測(cè)試點(diǎn)
Web 接口通過 HTTP(S)請(qǐng)求,是一個(gè)URL,URL請(qǐng)求結(jié)果,會(huì)得到數(shù)據(jù),數(shù)據(jù)的格式主要有兩種,一種JSON,一種 XML。主要用JSON演示。
- JSON,是JavaScript Object Notation,JavaScript 對(duì)象表示法。是用來表示JavaScript的對(duì)象,或者JavaScript數(shù)據(jù)等。因?yàn)镴avaScript廣泛的應(yīng)用在 Web的前端頁面,所以 JSON 主要應(yīng)用在 Web 接口中。主要的應(yīng)用場(chǎng)景:
- APP移動(dòng)端和服務(wù)器的通信。用應(yīng)用層 HTTP 協(xié)議,通過 Web接口讀取數(shù)據(jù)和處理(提交)數(shù)據(jù)。
- Web前端與服務(wù)器的通信,往往服務(wù)器是第三方的,主要的場(chǎng)景就是 支付和第三方登錄。
- 京東 web端 調(diào)用 微信支付、財(cái)付通支付、支付寶支付、銀聯(lián)支付、網(wǎng)銀支付。。。
- 京東 web端 支持 微信登錄、QQ登錄、微博登錄
- 京東 web端 顯示 第三方的的物流信息(順豐、申通、圓通。。。)
- 公共數(shù)據(jù),在web端/APP端的天氣預(yù)報(bào) 是由第三方接口提供。
- XML,Extensible Markup Language,可擴(kuò)展的標(biāo)記語言,HTML就是XML的一種形式,通過 標(biāo)簽的成對(duì)出現(xiàn),以及標(biāo)簽的層次,來決定數(shù)據(jù)的內(nèi)容。XML 主要用在后端的 應(yīng)用程序接口的數(shù)據(jù)傳遞,比如 Java,C#等。XML 比較舊的格式。
接下來用一個(gè)例子,來分別JSON和XML表示以下的表格數(shù)據(jù)。
| employee_id | first_name | last_name | phone_number | hire_date | job_id | salary | |
|---|---|---|---|---|---|---|---|
| 100 | Steven | King | SKING | 515.123.4567 | 6/17/1987 | AD_PRES | 24000 |
| 101 | Neena | Kochhar | NKOCHHAR | 515.123.4568 | 9/21/1989 | AD_VP | 17000 |
首先用 JSON的形式,JSON是“鍵值對(duì)”(Key Value)的形式
{
"employees": [{
"employee_id": 100,
"first_name": "Steven",
"last_name": "King",
"email": "SKING",
"phone_number": "515.123.4567",
"hire_date": "6/17/1987",
"job_id": "AD_PRES",
"salary": 24000
},
{
"employee_id": 101,
"first_name": "Neena",
"last_name": "Kochhar",
"email": "NKOCHHAR",
"phone_number": "515.123.4568",
"hire_date": "9/21/1989",
"job_id": "AD_VP",
"salary": 17000
}]
}
對(duì)應(yīng)的 XML 格式:
<?xml version="1.0" encoding="UTF-8" ?>
<employees>
<employee>
<employee_id>100</employee_id>
<first_name>Steven</first_name>
<last_name>King</last_name>
<email>SKING</email>
<phone_number>515.123.4567</phone_number>
<hire_date>6/17/1987</hire_date>
<job_id>AD_PRES</job_id>
<salary>24000</salary>
</employee>
<employee>
<employee_id>101</employee_id>
<first_name>Neena</first_name>
<last_name>Kochhar</last_name>
<email>NKOCHHAR</email>
<phone_number>515.123.4568</phone_number>
<hire_date>9/21/1989</hire_date>
<job_id>AD_VP</job_id>
<salary>17000</salary>
</employee>
</employees>
Web 接口的定義來決定測(cè)試內(nèi)容
- Method:GET POST PUT DELETE
- URL: 接口的地址
- 請(qǐng)求參數(shù):每個(gè)參數(shù)名字,參數(shù)的類型,參數(shù)的范圍,參數(shù)是否可選,參數(shù)是否有默認(rèn)值
- 等價(jià)類:有效等價(jià)的參數(shù),無效等價(jià)的參數(shù)
- 邊界值:離點(diǎn),上點(diǎn),內(nèi)點(diǎn)
- 正交試驗(yàn)法:×因子 ×狀態(tài)
- 有的時(shí)候,參數(shù)之間關(guān)聯(lián):省,市,縣(區(qū)),尤其注意非法(無效)的關(guān)聯(lián)
- 斷言:檢查響應(yīng)的內(nèi)容
- 正文:正文是否包含某些字符
- 正文:JSON 或者 XML 的鍵值對(duì)檢查,數(shù)量檢查 xx.length
- 響應(yīng)的狀態(tài)碼:200, 403
- 響應(yīng)的時(shí)間: 100ms, 200ms
*5. 認(rèn)證:你是否有權(quán)限訪問接口
-
接口的實(shí)質(zhì)對(duì)象:數(shù)據(jù)
- 數(shù)據(jù)的格式
- 數(shù)據(jù)的內(nèi)容
?
4. Postman 的使用
-
測(cè)試 心知天氣 API:https://www.seniverse.com/
登錄 心知天氣 (先注冊(cè))
-
讀 接口的 API 文檔
- API的定義: API 的URL的組成 和請(qǐng)求方法
- API的參數(shù)
- 請(qǐng)求參數(shù)
- 響應(yīng)參數(shù)
-
以 獲取實(shí)時(shí)天氣作為示例:
API的方法和URL:GET, https://api.seniverse.com/v3/weather/now.json
-
API的參數(shù):
-
請(qǐng)求參數(shù):
參數(shù)名 參數(shù)類型 參數(shù)意義 是否必選 key string 你的API密鑰 true location string 查詢的地理位置 true language string 結(jié)果表示的語言 false,默認(rèn)簡(jiǎn)體中文 unit string 結(jié)果表示的單位(華氏度,攝氏度) false,默認(rèn)攝氏度 -
響應(yīng)參數(shù):
參數(shù)名 參數(shù)類型 參數(shù)意義 location 對(duì)象:包括id, name, country, time_zone, time_zone_offset now 對(duì)象:包括 text,code, temperature, feel_like... last_update 日期 -
用Postman開始測(cè)試
new tab 中輸入 方式,和URL
點(diǎn)擊 Params 設(shè)置參數(shù)
點(diǎn)擊 send 開始發(fā)送請(qǐng)求
-
查看請(qǐng)求結(jié)果是否有輸出,格式是否和上述的響應(yīng)參數(shù)對(duì)應(yīng)
{ "results": [ { "location": { "id": "WS10730EM8EV", "name": "Shenzhen", "country": "CN", "path": "Shenzhen,Shenzhen,Guangdong,China", "timezone": "Asia/Shanghai", "timezone_offset": "+08:00" }, "now": { "text": "Cloudy", "code": "4", "temperature": "25" }, "last_update": "2017-05-09T10:05:00+08:00" } ] }?
-
編輯 Tests 頁面,添加斷言。
var jsonData = JSON.parse(responseBody); tests["檢查城市名稱"] = jsonData.results[0].location.name === "Shenzhen";
-
-
使用Postman 登錄然之系統(tǒng),測(cè)試登錄接口
使用然之 4.2 或者以上版本
-
修改然之系統(tǒng) 配置文件
C:\xampp5\htdocs\ranzhi\config\my.php,在最后添加一行配置,如下圖:修改 然之 配置文件$config->notEncryptedPwd = true; 重啟 Apache
-
打開 Chrome,輸入然之的網(wǎng)址,打開登錄頁面
Chrome 打開登錄頁面 打開 Fiddler,并設(shè)置 Chrome 進(jìn)行抓包
在 Chrome 中進(jìn)行登錄,提交用戶名和密碼
-
在 Fiddler 中捕獲剛剛的登錄 POST 請(qǐng)求
Fiddler 抓包登錄 POST -
打開 Postman,新建 URL,POST方法。
需要設(shè)置 Postman,點(diǎn)擊 File | Settings,進(jìn)行設(shè)置
settingsSetting 2 -
在 Postman 輸入剛剛 Fiddler 請(qǐng)求的 POST 的 URL
Fiddler 抓包分析輸入上述 URL
URL 在 Fiddler 中復(fù)制請(qǐng)求的第二行到空行之間的 消息報(bào)頭(Head),Postman 輸入 Head
Head 1Head2.png-
在 Fiddler 中復(fù)制請(qǐng)求的正文,在 Postman 中 body 選擇 raw,并輸入
輸入 Body -
在 Postman 的test 中輸入以下測(cè)試內(nèi)容:
輸入斷言var jsonData = JSON.parse(responseBody); tests["檢查locate"] = jsonData.locate === "\/sys\/index.html"; tests["檢查result"] = jsonData.result === "success"; tests["Status code is 200"] = responseCode.code === 200; -
在 Chrome 中退出登錄,注意此步驟很重要,退出以后才能夠進(jìn)行 Postman 登錄
退出 然之 -
在 Postman 中點(diǎn)擊 Send,進(jìn)行測(cè)試
測(cè)試結(jié)果 -
查看 Postman 的運(yùn)行結(jié)果。
?
result.png
5. Web 接口的認(rèn)證
Web 接口測(cè)試的準(zhǔn)備
- HTTP協(xié)議的請(qǐng)求和響應(yīng)
請(qǐng)求:GET/POST
響應(yīng):html/JSON/XML/CSS/JavaScript/png.. - 測(cè)試的概念
斷言:檢查返回的響應(yīng)里面的內(nèi)容。
測(cè)試設(shè)計(jì):根據(jù)請(qǐng)求的參數(shù)來設(shè)計(jì)用例 - 讀懂接口的文檔
請(qǐng)求的方式和URL
請(qǐng)求的參數(shù)和響應(yīng)的參數(shù) - 在請(qǐng)求接口時(shí)使用認(rèn)證
basic authorization 基礎(chǔ)認(rèn)證,輸入用戶名和密碼
在上面四個(gè)的基礎(chǔ)上,注意Web 接口需要認(rèn)證,尤其是支付業(yè)務(wù),這里用一個(gè)例子,并且是POST請(qǐng)求 + Basic Auth 認(rèn)證,來闡述此部分。
示例的步驟:
-
打開 https://www.pingxx.com/ Ping++ 在線支付網(wǎng)站,注冊(cè)一個(gè)賬號(hào),并登錄,會(huì)自動(dòng)創(chuàng)建一個(gè)應(yīng)用。
Snap27.png 進(jìn)入自動(dòng)創(chuàng)建的應(yīng)用,進(jìn)入應(yīng)用的控制面板界面。
-
獲取
APP[id],按如圖的方式獲取到,并等下使用Snap28.png -
獲取
Test Secret Key,按照如圖的方式獲取到,并依舊等下使用Snap29.pngSnap30.png -
按照下操作,查閱 API 文檔,并開始測(cè)試。
Snap31.png
Snap32.png
Snap33.png -
選擇 Charge,創(chuàng)建一個(gè) 支付訂單,查閱 API 文檔的請(qǐng)求參數(shù),響應(yīng)參數(shù),依舊 方法和URL
Snap34.png -
在Postman 中創(chuàng)建新的測(cè)試,輸入 POST 和 URL
Snap35.png -
設(shè)置參數(shù),其中需要用到 APP[id],為之前步驟獲取到的。
Snap36.png -
在 請(qǐng)求中使用 認(rèn)證,Basic Auth,輸入 之前步驟獲取到的 Test Secret Key,作為用戶名。
Snap37.png
Snap38.png 添加測(cè)試斷言。
用 JavaScript腳本,查詢 JSON 對(duì)象的值,并做檢查。點(diǎn)擊右側(cè)的現(xiàn)成菜單,會(huì)自動(dòng)生成檢查 JSON 的框架。
var jsonData = JSON.parse(responseBody);
tests["檢查object值"] = jsonData.object === "charge";
tests["檢查order_no值"] = jsonData.order_no === "99887766554433221100";
tests["檢查amount值"] = jsonData.amount === 9900;
?

-
點(diǎn)擊 Send 開始測(cè)試。
Snap40.png
- 示例2:創(chuàng)建紅包的Web 接口測(cè)試
-
微信紅包支付接口測(cè)試的接口描述
創(chuàng)建紅包的Web接口描述 -
在 Postman 中輸入 POST 方法和 URL
Paste_Image.png -
在 Postman 中 使用 Http Basic Auth 認(rèn)證。輸入之前獲取的 Secret_test_key。根據(jù) API文檔進(jìn)行的操作
Paste_Image.png在 Postman 中操作
Paste_Image.pngPaste_Image.png -
輸入 請(qǐng)求的參數(shù),注意 POST 請(qǐng)求的請(qǐng)求參數(shù),輸入到 Body 中
?
輸入正文 -
在 Test 設(shè)置斷言,剛才說要設(shè)置 Object 的驗(yàn)證。
輸入以下內(nèi)容:
斷言var jsonData = JSON.parse(responseBody); tests["檢查 Object 屬性"] = jsonData.object === "red_envelope"; tests["檢查 金額 屬性"] = jsonData.amount === 6000;?
-
點(diǎn)擊Send,檢查。
結(jié)果 -
到管理平臺(tái)查看訂單結(jié)果。
Paste_Image.png
6. Postman 的其他功能
Postman 支持導(dǎo)出用例以及賬戶的同步功能。

接口實(shí)例:
天氣預(yù)報(bào)接口:
接口URL: http://www.webxml.com.cn/WebServices/WeatherWebService.asmx
網(wǎng)絡(luò)服務(wù)描述語言: http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl
該接口有5個(gè)方法:
- getSupportCity()
- getSupportDataSet()
- getSupportProvince()
- getWeatherbyCityName()
- getWeatherbyCityNamePro()-
通過輸入?yún)?shù),可以調(diào)用這些接口,并得到請(qǐng)求的數(shù)據(jù)。
查詢本天氣預(yù)報(bào)Web Services支持的國內(nèi)外城市或地區(qū)信息:
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getSupportCity?byProvinceName=廣東
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getSupportCity?byProvinceName=北京
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getSupportCity?byProvinceName=上海
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getSupportCity?byProvinceName=湖北
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getSupportCity?byProvinceName=河南查詢獲得本天氣預(yù)報(bào)Web Services支持的洲、國內(nèi)外省份和城市信息
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getSupportDataSet
查詢獲得本天氣預(yù)報(bào)Web Services支持的洲、國內(nèi)外省份和城市信息
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getSupportProvince
查詢獲得根據(jù)城市或地區(qū)名稱查詢獲得未來三天內(nèi)天氣情況、現(xiàn)在的天氣實(shí)況、天氣和生活指數(shù)
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getWeatherbyCityName?theCityName=深圳
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getWeatherbyCityName?theCityName=59493
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getWeatherbyCityName?theCityName=北京
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getWeatherbyCityName?theCityName=54511
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getWeatherbyCityName?theCityName=上海
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getWeatherbyCityName?theCityName=58367
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getWeatherbyCityName?theCityName=香港
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getWeatherbyCityName?theCityName=45005
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getWeatherbyCityName?theCityName=Chicago
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getWeatherbyCityName?theCityName=72530
7. Python requests 的使用
Postman 作為工具,有UI的工具可以完整的操作 Web API(Application Programming Interface),有些場(chǎng)景,還需要在自動(dòng)化測(cè)試方案中操作 Web API。對(duì)于 Python 來說有兩種主流的工具操作 HTTP Web API。
- urllib (python 自帶的,但是語法反人類)
- requests (第三方的,但是 HTTP Request for human),我們推薦這個(gè) requests 工具。
和 Selenium 一樣,requests 也是第三方的工具庫。類比 Selenium 操作瀏覽器,requests 操作 HTTP 請(qǐng)求。
部署 requests 的過程
pip install requests
requests 有兩個(gè)常見的方法
- requests.get()
- requests.post()
上面兩個(gè)方法都會(huì)返回一個(gè) Response 類的對(duì)象。注意 Response 類 屬于 requests。
作為自動(dòng)化接口測(cè)試工具,類似于 Selenium,我們需要 用 Page-Object 方式進(jìn)行設(shè)計(jì)
- 每個(gè) Page 寫一個(gè) URL 的功能。
- get_realtime_weather_by_ip
- get_realtime_weather_by_city
- get_realtime_weather_by_location
- ... 單位
- ... 語言
- 每個(gè) page 都不可以 直接用 requests
- 封裝 requests 到 box_requests.py
- 創(chuàng)建一個(gè)類,用來從封裝的 box_requests.py 中返回我們定制的 結(jié)果(響應(yīng))
- 在每個(gè)用例中,繼承 unittest.TestCase,調(diào)用 Page,進(jìn)行測(cè)試
- 測(cè)試用的數(shù)據(jù)還是應(yīng)該抽出來,放到 csv 或者 數(shù)據(jù)庫中
8. 簡(jiǎn)單的GET請(qǐng)求實(shí)例
- 天氣實(shí)況
GET /weather/now.json
獲取指定城市的天氣實(shí)況。付費(fèi)用戶可獲取全部數(shù)據(jù),免費(fèi)用戶只返回天氣現(xiàn)象文字、代碼和氣溫3項(xiàng)數(shù)據(jù)。注:中國城市暫不支持云量和露點(diǎn)溫度。
請(qǐng)求地址示例
參數(shù)
-
key
你的API密鑰
-
location
所查詢的位置參數(shù)值范圍:
城市ID例如:location=WX4FBXXFKE4F城市中文名例如:location=北京省市名稱組合例如:location=遼寧朝陽、location=北京朝陽城市拼音/英文名例如:location=beijing(如拼音相同城市,可在之前加省份和空格,例:shanxi yulin)經(jīng)緯度例如:location=39.93:116.40(緯度前經(jīng)度在后,冒號(hào)分隔)IP地址例如:location=220.181.111.86(某些IP地址可能無法定位到城市)“ip”兩個(gè)字母自動(dòng)識(shí)別請(qǐng)求IP地址,例如:location=ip -
language
語言 (可選)參數(shù)值范圍:點(diǎn)此查看
-
unit
單位 (可選)參數(shù)值范圍:
c當(dāng)參數(shù)為c時(shí),溫度c、風(fēng)速km/h、能見度km、氣壓mbf當(dāng)參數(shù)為f時(shí),溫度f、風(fēng)速mph、能見度mile、氣壓inch默認(rèn)值:c
返回結(jié)果 200
{
"results": [{
"location": {
"id": "C23NB62W20TF",
"name": "西雅圖",
"country": "US",
"timezone": "America/Los_Angeles",
"timezone_offset": "-07:00"
},
"now": {
"text": "多云", //天氣現(xiàn)象文字
"code": "4", //天氣現(xiàn)象代碼
"temperature": "14", //溫度,單位為c攝氏度或f華氏度
"feels_like": "14", //體感溫度,單位為c攝氏度或f華氏度
"pressure": "1018", //氣壓,單位為mb百帕或in英寸
"humidity": "76", //相對(duì)濕度,0~100,單位為百分比
"visibility": "16.09", //能見度,單位為km公里或mi英里
"wind_direction": "西北", //風(fēng)向文字
"wind_direction_degree": "340", //風(fēng)向角度,范圍0~360,0為正北,90為正東,180為正南,270為正西
"wind_speed": "8.05", //風(fēng)速,單位為km/h公里每小時(shí)或mph英里每小時(shí)
"wind_scale": "2", //風(fēng)力等級(jí),請(qǐng)參考:http://baike.baidu.com/view/465076.htm
"clouds": "90", //云量,范圍0~100,天空被云覆蓋的百分比 #目前不支持中國城市#
"dew_point": "-12" //露點(diǎn)溫度,請(qǐng)參考:http://baike.baidu.com/view/118348.htm #目前不支持中國城市#
},
"last_update": "2015-09-25T22:45:00-07:00" //數(shù)據(jù)更新時(shí)間(該城市的本地時(shí)間)
}]
}
具體的步驟:
-
封裝 requests 到
box_requests.pyimport requests from model.http_response import HttpResponse class BoxRequests: def get(self, url, param): """ 用 Get 的方式請(qǐng)求 URL :param url: :param param: 參數(shù) :return: model 中的 HttpResponse 類的對(duì)象 """ r = requests.get(url, param) http_response = HttpResponse() http_response.status_code = r.status_code http_response.json_dict = r.json() return http_response?
-
創(chuàng)建一個(gè)文件夾 model,在里面創(chuàng)建一個(gè)類
HttpResponseclass HttpResponse: status_code = None json_dict = None?
-
創(chuàng)建一個(gè) page :
senivers_realtime_weather_page.pyfrom base.box_requests import BoxRequests class SeniversRealtimeWeatherPage: base_url = "/weather/now.json" def get_weather_by_ip(self, host, api_key): """ 根據(jù)IP地址所在的地方查詢天氣 :param host: :param api_key: :return: 自定義的 HttpResponse 類的對(duì)象 """ br = BoxRequests() # 創(chuàng)建一個(gè)字典,用來傳參數(shù) param = { "key": api_key, "location": "ip" } # 用 host 和 全局 base_url 拼成 URL http_response = br.get(host + self.base_url, param) return http_response?
-
創(chuàng)建一個(gè) case :
seniverse_api_tests.pyimport unittest from pages.api.senivers_realtime_weather_page import SeniversRealtimeWeatherPage
class SeniverseApiTests(unittest.TestCase):
api_key = None
page = None
host = None
def setUp(self):
self.api_key = "MJX11XSAPG"
self.host = "https://api.seniverse.com/v3"
self.page = SeniversRealtimeWeatherPage()
def test_query_realtime_weather_by_ip(self):
r = self.page.get_weather_by_ip(self.host, self.api_key)
self.assertEqual(200, r.status_code, "狀態(tài)碼返回不正確!")
expected_city = "深圳"
actual_city = r.json_dict["results"][0]["location"]["name"]
self.assertEqual(expected_city, actual_city, "城市名稱與ip不相符合")
if name == "main":
unittest.main()
?
## 9. 簡(jiǎn)單的 POST 請(qǐng)求實(shí)例
1. 封裝 Requests.post()方法
1. 傳遞 url
2. 傳遞 data
3. 傳遞 headers
2. 創(chuàng)建 PingChargeCreatePage 類
1. create()
2. ...
3. 創(chuàng)建 用例
示例如下:
### 創(chuàng)建 Charge 對(duì)象
請(qǐng)求:POST `https://api.pingxx.com/v1/charges`
發(fā)起一次支付請(qǐng)求時(shí)需要?jiǎng)?chuàng)建一個(gè)新的 `charge` 對(duì)象,獲取一個(gè)可用的支付憑據(jù)用于客戶端向第三方渠道發(fā)起支付請(qǐng)求。如果使用測(cè)試模式的 API Key,則不會(huì)發(fā)生真實(shí)交易。當(dāng)支付成功后,Ping++ 會(huì)發(fā)送 Webhooks 通知。
| 請(qǐng)求參數(shù) | |
| ------------------------------------ | ---------------------------------------- |
| order_no**REQUIRED** | 商戶訂單號(hào),適配每個(gè)渠道對(duì)此參數(shù)的要求,必須在商戶系統(tǒng)內(nèi)唯一。( `alipay` : 1-64 位, `wx` : 2-32 位, `bfb` : 1-20 位, `upacp` : 8-40 位, `yeepay_wap` :1-50 位, `jdpay_wap` :1-30 位, `qpay` :1-30 位, `cmb_wallet` :10 位純數(shù)字字符串。注:除 `cmb_wallet` 外的其他渠道推薦使用 8-20 位,要求數(shù)字或字母,不允許特殊字符)。 |
| app [ id ]**EXPANDABLE****REQUIRED** | 支付使用的 `app` 對(duì)象的 `id` , `expandable` 可展開,查看 [如何獲取App ID](https://help.pingxx.com/article/198599) 。 |
| channel**REQUIRED** | 支付使用的第三方支付渠道。參考 [支付渠道屬性值](https://www.pingxx.com/api#%E6%94%AF%E4%BB%98%E6%B8%A0%E9%81%93%E5%B1%9E%E6%80%A7%E5%80%BC) 。 |
| amount**REQUIRED** | 訂單總金額(必須大于0),單位為對(duì)應(yīng)幣種的最小貨幣單位,人民幣為分。如訂單總金額為 1 元, `amount` 為 100,么么貸商戶請(qǐng)查看申請(qǐng)的借貸金額范圍。 |
| client_ip**REQUIRED** | 發(fā)起支付請(qǐng)求客戶端的 IPv4 地址,如: 127.0.0.1。 |
| currency**REQUIRED** | 三位 ISO 貨幣代碼,目前僅支持人民幣 `cny` 。 |
| subject**REQUIRED** | 商品的標(biāo)題,該參數(shù)最長(zhǎng)為 32 個(gè) Unicode 字符,銀聯(lián)全渠道( `upacp` / `upacp_wap` )限制在 32 個(gè)字節(jié)。 |
| body**REQUIRED** | 商品的描述信息,該參數(shù)最長(zhǎng)為 128 個(gè) Unicode 字符,yeepay_wap 對(duì)于該參數(shù)長(zhǎng)度限制為 100 個(gè) Unicode 字符。 |
| extra*optional* | 特定渠道發(fā)起交易時(shí)需要的額外參數(shù),以及部分渠道支付成功返回的額外參數(shù),詳細(xì)參考 [支付渠道 extra 參數(shù)說明](https://www.pingxx.com/api#%E6%94%AF%E4%BB%98%E6%B8%A0%E9%81%93-extra-%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E) 。 |
| time_expire*optional* | 訂單失效時(shí)間,用 Unix 時(shí)間戳表示。時(shí)間范圍在訂單創(chuàng)建后的 1 分鐘到 15 天,默認(rèn)為 1 天,創(chuàng)建時(shí)間以 Ping++ 服務(wù)器時(shí)間為準(zhǔn)。 微信對(duì)該參數(shù)的有效值限制為 2 小時(shí)內(nèi);銀聯(lián)對(duì)該參數(shù)的有效值限制為 1 小時(shí)內(nèi)。 |
| metadata*optional* | 參考 [元數(shù)據(jù)](https://www.pingxx.com/api#%E5%85%83%E6%95%B0%E6%8D%AE) 。 |
| description*optional* | 訂單附加說明,最多 255 個(gè) Unicode 字符。 |
**返回**
返回一個(gè)支付憑據(jù) `charge` 對(duì)象。鑒于支付渠道對(duì) `order_no` 的合法性要求,為了保證支付請(qǐng)求的正確處理,請(qǐng)務(wù)必保證對(duì)于同一支付渠道下,不同支付產(chǎn)品間 `order_no` 的唯一性。例如:已在微信公眾號(hào)下使用的 `order_no` 則無法在微信支付以及微信公眾號(hào)掃碼下重復(fù)使用,該規(guī)則同樣適用于其他同類渠道。如果發(fā)生錯(cuò)誤,則會(huì)返回錯(cuò)誤碼和錯(cuò)誤詳情,詳見 [錯(cuò)誤](https://www.pingxx.com/api#%E9%94%99%E8%AF%AF)。
根據(jù) Postman 執(zhí)行這個(gè)測(cè)試的情況。選擇以下的數(shù)據(jù):
- headers
- data:params
把上述的兩個(gè)數(shù)據(jù),變成Python 的字典傳遞到 requests.post() 中,
檢查得到的響應(yīng)中的 Json 對(duì)象的值。
1. 修改 box_requests,添加 post_json方法
```python
def post_json(self, url, data=None, json=None, **kwargs):
"""
用 POST 的方式請(qǐng)求 URL
:param url:
:param data: 提交的數(shù)據(jù)
:param json: 提交的 json (可選)
:param kwargs: 額外的參數(shù)
:return:
"""
r = requests.post(url, data, json, **kwargs)
http_response = HttpResponse()
http_response.status_code = r.status_code
http_response.json_dict = r.json()
return http_response
-
創(chuàng)建 page,為測(cè)試用例服務(wù)
class PingxxChargeCreatePage: base_url = "/charges" def create_charge(self, host, data, headers): br = BoxRequests() # 用 host 和 全局 base_url 拼成 URL http_response = br.post_json(host + self.base_url, data=data, headers=headers) return http_response?
-
創(chuàng)建 test_case
import unittest from pages.api.pingxx_charge_create_page import PingxxChargeCreatePage class PingxxApiTests(unittest.TestCase): test_secret_key = None app_id = None page = None host = None def setUp(self): self.app_id = "app_rfv1SGmPKijLnPef" self.test_secret_key = "c2tfdGVzdF80bXpqelRpenpQQ0NqVEt5VEN5VGVqYlA6" self.host = "https://api.pingxx.com/v1" self.page = PingxxChargeCreatePage() def test_create_charge_by_wechat(self): data = { "order_no": "88888888666666664444444422222222", "app[id]": self.app_id, "channel": "wx", "amount": 10000000, "client_ip": "192.168.1.202", "currency": "cny", "subject": "iphone 999 正品行貨", "body": "正規(guī)的水貨 iphone 8 1000臺(tái)", "description": "iphone 8 一打。。。。訂單附加說明,最多 255 個(gè) Unicode 字符。" } headers = {"Authorization": "Basic %s" % self.test_secret_key} r = self.page.create_charge(self.host, data, headers) self.assertEqual(200, r.status_code, "狀態(tài)碼返回不正確!") expected_object = "charge" actual_object = r.json_dict["object"] self.assertEqual(expected_object, actual_object, "對(duì)象是否為支付檢查失??!")
if __name__ == "__main__":
unittest.main()
```
?






































