[接口測試_B] 14 pytest+requests實戰(zhàn)練習2-參數(shù)化

上一篇:http://www.reibang.com/p/d75f24e5de29

上一篇在一個py文件中厨钻,寫了一堆test_開頭的方法,所有數(shù)據(jù)和用例都在一個py文件中跌前,本篇嘗試讀取json文件的測試數(shù)據(jù),執(zhí)行用例。

技術(shù)準備

  • httpbin:安裝信息見上一篇
  • json:掌握json支持的數(shù)據(jù)格式和json的序列化操作
  • pytest:pytest的參數(shù)化方式
  • requests:requests是如何發(fā)送http請求的


    image.png

1翎卓、準備json格式的數(shù)據(jù)

  • httpbin中的示例接口都是比較簡單的, 都沒業(yè)務(wù)邏輯的關(guān)聯(lián)啥的,按照requests.Request中要傳入的參數(shù)準備的數(shù)據(jù)摆寄。
  • 可以把interface_info中的一個字典當作一個測試用例的數(shù)據(jù)失暴。
# data.json
{
  "TestHttpMethods":
    {
      "interface_info": [
        {
          "interface_method": "get",
          "method": "get",
          "headers": null,
          "url_data": null,
          "data": {"test": "testdata"},
          "params": null,
          "auth": null,
          "cookies": null,
          "hooks": null,
          "json": null,
          "except": [200]
        },
        {
          "interface_method": "post",
          "method": "post",
          "headers": null,
          "url_data": null,
          "data": {"test": "testdata"},
          "params": null,
          "auth": null,
          "cookies": null,
          "hooks": null,
          "json": null,
          "except": [200]
        }
      ]
    },
  "TestAuth":
    {
      "interface_info": [
        {
          "interface_method": "basic-auth",
          "method": "get",
          "headers": null,
          "url_data": ["testuser", "testpasswd"],
          "data": null,
          "params": null,
          "auth": ["testuser", "testpasswd"],
          "cookies": null,
          "hooks": null,
          "json": null,
          "except": [200]
        },
        {
          "interface_method": "bearer",
          "method": "get",
          "headers": {"Authorization": "justtestauth"},
          "url_data": null,
          "data": null,
          "params": null,
          "auth": null,
          "cookies": null,
          "hooks": null,
          "json": null,
          "except": [200]
        }
      ]
    }
}

2、讀取json文件中的數(shù)據(jù)

  • get_case(): 用于讀取json文件中的數(shù)據(jù)微饥,并保存為字典格式逗扒,最后用yield返回一個生成器
  • get_data(): 用于解析字典中的數(shù)據(jù),由于后續(xù)要采用pytest中的@pytest.mark.parametrize進行參數(shù)化欠橘,所以把每組數(shù)據(jù)都保持在一個元組中矩肩,元組存于列表中
# conftest.py
import sys
sys.path.append('.')

import json, codecs, os
print(os.getcwd())

def get_case():
    with codecs.open('data.json', 'r', encoding='utf-8') as f:
        f_dict = json.load(f)
        for collection, cases in f_dict.items():
            for case in cases['interface_info']:
                yield {collection: case}

def get_data():
    cases = get_case()
    datas = []
    for case_d in cases:
        for collection, case in case_d.items():
            url_method = case['interface_method']
            method = case['method']
            headers = case["headers"]
            url_data = case['url_data'] # if case['url_data'] is None else tuple(case['url_data'])
            data = case['data']
            params = case['params']
            auth = case['auth']
            cookies = case['cookies']
            hooks = case['hooks']
            json = case['json']
            except_data = case['except']
            t = (url_method, method, headers, url_data, data, params, auth, cookies, hooks, json, except_data)
            datas.append(t)

    return datas

結(jié)果:

print(type(get_case()))
print(get_data())
<class 'generator'>
[('get', 'get', None, None, {'test': 'testdata'}, None, None, None, None, None, [200]), 
('post', 'post', None, None, {'test': 'testdata'}, None, None, None, None, None, [200]), 
('basic-auth', 'get', None, ['testuser', 'testpasswd'], None, None, ['testuser', 'testpasswd'], None, None, None, [200]), 
('bearer', 'get', {'Authorization': 'justtestauth'}, None, None, None, None, None, None, None, [200])]

3、重寫一下requests的請求方法

  • 由于在json文件中肃续,寫入了接口路徑的path部分和接口的請求方法黍檩,所以選擇requests.Request()方法發(fā)送請求叉袍,參照Request的源碼,將需要傳入的參數(shù)都在__init__()構(gòu)造方法中進行初始化
  • 可以看到__init__()中用了非常經(jīng)典的三語表達式
  • 因為url_data和auth在json中傳入的是列表刽酱,但是參數(shù)需要的實際格式是元組畦韭,所以當傳入的參數(shù)不是None時,需要轉(zhuǎn)換為元組
  • 這個文件中肛跌,導(dǎo)入了一個config.py文件艺配,里面現(xiàn)在就一個參數(shù)BASE_URL = 'http://192.168.68.128:8088/',主要用于存儲一些配置信息(如果后面發(fā)郵件或者連數(shù)據(jù)庫啥的,配置信息也可以寫在這里面)
  • url拼接:httpbin中衍慎,某些接口的url需要傳入與auth數(shù)據(jù)一致的信息转唉,所以采用urljoin進行拼接
