接口測試第一章

# coding=utf-8

# 導入需要用到的模塊
import mysql.connector
import requests
import sys
import time
import xlrd
from xlutils import copy


# 從xlutils模塊中導入copy這個函數(shù)
def readExcel(file_path):
    """
    讀取excel測試用例的函數(shù)
    :param file_path:傳入一個excel文件,或者文件的絕對路徑
    :return:返回這個excel第一個sheet頁中的所有測試用例的list
    """
    try:
        book = xlrd.open_workbook(file_path)  # 打開excel
    except Exception as e:
        # 如果路徑不在或者excel不正確,返回報錯信息
        print '路徑不在或者excel不正確', e
        return e
    else:
        sheet = book.sheet_by_index(0)  # 取第一個sheet頁
        rows = sheet.nrows  # 取這個sheet頁的所有行數(shù)
        case_list = []  # 保存每一條case
        for i in range(rows):
            if i != 0:
                # 把每一條測試用例添加到case_list中
                case_list.append(sheet.row_values(i))
        # 調用接口測試的函數(shù),把存所有case的list和excel的路徑傳進去,因為后面還需要把返回報文和測試結果寫到excel中,
        # 所以需要傳入excel測試用例的路徑,interfaceTest函數(shù)在下面有定義
        interfaceTest(case_list, file_path)


def interfaceTest(case_list, file_path):
    res_flags = []
    # 存測試結果的list
    request_urls = []
    # 存請求報文的list
    responses = []
    # 存返回報文的list
    for case in case_list:
        '''
        先遍歷excel中每一條case的值,然后根據(jù)對應的索引取到case中每個字段的值
        '''
        try:
            '''
            這里捕捉一下異常,如果excel格式不正確的話,就返回異常
            '''
            # 項目,提bug的時候可以根據(jù)項目來提
            product = case[0]
            # 用例id,提bug的時候用
            case_id = case[1]
            # 接口名稱,也是提bug的時候用
            interface_name = case[2]
            # 用例描述
            case_detail = case[3]
            # 請求方式
            method = case[4]
            # 請求url
            url = case[5]
            # 入?yún)?            param = case[6]
            # 預期結果
            res_check = case[7]
            # 測試人員
            tester = case[10]
        except Exception as e:
            return '測試用例格式不正確!%s' % e
        if param == '':
            '''
            如果請求參數(shù)是空的話,請求報文就是url,然后把請求報文存到請求報文list中
            '''
            new_url = url  # 請求報文
            request_urls.append(new_url)
        else:
            '''
            如果請求參數(shù)不為空的話,請求報文就是url+?+參數(shù),格式和下面一樣
            http://127.0.0.1:8080/rest/login?oper_no=marry&id=100,然后把請求報文存到請求報文list中
            '''
            new_url = url + '?' + urlParam(param)  # 請求報文
            '''
            excel里面的如果有多個入?yún)⒌脑挘瑓?shù)是用;隔開,a=1;b=2這樣的,請求的時候多個參數(shù)要用&連接,
            要把;替換成&,所以調用了urlParam這個函數(shù),把參數(shù)中的;替換成&,函數(shù)在下面定義的
            '''
            request_urls.append(new_url)
        if method.upper() == 'GET':
            '''
            如果是get請求就調用requests模塊的get方法,.text是獲取返回報文,保存返回報文,
            把返回報文存到返回報文的list中
            '''
            print new_url
            results = requests.get(new_url).text
            print results
            responses.append(results)
            '''
            獲取到返回報文之后需要根據(jù)預期結果去判斷測試是否通過,調用查看結果方法
            把返回報文和預期結果傳進去,判斷是否通過,readRes方法在下面定義了。
            '''
            res = readRes(results, res_check)
        else:
            '''
            如果不是get請求,也就是post請求,就調用requests模塊的post方法,.text是獲取返回報文,
            保存返回報文,把返回報文存到返回報文的list中
            '''
            results = requests.post(new_url).text
            responses.append(results)
            '''
            獲取到返回報文之后需要根據(jù)預期結果去判斷測試是否通過,調用查看結果方法
            把返回報文和預期結果傳進去,判斷是否通過,readRes方法會返回測試結果,如果返回pass就
            說明測試通過了,readRes方法在下面定義了。
            '''
            res = readRes(results, res_check)
        if 'pass' in res:
            '''
            判斷測試結果,然后把通過或者失敗插入到測試結果的list中
            '''
            res_flags.append('pass')
        else:
            res_flags.append('fail')
            '''
            如果不通過的話,就調用寫bug的方法,把case_id、接口名稱、請求報文、返回報文和預期結果傳進去
            writeBug方法在下面定義了,具體實現(xiàn)是先連接數(shù)據(jù)庫,然后拼sql,插入到bug表中
            '''
            writeBug(case_id, interface_name, new_url, results, res_check)
    '''
    全部用例執(zhí)行完之后,會調用copy_excel方法,把測試結果寫到excel中,
    每一條用例的請求報文、返回報文、測試結果,這三個每個我在上面都定義了一個list
    來存每一條用例執(zhí)行的結果,把源excel用例的路徑和三個list傳進去調用即可,copy_excel方
    法在下面定義了,也加了注釋
    '''
    copy_excel(file_path, res_flags, request_urls, responses)


