第一个自动化测试框架(day10)

Posted 我已不爱凯蒂

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第一个自动化测试框架(day10)相关的知识,希望对你有一定的参考价值。

一.自动化测试分类:

1.数据驱动:

  根据数据(读取excel)来去测试的。

2.代码驱动:

  测试用例都是写代码的。

3.关键字驱动:

  UI自动化,根据封装好的工具,输入关键字来测试,有点傻瓜式测试。

二.自动化框架:可以理解为工具的集合。日常工作中,根据工作需求,实现某些功能,封装起来。或结合其他自动化工具。

三.举例:数据驱动自动测试框架:

自动化测试框架步骤:

1.获取用例

2.调用接口

3.校验结果

4.发送测试报告

5.异常处理

6.日志模块

 码起来:【宗旨:一个函数只做一件事情】

提示:

1.用例文件的内容:

2.ATP文件的结构:

 一.在common.py里写OpCase类,及get_case,my_request,check_res,write_excel,dataToDict函数。

1.get_case()函数:获取用例。获取用例中需要的数据:url,请求方式,请求数据及预期结果,放到cases list里

import xlrd
from lib.log import atp_log

class OpCase(object):  
    def get_case(self,file_path):#获取用例的函数

        cases = [] #存放所有的case
        if file_path.endswith(\'.xls\') or file_path.endswith(\'.xlsx\'):  #判断用例文件是否是excel
            try:
                book = xlrd.open_workbook(file_path)
                sheet = book.sheet_by_index(0)
                for i in range(1,sheet.nrows):
                    row_data = sheet.row_values(i)  #获取每行
                    cases.append(row_data[4:8]) #将用例中第5列至第9列截取到cases list中
                atp_log.info(\'共读取%s条用例\'%(len(cases)))  #读取用例的条数
                self.file_path = file_path  #在实例中将路径(文件名)定义,在后面write_excel()函数中不需要再传入该参数,可以直接用,否则需要在write_excel()函数中传入参数file_path
            except Exception as e:
                atp_log.error(\'【%s】用例获取失败,错误信息:%s\'%(file_path,e))
        else:
            atp_log.error(\'用例文件不合法的,%s\'%file_path)
        return cases

 2.my_request()及dataToDict()函数,调用接口。通过url,data请求获取返回的内容,其中获取的data需要先转成字典

import requests

    def my_request(self,url,method,data):#参数url,method,data
        method = method.upper() #传入参数有可能会有大小写,统一转成大写字母
        data = self.dataToDict(data)  #将获取的数据做处理,转成字典
        try :
            if method==\'POST\': #判断method的类型
                res = requests.post(url,data).text  #发送请求并转换成字典
            elif method==\'GET\':
                res = requests.get(url,params=data).text
            else:
                atp_log.warning(\'该请求方式暂不支持。。\')  #调用日志文件
                res = \'该请求方式暂不支持。。\'
        except Exception as e:
            msg = \'【%s】接口调用失败,%s\'%(url,e)
            atp_log.error(msg)
            res = msg
        return res  #返回请求返回的内容


    def dataToDict(self,data):#从excel表里获取的data格式:username=fancy,passwd=abc123456,把数据转成字典

        res = {}
        data = data.split(\',\')
        for d in data:
            k,v = d.split(\'=\')
            res[k]=v
        return res

3.check_res()函数,校验结果成功或失败。将从服务器获取的返回结果与excel表里的预期结果比较,是否一致,若一致返回“成功”并写入结果,否则失败。

首先了解从my_request里获取的返回内容的样式:

excel表里预期结果的样式:

思路:将my_request()函数里返回的res样式变为:

然后判断预期结果check是否在res返回的这个字典里。

具体实现如下:

    def check_res(self,res,check):
        res = res.replace(\'": "\',\'=\').replace(\'": \',\'=\')  #两次替换,把res里返回的字典里所有的替换成=号(因为返回的Json串格式都是一样的)
        for c in check.split(\',\'): #将预期结果里的以逗号分开
            if c not in res: #判断预期结果里的list是否在返回结果res里
                atp_log.info(\'结果校验失败,预期结果:【%s】,实际结果【%s】\'%(c,res))
                return \'失败\'
        return \'成功\'

4.write_excel()函数,写excel。获取返回每条用例的执行结果cases_res。需导入xlutils模块。

注:在get_case()函数里,定义了: self.file_path = file_path  ,因此在该函数write_excel()中不需要再传入file_path参数,可以直接调用,否则需要在write_excel()函数中传入参数file_path。

 首先需要了解用例返回结果样式:返回一个二维数组:[[\'abcxx,‘通过’],[abxx2,‘失败’]....],将结果写入返回报文和测试结果列。

from xlutils import copy

        def write_excel(self,cases_res):
        # [ [\'dsfd\',"通过"] ,[\'sdfsdf\',\'失败\'] ]
        book = xlrd.open_workbook(self.file_path)
        new_book = copy.copy(book)
        sheet = new_book.get_sheet(0)
        row = 1  #从第二行开始写,第一行是表头
        for case_case in cases_res: #获取到每一个结果
            sheet.write(row,8,case_case[0]) #写第8列
            sheet.write(row,9,case_case[1]) #写第9列
            row+=1
        new_book.save(self.file_path.replace(\'xlsx\',\'xls\'))  #如果是xlsx结尾的将替换为xls结尾,保证excel可以打开

二.在lib下写发邮件的类:send_mail.py

发邮件是需要定义一些变量、常量,因此将这些内容写在配置文件setting里便于管理。

import yagmail
from conf import setting  #将setting文件里定义的常量导入
from lib.log import atp_log  #导入lib下的log文件,写日志
def sendmail(title,content,attrs=None):
    m = yagmail.SMTP(host=setting.MAIL_HOST,user=setting.MAIL_USER
                 ,password=setting.MAIL_PASSWRD,smtp_ssl=True  #当是qq邮箱时,需加入smtp_ssl=True
                 )
    m.send(to=setting.TO,subject=title,
           contents=content,
           attachments=attrs)
    atp_log.info(\'发送邮件完成\')

三.在conf下新建setting.py,配置文件里定义各种需要的变量,常量,修改时,方便。

import os
BASE_PATH = os.path.dirname(
    os.path.dirname(os.path.abspath(__file__))  #获取ATP所在的路径
)
MAIL_HOST=\'smtp.163.com\'
MAIL_USER=\'liu.****@163.com\'
MAIL_PASSWRD = \'p888****g421\'
TO = [
    \'5472*****@qq.com\',
]
LEVEL = \'debug\' #日志级别

LOG_PATH = os.path.join(BASE_PATH,\'logs\') #存放日志的路径,动态获取的,无论文件存放位置
CASE_PATH = os.path.join(BASE_PATH,\'cases\') #存放日志的路径
LOG_NAME=\'atp.log\' #日志的文件名

四.在lib下log.py文件。写日志文件,在其他文件抛异常时,会打印日志,直接调用该文件。

import logging,os
from logging import handlers
from conf import setting
class MyLogger():
    def __init__(self,file_name,level=\'info\',backCount=5,when=\'D\'):
        logger = logging.getLogger()  # 先实例化一个logger对象,先创建一个办公室
        logger.setLevel(self.get_level(level))  # 设置日志的级别的人
        cl = logging.StreamHandler()  # 负责往控制台输出的人
        bl = handlers.TimedRotatingFileHandler(filename=file_name, when=when, interval=1, backupCount=backCount, encoding=\'utf-8\')
        fmt = logging.Formatter(\'%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s\')
        cl.setFormatter(fmt)  # 设置控制台输出的日志格式
        bl.setFormatter(fmt)  # 设置文件里面写入的日志格式
        logger.addHandler(cl)
        logger.addHandler(bl)
        self.logger = logger

    def get_level(self,str):
        level = {
            \'debug\':logging.DEBUG,
            \'info\':logging.INFO,
            \'warn\':logging.WARNING,
            \'error\':logging.ERROR
        }
        str = str.lower()
        return level.get(str)


path = os.path.join(setting.LOG_PATH,setting.LOG_NAME) #拼好日志的绝对路径
atp_log = MyLogger(path,setting.LEVEL).logger  #日志级别
#直接在这里实例化,用的时候就不用再实例化了

五.在bin下新建start.py。start.py文件是启动文件,程序的入口,串联整个系统功能的所有逻辑。

import os,sys
BASE_PATH = os.path.dirname(
    os.path.dirname(os.path.abspath(__file__))  #获取ATP的路径
)
sys.path.insert(0,BASE_PATH)  #将ATP目录下的所有文件加到环境变量,这样保证以后在哪里运行都可以

from lib.common import OpCase #导入读取用例的类
from lib.send_mail import sendmail  #导入发邮件的类
from conf import setting  #导入配置文件
class CaseRun(object): #启动的类
    def find_cases(self):
        op = OpCase()  #实例化获取用例的类,便于调用OpCase()类下的函数
        for f in os.listdir(setting.CASE_PATH):#每次循环的时候读一个excel
            abs_path = os.path.join(setting.CASE_PATH,f)  #拼成绝对路径,f只是一个文件名
            case_list = op.get_case(abs_path)  #调用OpCase()类下的获取用例的函数,获取所有用例
            res_list = []
            pass_count,fail_count = 0,0
            for case in case_list:#循环每个excel里面所有用例
                url,method,req_data,check = case  #check:预期结果
                res = op.my_request(url,method,req_data) #调用完接口返回的结果,res:实际结果
                status = op.check_res(res,check)  #调用check_res()函数,校验预期结果&实际结果
                res_list.append([res,status])  #将返回结果和测试结果加入一个list,定义res_list,便于写入excel
                if status==\'成功\':
                    pass_count+=1
                else:
                    fail_count+=1
            op.write_excel(res_list)  #将res_list(返回报文,测试结果)写入excel
            msg = \'\'\'
            xx你好:
                本次共运行%s条用例,通过%s条,失败%s条。
            \'\'\'%(len(res_list),pass_count,fail_count)
            sendmail(\'测试用例运行结果\',content=msg,attrs=abs_path)  #发邮件

六.启动:在start.py文件中:

CaseRun().find_cases() #调用find_cases函数

 

欧了,整个简单的自动化框架包装完毕。

 

以上是关于第一个自动化测试框架(day10)的主要内容,如果未能解决你的问题,请参考以下文章

WindowsGUI自动化测试框架搭建-第一个WindowsGUI自动化测试程序

Python+Selenium自动化测试框架--第一个自动化测试脚本

第 5 章 自动化测试模型 - Selenium3 自动化测试

第 6 章 unittest 单元测试框架 - Selenium3 自动化测试

浅析Minium,微信小程序自动化测试框架

Day 10 信息打点—APP/小程序 抓包封包(Xposed框架 资产提取)