Python 簡易實現接口測試自動化

原文鏈接:http://www.cnblogs.com/Detector/p/6935650.html

實現思路

使用excel管理用例用例信息,requests模塊發送http請求,實現了記錄日誌,郵件發送測試報告的功能

目錄結構如下:

D:\PROJECT\INTERFACE_
│  controler.py
│  interface.py
│  logging_save.py
│  result_check.py
│  result_save.py
│  result_send.py
│  testcase_get.py
│  url_transform.py
│  __init__.py
├─config
│      config.py
│      mail.conf
│      __init__.py

├─report
│      [email protected]@163850.xls
│      __init__.py

└─test_case
        20170602.xls
        __init__.py

下面直接上代碼:

controler.py  統籌執行所有腳本

複製代碼
# -*- coding:utf-8 -*-
from interface import Interface
from testcase_get import Get_testcase
from result_save import Save_test_result
from result_send import Send_report
from config.config import Config
from logging_save import logger
import os

if __name__ == '__main__':
    '''try:
        filename = sys.argv[1]
    except IndexError, e:
        print 'Please enter a correct testcase! \n e.x: python gkk.py test_case.xls'
    else:
        readExcel(filename)
    print 'Done!'''
    cur_path = os.path.split(os.path.realpath(__file__))[0] #獲取當前文件絕對路徑
    case_path = os.path.join(cur_path,'test_case','20170602.xls')
    test_case = Get_testcase(case_path).readExcel() #獲取用例
    if not isinstance(test_case,list): #判斷用例是否獲取成功
        logger.info('Test_case get failed... \n Done!')
    else:
        logger.info('獲取用例成功')
        # 調用接口
        test_result = Interface().interfaceTest(test_case)
        #獲取執行結果,用於發郵件
        count_success = test_result[3]
        count_failure = test_result[4]
        failed_case_detail = test_result[5]
        # 保存測試結果
        Save_test_result().save_result(case_path, test_result[0], test_result[1], test_result[2])
        logger.info('保存測試結果成功')
        #獲取郵件配置信息
        mail_config = Config(os.path.join(cur_path,'config', 'mail.conf')).get_mail_config()
        logger.info('獲取郵箱配置成功')
        login_user = mail_config[0]
        login_pwd = mail_config[1]
        from_addr = mail_config[2]
        to_addrs = mail_config[3]
        smtp_server = mail_config[4]
        mail_send = Send_report(count_success, count_failure, failed_case_detail)
        #獲取最新測試報告
        last_report = mail_send.newest_report()
        mail_send.send_result(login_user, login_pwd,from_addr, to_addrs,smtp_server,last_report)
複製代碼

interface.py  對接口的發送和請求統一進行的封裝

複製代碼
#coding:utf-8
import requests,json

from logging_save import logger
from  result_check import result_check
from url_transform import urltransform

class Interface():
    def __init__(self,):
        pass

    def interfaceTest(self,case_list):
        '''
        接口調用主函數
        '''
        # 用於存結果
        res_flags = []
        # 用於存請求報文
        request_urls = []
        # 用於存返回報文
        responses = []
        #用戶存失敗的用例
        failed_case = []
        #統計成功失敗的用例數
        count_success = 0
        count_failure = 0
        for case in case_list:
            try:
                # 模塊
                product = case[0]
                # 用例id
                case_id = case[1]
                # 用例標題
                interface_name = case[2].strip('\n')
                # 用例描述
                case_detail = case[3]
                # 請求方式
                method = case[4]
                # 請求url
                url = case[5]
                # 入參
                param = case[6]
                # 預期結果
                res_check = case[7]
            except Exception, e:
                return '測試用例格式不正確!%s' % e
            # 定義消息頭信息
            headers = {'content-type': 'application/json',
                       'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'}
            #對url進行封裝
            new_url = urltransform().urltransform(url,method,param)
            if  method.upper() == 'GET':
                results = requests.get(new_url).text
                #print results
                responses.append(results)
                #用於存儲預期結果與實際結果的比較結果
                res = result_check().result_check(results, res_check)
                request_urls.append(new_url)
            else:
                request_urls.append(new_url)
                if param == '':
                    pass
                else:
                    data = json.loads(param) #將參數轉化爲json格式
                results = requests.post(new_url,data=json.dumps(data),headers=headers).text
                responses.append(results)
                res = result_check().result_check(results, res_check)
            if 'pass' in res:
                res_flags.append('pass')
                count_success += 1
            else:
                logger.warning(u'接口: %s 調用失敗'%interface_name)
                logger.warning(u'失敗接口URL: %s METHOD :%s'%(url,method))
                res_flags.append('fail')
                count_failure += 1
                failed_case.append((interface_name,method,url))
        return res_flags,request_urls,responses,count_success,count_failure,failed_case
        #print request_urls,res_flags,responses
複製代碼

 logging_save.py   對日誌模塊統一進行的封裝,可以保存日誌和在控制檯輸出

複製代碼
# coding=utf-8
import logging
import sys
import traceback
import time