# httpmethods.py
import sys
sys.path.append('.')
from urllib.parse import urljoin

import requests
from requests import Request, Session

import config

# print(config.BASE_URL)
class Http:
    def __init__(self,
                 method=None, url=None, headers=None, files=None, data=None,
                 params=None, auth=None, cookies=None, hooks=None, json=None,
                 base_url=None, url_method=None, url_data=None):
        # Default empty dicts for dict params.
        data = [] if data is None else data
        files = [] if files is None else files
        headers = {} if headers is None else headers
        params = {} if params is None else params
        hooks = {} if hooks is None else hooks
        url_data = () if url_data is None else tuple(url_data)
        auth = None if auth is None else tuple(auth)

        self.hooks = requests.hooks.default_hooks()
        type(hooks)
        for (k, v) in list(hooks.items()):
            Request.register_hook(event=k, hook=v)

        self.method = method
        self.url = url
        self.headers = headers
        self.files = files
        self.data = data
        self.json = json
        self.params = params
        self.auth = auth
        self.cookies = cookies
        self.base_url = base_url
        self.url_method = url_method
        self.url_data = url_data

    def method_new(self):
        self.base_url = config.BASE_URL
        s = Session()
        url = urljoin(self.base_url, '/'.join((self.url_method,) + self.url_data))
        print(url)
        req = Request(method=self.method.upper(), url=url, headers=self.headers,
                    files=self.files, data=self.data, params=self.params, auth=self.auth,
                    cookies=self.cookies, json=self.json)
        prepped = req.prepare()
        # 如果需要設(shè)置代理,可以在s.send中添加并進行配置, 詳情查看send的源碼
        resp = s.send(prepped)
        return resp

4稳捆、采用pytest進行參數(shù)化

  • 導(dǎo)入前面準備的文件赠法,采用pytest.mark.parametrize進行參數(shù)化
  • 實例化重寫的請求發(fā)送方式,并傳入?yún)?shù)化數(shù)據(jù)
  • 發(fā)送請求乔夯,接收結(jié)果并進行斷言
# test_run.py
import sys
sys.path.append('.')

import pytest

from httpmethods import Http
import conftest

@pytest.mark.parametrize("url_method, method, headers, url_data, data, params, auth, cookies, hooks, json, except_data",
                         conftest.get_data())
def test_case(url_method, method, headers, url_data, data, params, auth, cookies, hooks, json, except_data):
    h = Http(method=method, url_method=url_method, headers=headers,
             url_data=url_data, data=data, params=params, auth=auth,
             cookies=cookies, hooks=hooks, json=json)
    r = h.method_new()
    assert r.status_code == except_data[0]

5砖织、運行pytest命令,執(zhí)行用例生成測試報告

pytest -q --tb=no --html=./report.html

總結(jié)

  • 往前的一小步:學會了json文件的讀取末荐,雖然我覺得之前也是會的侧纯,但是在實際練習過程中發(fā)現(xiàn),對json支持的數(shù)據(jù)類型與python之間的轉(zhuǎn)換認識得仍然不夠深入:


    image.png
  • 不足之處:
    1甲脏、從json文件可以看出眶熬,TestHttpMethods和TestAuth存在的目的是想要表示一個測試集,但是在用例實際執(zhí)行過程中沒有體現(xiàn)出來块请,對于pytest的使用不熟練娜氏,還不知道應(yīng)該如何結(jié)合起來;
    2墩新、在命令行中使用pytest的命令執(zhí)行用例的方式不夠靈活贸弥;
    3、郵件發(fā)送海渊、定時任務(wù)執(zhí)行等等绵疲,都是必要的。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末切省,一起剝皮案震驚了整個濱河市最岗,隨后出現(xiàn)的幾起案子帕胆,更是在濱河造成了極大的恐慌朝捆,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件懒豹,死亡現(xiàn)場離奇詭異芙盘,居然都是意外死亡驯用,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門儒老,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蝴乔,“玉大人,你說我怎么就攤上這事驮樊∞闭” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵囚衔,是天一觀的道長挖腰。 經(jīng)常有香客問我,道長练湿,這世上最難降的妖魔是什么猴仑? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮肥哎,結(jié)果婚禮上辽俗,老公的妹妹穿的比我還像新娘。我一直安慰自己篡诽,他們只是感情好崖飘,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著杈女,像睡著了一般坐漏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上碧信,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天赊琳,我揣著相機與錄音,去河邊找鬼砰碴。 笑死躏筏,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的呈枉。 我是一名探鬼主播趁尼,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼猖辫!你這毒婦竟也來了酥泞?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤啃憎,失蹤者是張志新(化名)和其女友劉穎芝囤,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡悯姊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年羡藐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片悯许。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡仆嗦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出先壕,到底是詐尸還是另有隱情瘩扼,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布垃僚,位于F島的核電站邢隧,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏冈在。R本人自食惡果不足惜倒慧,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望包券。 院中可真熱鬧纫谅,春花似錦、人聲如沸溅固。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽侍郭。三九已至询吴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間亮元,已是汗流浹背猛计。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留爆捞,地道東北人奉瘤。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像煮甥,于是被迫代替她去往敵國和親盗温。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容