def readRes(res, res_check):
    """
    :param res: 返回報文
    :param res_check: 預期結果
    :return: 通過或者不通過,不通過的話會把哪個參數(shù)和預期不一致返回
    """
    '''
    返回報文的例子是這樣的{"id":"J_775682","p":275.00,"m":"458.00"}
    excel預期結果中的格式是xx=11;xx=22這樣的,所以要把返回報文改成xx=22這樣的格式
    所以用到字符串替換,把返回報文中的":"和":替換成=,返回報文就變成
    {"id=J_775682","p=275.00,"m=458.00"},這樣就和預期結果一樣了,當然也可以用python自帶的
    json模塊來解析json串,但是有的返回的不是標準的json格式,處理起來比較麻煩,這里我就用字符串的方法了
    '''
    res = res.replace('":"', "=").replace('":', "=")

    '''
    res_check是excel中的預期結果,是xx=11;xx=22這樣的
    所以用split分割字符串,split是python內置函數(shù),切割字符串,變成一個list
    ['xx=1','xx=2']這樣的,然后遍歷這個list,判斷l(xiāng)ist中的每個元素是否存在這個list中,
    如果每個元素都在返回報文中的話,就說明和預期結果一致
    上面我們已經把返回報文變成{"id=J_775682","p=275.00,"m=458.00"}
    '''
    res_check = res_check.split(';')
    for s in res_check:
        '''
        遍歷預期結果的list,如果在返回報文中,什么都不做,pass代表什么也不做,全部都存在的話,就返回pass
        如果不在的話,就返回錯誤信息和不一致的字段,因為res_check是從excel里面讀出來的
        字符Unicode類型的的,python的字符串是str類型的,所以要用str方法強制類型轉換,轉換成string類型的
        '''
        if s in res:
            pass
        else:
            return '錯誤,返回參數(shù)和預期結果不一致' + str(s)
    return 'pass'


def urlParam(param):
    """
    參數(shù)轉換,把參數(shù)轉換為'xx=11&xx=2這樣'
    """
    return param.replace(';', '&')


def copy_excel(file_path, res_flags, request_urls, responses):
    """
    :param file_path: 測試用例的路徑
    :param res_flags: 測試結果的list
    :param request_urls: 請求報文的list
    :param responses: 返回報文的list
    :return:
    """
    '''
    這個函數(shù)的作用是寫excel,把請求報文、返回報文和測試結果寫到測試用例的excel中
    因為xlrd模塊只能讀excel,不能寫,所以用xlutils這個模塊,但是python中沒有一個模塊能
    直接操作已經寫好的excel,所以只能用xlutils模塊中的copy方法,copy一個新的excel,才能操作
    '''
    # 打開原來的excel,獲取到這個book對象
    book = xlrd.open_workbook(file_path)
    # 復制一個new_book
    new_book = copy.copy(book)
    # 然后獲取到這個復制的excel的第一個sheet頁
    sheet = new_book.get_sheet(0)
    i = 1
    for request_url, response, flag in zip(request_urls, responses, res_flags):
        '''
        同時遍歷請求報文、返回報文和測試結果這3個大的list
        然后把每一條case執(zhí)行結果寫到excel中,zip函數(shù)可以將多個list放在一起遍歷
        因為第一行是表頭,所以從第二行開始寫,也就是索引位1的位置,i代表行
        所以i賦值為1,然后每寫一條,然后i+1, i+=1同等于i=i+1
        請求報文、返回報文、測試結果分別在excel的8、9、11列,列是固定的,所以就給寫死了
        后面跟上要寫的值,因為excel用的是Unicode字符編碼,所以前面帶個u表示用Unicode編碼
        否則會有亂碼
        '''
        sheet.write(i, 8, u'%s' % request_url)
        sheet.write(i, 9, u'%s' % response)
        sheet.write(i, 11, u'%s' % flag)
        i += 1
    # 寫完之后在當前目錄下(可以自己指定一個目錄)保存一個以當前時間命名的測試結果,time.strftime()是格式化日期
    new_book.save('%s_測試結果.xls' % time.strftime('%Y%m%d%H%M%S'))


