python接口自動化-實戰(zhàn)(第二階段)

再次強(qiáng)調(diào),因為視頻中實戰(zhàn)地址已無法訪問,建議大家根據(jù)原理,用自己公司的業(yè)務(wù)邏輯、代碼來練手。本人公司使用pyhon2.7,所以語法可能與3.x不同

目標(biāo)

  • 復(fù)習(xí)單元測試:引入單元測試、html測試報告、斷言結(jié)果
  • 引入超繼承(二選一)
  • 引入ddt(二選一)
  • 添加一個字段存入測試結(jié)果
  • 引入try...except...finally
  • 完成用例的可配置化,想跑哪條用例,通過配置文件配置好
  • 難點(diǎn):
    • 同時跑多個模塊怎么跑

復(fù)習(xí)單元測試

使用unittest,測試我們自己封裝的http請求類-HttpRequest,目的一:學(xué)習(xí)如何進(jìn)行單元測試,目的二:寫出咱們的各個接口。

  • 新建test_http_request.py編寫測試用例

    import json
    import unittest
    from common.public.http_request import HttpRequest
    
    class TestHttpRequest(unittest.TestCase):
    
        def setUp(self):
            pass
    
        def tearDown(self):
            pass
        
        #登錄接口
        def test_login(self): 
            payload = {"user_phone": "1801923****", "device_model": "iphone7"}
            res=HttpRequest().http_request("1.6.0", "android", "785c6fee0e4488ca412a5afc9a00e9d8","/login","post",payload)
            self.assertEqual(200,res.status_code)  #添加斷言
            print ("獲得的結(jié)果是:",res.json()) 
    
  • run.py文件中加載用例、執(zhí)行用例

    import unittest
    from common.public.test_http_request import TestHttpRequest
    
    suite=unittest.TestSuite()
    suite.addTest(TestHttpRequest("test_login")) #添加用例
    
    #執(zhí)行用例
    runner=unittest.TextTestRunner()
    runner.run(suite)
    
  • 使用HTMLTestRunner生成HTML測試報告

    下載地址:http://tungwaiyip.info/software/HTMLTestRunner.html

    使用:

      - HTMLTestRunner是Python標(biāo)準(zhǔn)庫的unittest模塊的擴(kuò)展,無法通過pip安裝
      - 下載HTMLTestRunner.py放在lib目錄下
      - 導(dǎo)入模塊 `import HTMLTestRunner`
    

    注意點(diǎn):

    代碼改造為使用HTMLTestRunner生成HTML測試報告:

    # encoding:utf-8
    
    import sys
    reload(sys)
    sys.setdefaultencoding('utf8') #python2.7需要添加,否則會因編碼問題報錯
    
    import HTMLTestRunner
    import unittest
    from common.public.test_http_request import TestHttpRequest
    
    suite=unittest.TestSuite()
    suite.addTest(TestHttpRequest("test_login")) #添加用例
    
    with open("test_result/rusult.html","wb") as file:
        #執(zhí)行用例
        runner=HTMLTestRunner.HTMLTestRunner(stream=file,verbosity=2,title="測試HttpRequest類")
        runner.run(suite)
    

    獲得的html格式的測試報告:

    image

引入ddt