class LoggingUtils:
    '''
    ===========封裝日誌工具類的基本操作=============
    '''
    def __init__(self,logfile):
        '''
        :param logfile: 
        '''
        self.logger = logging.getLogger(logfile)
        self.hdlr = logging.FileHandler(logfile)
        formatter = logging.Formatter('%(asctime)s %(levelname)s - %(message)s')
        self.ch = logging.StreamHandler()
        self.ch.setLevel(logging.INFO)
        self.ch.setFormatter(formatter)
        self.hdlr.setFormatter(formatter)
        self.logger.addHandler(self.hdlr)
        self.logger.addHandler(self.ch)
        self.logger.setLevel(logging.DEBUG)

    def debug(self, msg):
        '''
        :param msg: 
        :return: 
        '''
        self.logger.debug(msg)
        self.hdlr.flush()

    def info(self, msg):
        '''
        
        :param msg: 
        :return: 
        '''
        self.logger.info(msg)
        self.hdlr.flush()

    def warning(self,msg):
        self.logger.warning(msg)
        self.hdlr.flush()

    def error(self, msg):
        '''

        :param msg: 
        :return: 
        '''
        self.logger.error(msg)
        # self.logger.removeHandler(logging.StreamHandler())
        self.logger.removeHandler(self.ch)
        self.hdlr.flush()

    def error_sys(self, limit=None):
        '''
        :param limit: 
        :return: 
        '''
        exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
        if limit is None:
            if hasattr(sys, 'tracebacklimit'):
                limit = sys.tracebacklimit
        n = 0
        eline = '\n'
        while exceptionTraceback is not None and (limit is None or n < limit):
            f = exceptionTraceback.tb_frame
            lineno = exceptionTraceback.tb_lineno
            co = f.f_code
            filename = co.co_filename
            name = co.co_name
            eline += ' File "%s", line %d, in %s \n ' % (filename, lineno, name)
            exceptionTraceback = exceptionTraceback.tb_next
            n = n + 1

        eline += "\n".join(traceback.format_exception_only(exceptionType, exceptionValue))
        self.logger.error(eline)
        self.hdlr.flush()
timer = time.strftime('%Y-%m-%d',time.localtime())
logger = LoggingUtils('%s.log'%timer)
複製代碼

result_check.py  進行測試結果比對的模塊,可以根據項目情況進行擴展

複製代碼
#coding:utf-8
class result_check():

    def __init__(self):
        pass

    def result_check(self,results,res_check):
        '''
        結果對比函數
        '''
        #返回結果,將結果中的json數據轉化爲可以和預期結果比較的數據
        res = results.replace('":"','=').replace('" : "','=')
        #預期結果,是xx=11;xx=22
        res_check = res_check.split(';')
        for s in res_check:
            if s in res:
                pass
            else:
                return '結果不匹配 '+ str(s)
        return 'pass'
複製代碼

 result_save.py   保存測試結果的模塊,複製原有的用例,保存爲新的excel

複製代碼
#coding:utf-8
from xlutils import copy
import xlrd
import time
import os

class Save_test_result():

    def __init__(self):
        pass

    def save_result(self,file_path,res_flags,request_urls,responses):
        '''
        :return: 
        '''
        book = xlrd.open_workbook(file_path)
        new_book = copy.copy(book)
        sheet = new_book.get_sheet(0)
        i = 1
        for request_url, response, flag in zip(request_urls, responses, res_flags):
            sheet.write(i, 8, u'%s' % request_url)
            sheet.write(i, 9, u'%s' % response)
            sheet.write(i, 10, u'%s' % flag)
            i += 1
        report_path = os.path.abspath(os.path.join('report'))
        if not os.path.exists(report_path):
            os.makedirs(report_path)
        new_book.save(os.path.abspath(os.path.join(report_path, 'Report@%s.xls' % time.strftime('%Y.%m.%d@%H%M%S'))))
複製代碼

 result_send.py  發送郵件的模塊,可以發送多個附件

複製代碼
#coding:utf-8
import smtplib
from email.mime.text import MIMEText
from email.header import Header
from email.mime.multipart import MIMEMultipart
import os
from logging_save import  logger