def writeBug(bug_id, interface_name, request, response, res_check):
    """
    這個函數(shù)用來連接數(shù)據(jù)庫,往bugfree數(shù)據(jù)中插入bug,拼sql,執(zhí)行sql即可
    :param bug_id: bug序號
    :param interface_name: 接口名稱
    :param request: 請求報文
    :param response: 返回報文
    :param res_check: 預期結果
    :return:
    """
    bug_id = bug_id.encode('utf-8')
    interface_name = interface_name.encode('utf-8')
    res_check = res_check.encode('utf-8')
    response = response.encode('utf-8')
    request = request.encode('utf-8')
    '''
    因為上面幾個字符串是從excel里面讀出來的都是Unicode字符集編碼的,
    python的字符串上面指定了utf-8編碼的,所以要把它的字符集改成utf-8,才能把sql拼起來
    encode方法可以指定字符集
    '''
    # 取當前時間,作為提bug的時間
    now = time.strftime("%Y-%m-%d %H:%M:%S")
    # bug標題用bug編號加上接口名稱然后加上_結果和預期不符,可以自己隨便定義要什么樣的bug標題
    bug_title = bug_id + '_' + interface_name + '_結果和預期不符'
    # 復現(xiàn)步驟就是請求報文+預期結果+返回報文
    step = '[請求報文]<br />' + request + '<br/>' + '[預期結果]<br/>' + res_check + '<br/>' + '<br/>' + '[響應報文]<br />' + '<br/>' + response
    # 拼sql,這里面的項目id,創(chuàng)建人,嚴重程度,指派給誰,都在sql里面寫死,使用的時候可以根據(jù)項目和接口
    # 來判斷提bug的嚴重程度和提交給誰
    sql = "INSERT INTO `bf_bug_info` (`created_at`, `created_by`, `updated_at`, `updated_by`, `bug_status`, `assign_to`, `title`, `mail_to`, `repeat_step`, `lock_version`, `resolved_at`, `resolved_by`, `closed_at`, `closed_by`, `related_bug`, `related_case`, `related_result`, " \
          "`productmodule_id`, `modified_by`, `solution`, `duplicate_id`, `product_id`, " \
          "`reopen_count`, `priority`, `severity`) " \
          "VALUES ('%s', '1', '%s', '1', 'Active', '1', '%s', '系統(tǒng)管理員', '%s', '1', NULL , NULL, NULL, NULL, '', '', '', NULL, " \
          "'1', NULL, NULL, '1', '0', '1', '1');" % (now, now, bug_title, step)

    # 建立連接,使用MMySQLdb模塊的connect方法連接mysql,傳入賬號、密碼、數(shù)據(jù)庫、端口、ip和字符集
    coon = mysql.connector.connect(user='root',
                                   passwd='123456',
                                   db='bugfree',
                                   port=3306,
                                   host='127.0.0.1',
                                   charset='utf8')
    # 建立游標
    cursor = coon.cursor()
    # 執(zhí)行sql
    cursor.execute(sql)
    # 提交
    coon.commit()
    # 關閉游標
    cursor.close()
    # 關閉連接
    coon.close()


if __name__ == '__main__':

    '''
    然后進行調用,調用的時候需要傳入一個excel,調用方式是 python test.py test_case.xls
    sys.argv[1]的意思是取傳入的第二個參數(shù),也就是索引是1的,
    第一個是這個python文件的文件名,如果不傳入?yún)?shù)運行的話,會提示錯誤,如果正確的話,
    會調用讀excel的程序,執(zhí)行用例,運行完成后,會打印Done
    '''
    try:
        filename = sys.argv[1]
    except IndexError as e:
        print 'Please enter a correct testcase! \n e.x: python gkk.py test_case.xls'
    else:
        readExcel(filename)
    print 'Done!'

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 初次嘗試phpunit 編寫代碼,保存為hello_php.php,內容如下: //引入框架 use PHPUni...
    測試幫日記閱讀 221評論 0 0
  • 今天參加了接口測試第一節(jié)課,給我的感覺是非常好,老師很負責人,短短三個月的課程安排很緊湊,課程內容很豐富,讓我...
    劉巍l閱讀 247評論 0 0
  • 大自然的鬼斧神工,在那個遠古時代,人類還未曾達到的地方,有一個仙境一般美麗的地方,在天一地之間孕育著的靈物,慢慢有...
    相相閱讀 196評論 0 0
  • 世間最完美的男子長什么模樣 敢問這人世間,真正完美的男子到底有沒有呢?如果有,那他長什么樣子?姓甚名誰,又在哪里呢...
    七七愛天空閱讀 234評論 0 0
  • 城市街道的背后, 隱藏著看不見的貧窮, 轉過街角就是一片斑斕, 穿過小巷是流浪者的殿堂, 一線之隔如若兩個世界, ...
    常建元閱讀 180評論 3 1