引入ddt的目的是為了數(shù)據(jù)分離、數(shù)據(jù)驅(qū)動測試。所謂數(shù)據(jù)驅(qū)動,從它的定義來看,就是數(shù)據(jù)的改變從而驅(qū)動自動化測試的執(zhí)行,最終引起測試結(jié)果的改變。說的直白些,就是參數(shù)化的應(yīng)用。值得注意的是,ddt適用于測試數(shù)據(jù)是列表嵌套列表或者列表嵌套字典。

  • 給測試數(shù)據(jù)中新增一列expected,用于添加斷言的預(yù)期結(jié)果


    image
  • 修改do_excel.py,讀取expected的數(shù)據(jù):

    get_data()方法中新增:sub_data["expected"] = sheet.cell(i, 6).value
    write_back_data()方法中修改:sheet.cell(i,7).value=value

  • 改造測試用例test_http_request.py

    import unittest
    from common.public.http_request import HttpRequest
    from ddt import ddt,data
    from common.public.do_excel import DoExcel
    
    test_data=DoExcel().get_data("../../test_data/test_data.xlsx","Sheet1")
    
    @ddt
    class TestHttpRequest(unittest.TestCase):
    
        def setUp(self):
            pass
    
        def tearDown(self):
            pass
        @data(*test_data)
        def test_login(self,item): #添加item,即測試數(shù)據(jù)
            res=HttpRequest().http_request(item["url"],item["method"],eval(item["payload"]))
            self.assertEqual(str(item["expected"]),str(res.status_code))
            print "獲得的結(jié)果是:",res.json()
    
  • 改造run.py

    import HTMLTestRunner
    import unittest
    from common.public.test_http_request import TestHttpRequest
    
    suite=unittest.TestSuite()
    loader=unittest.TestLoader()
    suite.addTest(loader.loadTestsFromTestCase(TestHttpRequest))
    
    with open("test_result/rusult.html","wb") as file:
        #執(zhí)行用例
        runner=HTMLTestRunner.HTMLTestRunner(stream=file,verbosity=2,title="測試HttpRequest類")
        runner.run(suite)
    
    • 問題:因為test_http_request.pyrun.py不是一個層級,所以這樣運(yùn)行run.py會報錯,找不到test_data.xlsx,所以在test_http_request.py中的test_data地址改為絕對路徑。but,如果設(shè)置為絕對路徑,那么在自己電腦上能跑,在別人電腦上可能會失敗。

    • 解決方案:路徑可配置

      • os.path.split()函數(shù),將文件名和路徑分割開
      • os.path.split(path)[0],取上級目錄
      • os.path.join(path,*paths),拼接路徑不用加/
      import os
      """專門讀取路徑的值"""
      
      #獲取當(dāng)前文件所在絕對路徑,包括模塊名,__file__表示是當(dāng)前文件本身
      path=os.path.realpath(__file__)
      
      #獲取頂級目錄的絕對路徑
      project_path=os.path.split(os.path.split(os.path.split(path)[0])[0])[0]
      
      #獲取測試數(shù)據(jù)的絕對路徑
      test_data_path=os.path.join(project_path,"test_data","test_data.xlsx")
      
      #獲取測試報告的絕對路徑
      test_result_path=os.path.join(project_path,"test_result","html_report","result.html")
      
      • 使用project_path.py中的路徑
        • 引入project_path.pyfrom common.public.project_path import *
        • test_http_request.py中:test_data=DoExcel().get_data(test_data_path,"Sheet1")
        • run.py中:with open(test_result_path,"wb") as file:

添加字段存入測試結(jié)果

1.result字段存放response.json()

添加:DoExcel().write_back_data(test_data_path,"Sheet1",item["case_id"]+1,str(res.json))

# encoding: utf-8
import json
import unittest
from common.public.http_request import HttpRequest
from ddt import ddt,data
from common.public.do_excel import DoExcel
from common.public.project_path import *

test_data=DoExcel().get_data(test_data_path,"Sheet1")

@ddt
class TestHttpRequest(unittest.TestCase):

    def setUp(self):
        pass

    def tearDown(self):
        pass
    @data(*test_data)
    def test_login(self,item):
        res=HttpRequest().http_request(item["url"],item["method"],eval(item["payload"]))
        self.assertEqual(str(item["expected"]),str(res.status_code))  
        #將res.json寫入excel中
        DoExcel().write_back_data(test_data_path,"Sheet1",item["case_id"]+1,str(res.json)) 
        print "獲得的結(jié)果是:", res.json()

  • 問題:一,報錯時,因為執(zhí)行不到print語句,從result.html中無法看出時什么問題。二,如果報錯時,res.json()就無法寫入到excel文件中。
  • 解決:使用finally,是無論有沒有捕獲到異常都執(zhí)行finally下的代碼(代碼在后面展示)

2.新增一個TestResult字段存放測試結(jié)果