class Send_report(object):
    def __init__(self,count_success,count_failure,failed_case):
        '''
        :param count_success: 
        :param count_failure: 
        :param failed_case: 
        '''
        self.count_success = count_success
        self.count_failure = count_failure
        self.failed_case = failed_case

    def newest_report(self,testreport='report'):
        '''
        獲取最新的測試報告
        :param testreport: 
        :return: 
        '''
        lists = os.listdir(testreport)
        lists.sort(key=lambda fn: os.path.getmtime(os.path.join(testreport,fn)))
        file_new = os.path.join(testreport, lists[-1])
        logger.info('獲取最新附件報告成功')
        return file_new

    def send_result(self,username,passwd,from_addr,to_addrs,smtpserver,*args):
        '''
        :param username: 
        :param passwd: 
        :param from_addr: 
        :param to_addrs: 
        :param smtpserver: 
        :param args: 
        :return: 
        '''
        sender = from_addr
        subject = '財富港接口測試結果'
        username = username
        passwd = passwd

        '''郵件內容'''
        tille = (u'用例名稱', u'請求方式', u'url')
        details = (u'成功: ' + str(self.count_success) + u'失敗: ' + str(self.count_failure)) + '\n' + u'失敗的用例如下 :' + \
                  '\n' + '\n'.join(str(zip(tille, i)) for i in self.failed_case).decode('unicode-escape')
        logger.info('郵件附件爲: %s' %(args[0].split('\\')[1]))

        if args != None: #判斷是否添加附件
            msg = MIMEMultipart()
            msg.attach(MIMEText(details, 'plain', 'utf-8'))
            i = 0
            while i < len(args): #可以添加多個附件
                part = MIMEText(open(args[i], 'rb').read(), 'base64', 'utf-8')
                part["Content-Type"] = 'application/octet-stream'
                part["Content-Disposition"] = 'attachment; filename="%s"'%args[i]
                msg.attach(part) #添加附件
                i += 1

            msg['subject'] = Header(subject, 'utf-8')
            msg['From'] = from_addr
            msg['To'] = ','.join(eval(to_addrs)) #兼容多個收件人
            smtp = smtplib.SMTP()
            try:
                smtp.connect(smtpserver)
                smtp.login(username, passwd)
                smtp.sendmail(sender, eval(to_addrs), msg.as_string())
                smtp.close()
                logger.info('帶附件測試報告發送成功!')
            except smtplib.SMTPAuthenticationError,e:
                logger.error('郵箱賬戶或密碼錯誤: '+ str(e))

        else:
            msg = MIMEText(details, 'plain', 'utf-8')
            msg['subject'] = Header(subject, 'utf-8')
            msg['From'] = from_addr
            msg['To'] =  ','.join(eval(to_addrs))
            smtp = smtplib.SMTP()
            try:
                smtp.connect(smtpserver)
                smtp.login(username, passwd)
                smtp.sendmail(sender, eval(to_addrs), msg.as_string())
                logger.info('測試報告發送成功!')
                smtp.close()
            except smtplib.SMTPAuthenticationError,e:
                logger.error('郵箱賬戶或密碼錯誤 : '+str(e))
複製代碼

 testcase_get.py   獲取用例信息的模塊

複製代碼
#coding:utf-8
import xlrd

from logging_save import logger

class Get_testcase(object):

    def __init__(self, file_path):
        '''
        :param file_path: 用例文件路徑
        '''
        self.file_path = file_path

    def readExcel(self):
        '''
        讀取用例函數
        :return: 測試用例列表
        '''
        try:
            book = xlrd.open_workbook(self.file_path)  # 打開excel
        except Exception, error:
            logger.error('路徑不在或者excel不正確 : ' + str(error))
            return error
        else:
            sheet = book.sheet_by_index(0)  # 取第一個sheet頁
            rows = sheet.nrows  # 取這個sheet頁的所有行數
            case_list = []  # 用於保存用例信息
            for i in range(rows):
                if i != 0:
                    case_list.append(sheet.row_values(i)) # 把每一條測試用例添加到case_list中
            return case_list
複製代碼

 url_transform.py   對excel中管理的請求的url進行轉換的模塊

複製代碼
#coding:utf-8
class urltransform(object):
    def __init__(self):
        pass

    def urltransform(self, url, method, param):
        '''
        :return: 
        '''
        if param == '':
            new_url = url
        else:
            if method.upper() == 'GET':
                new_url = url + '?' + param.replace(';', '&')  #如果有參數,且爲GET方法則組裝url
            else:
                new_url = url
        return new_url
複製代碼

testcase目錄下excel結構

config目錄下,config.py   獲取配置文件信息的模塊

複製代碼
#conding:utf-8
import ConfigParser

class Config(object):

    def __init__(self,file_path):
        self.config = ConfigParser.ConfigParser()
        self.config.read(file_path)

    def get_mail_config(self):
        login_user = self.config.get('SMTP', 'login_user')
        login_pwd = self.config.get('SMTP', 'login_pwd')
        from_addr = self.config.get('SMTP', 'from_addr')
        to_addrs = self.config.get('SMTP', 'to_addrs')
        smtp_server = self.config.get('SMTP', 'smtp_server')
        port = self.config.get('SMTP', 'port')
        return login_user, login_pwd , from_addr, to_addrs,smtp_server, port

    def report_save_config(self):
        pass
複製代碼

mail.conf

複製代碼
[SMTP]
login_user = 18******@163.com
login_pwd = ******
from_addr =  BI<18******@163.com>
to_addrs = ['18******@163.com']
#to_addrs = ['1******@qq.com','******.com']
smtp_server = smtp.163.com
port = 25
複製代碼

報告效果圖

收到的郵件效果圖:


發佈了59 篇原創文章 · 獲贊 4 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章