與result字段不同,result字段存放的是response.json(),TestResult字段存入Pass/Failed,表示用例成功還是失敗。寫入excel后可以直接通過excel篩選,只查看為Failed的用例

  • 首先在test_data.xlsx中添加字段TestResult

    image
  • 改造測試用例test_http_request.py

    test_data=DoExcel().get_data(test_data_path,"Sheet1")
    
    @ddt
    class TestHttpRequest(unittest.TestCase):
    
        def setUp(self):
            pass
    
        def tearDown(self):
            pass
            
        @data(*test_data)
        def test_login(self,item):
            res=HttpRequest().http_request(item["url"],item["method"],eval(item["payload"]))
            #捕獲異常
            try:
                self.assertEqual(str(item["expected"]),str(res.status_code)) 
                #如果沒有異常, TestResult="Pass"
                TestResult="Pass"
            except AssertionError as e:
                #如果有異常, TestResult="Failed"
                TestResult = "Failed"
                print "測試用例失敗,{0}".format(e)
                raise e
            #無論是否捕獲異常都執(zhí)行
            finally:
                print "獲得的結(jié)果是:", res.json()
                DoExcel().write_back_data(test_data_path,"Sheet1",item["case_id"]+1,str(res.json())
    
  • 改造do_excel.py寫入TestResult字段

    def write_back_data(self,file_name,sheet_name,i,result,TestResult):
        wb=load_workbook(file_name)
        sheet=wb[sheet_name]
        sheet.cell(i,7).value=result
        sheet.cell(i,8).value=TestResult
        wb.save(file_name) #保存
    

    同時,test_http_request.py中添加TestResult字段:
    DoExcel().write_back_data(test_data_path,"Sheet1",item["case_id"]+1,str(res.json(),TestResult)

用例可配置

實現(xiàn)多個用例同時執(zhí)行、多個模塊同時執(zhí)行

配置文件效果:

[MODE]
mode={"login":"all",
      "register":[1,2,4,5],
      "recharge":[1,2]
      }

通過option和value,配置不同的用例,option是對應(yīng)的模塊(使用不同的sheet放置不同的模塊,對應(yīng)sheetname),value的all代表該模塊所有用例,列表里的數(shù)字代表case_id,

  • 新建一個配置文件case.conf
  • 寫一個讀取配置文件的類
import configparser

class ReadConfig:

    @staticmethod
    def get_config(file_path,setion,option):
        cf=configparser.ConfigParser()
        cf.read(file_path)
        return cf[setion][option]
        
if __name__ == '__main__': #測試
    from common.public import project_path
    print ReadConfig.get_config(project_path.case_config_path,"MODE","mode")

控制臺輸出:

image
  • 改造do_excel.py

    class DoExcel:
    
        @staticmethod  #靜態(tài)方法,直接調(diào)用
        def get_data(file_name):
            wb=load_workbook(file_name)
            mode=eval(ReadConfig.get_config(project_path.case_config_path,"MODE","mode"))
    
            test_data=[]
            #循環(huán)配置文件中的mode的key
            for key in mode:
                sheet=wb[key] 
                #如果為all,跑所有的case
                if mode[key]=='all':
                    for i in range(2,sheet.max_row+1):
                        row_data={}
                        row_data["case_id"] = sheet.cell(i, 1).value
                        row_data["url"]=sheet.cell(i,2).value
                        row_data["method"]=sheet.cell(i,3).value
                        row_data["payload"]=sheet.cell(i,4).value
                        row_data["title"]=sheet.cell(i,5).value
                        row_data["expected"] = sheet.cell(i, 6).value
                        #讀取sheet_name
                        row_data["sheet_name"]=key
                        test_data.append(row_data)
                else:
                #如果不是all,按case_id跑
                    for case_id in mode[key]:
                        row_data = {}
                        row_data["case_id"] = sheet.cell(case_id+1, 1).value
                        row_data["url"] = sheet.cell(case_id+1, 2).value
                        row_data["method"] = sheet.cell(case_id+1, 3).value
                        row_data["payload"] = sheet.cell(case_id+1, 4).value
                        row_data["title"] = sheet.cell(case_id+1, 5).value
                        row_data["expected"] = sheet.cell(case_id+1, 6).value
                        row_data["sheet_name"] = key 
                        test_data.append(row_data)
    
            return test_data
    
        @staticmethod
        def write_back_data(file_name,sheet_name,i,result,TestResult):
            wb=load_workbook(file_name)
            sheet=wb[sheet_name]
            sheet.cell(i,7).value=result
            sheet.cell(i,8).value=TestResult
            wb.save(file_name) #保存
    
    
  • 改造測試用例test_http_request.py

    修改sheet_name參數(shù)化:

    DoExcel().write_back_data(test_data_path,item["sheet_name"],item["case_id"]+1,str(res.json()),TestResult)
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,990評論 2 374

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