接口测试框架优化(二)---主要代码

前言

接上一篇 文章 ,上一篇文章主要介绍了整体的思路流程及大致结构,这篇大致说一下主要代码。

结构介绍

如上一篇文章所说,代码主要分为common(公共部分)和testcase(测试用例)。

common部分主要是进行:

  • Excel读写操作
  • 数据库相关操作
  • 校验并返回结果
  • 基础日志模块

testcase部分主要是各个case:

  • 逐行读取Excel
  • 发送请求
  • 将返回的结果写入Excel
接口测试框架优化(二)---主要代码_第1张图片
结构.png

部分代码介绍

个人觉得整体结构中比较核心的是common部分,testcase部分相关逻辑比较简单。

common部分介绍

  • Excel相关操作
    主要就是读写操作,读取数据供接口发送请求,并将结果写入表格。
getexceldata.py

读取Excel数据分为两种,一个是读取指定单元格的数值,一个是读取行数
以读取请求参数为例,其他相同,请求参数多一步json.loads()

def get_formdata(name,rows):
    '''
    读取请求参数
    :param name: sheet名称
    :param rows: 行
    :return:
    '''
    alldata=xlrd.open_workbook(file)
    sheet = alldata.sheet_by_name(name)

    value = sheet.cell(rows,6).value
    if value == '':
        return value
    else:
        return json.loads(value)


def get_nrows(name):
    '''
    读取行数
    :param name: sheet名称
    :return:
    '''
    alldata=xlrd.open_workbook(file)
    sheet = alldata.sheet_by_name(name)
    nrows = sheet.nrows
    return nrows
setexceldata.py

以写入结果为例,列固定死,根据结果的不同设置对应的style
绿色 pass
红色 fail
黄色 not execute

def set_content(sheetnum,rows,content):
    newWb=set_data()
    newWs = newWb.get_sheet(sheetnum)
    if len(content)>10000:
        newWs.write(rows,12,content[:10000])
    else:
         newWs.write(rows,12,content)
    newWb.save(file)

def set_result(sheetnum,rows,content):
    '''
    写测试结果pass 还是fail
    :param sheetnum: sheet index
    :param rows: 行
    :param content: pass or fail or not execute
    :return:
    '''
    newWb=set_data()
    newWs = newWb.get_sheet(sheetnum)

    stylered = xlwt.easyxf('pattern: pattern solid, fore_color red;')
    stylegreen = xlwt.easyxf('pattern: pattern solid, fore_color green;')
    styleyellow = xlwt.easyxf('pattern: pattern solid, fore_color yellow;')

    if content == 'pass':
        newWs.write(rows,13,content,stylegreen)
        newWb.save(file)
    elif content == 'fail':
        newWs.write(rows,13,content,stylered)
        newWb.save(file)
    elif content == 'not execute':
        newWs.write(rows,13,content,styleyellow)
        newWb.save(file)

其他同这个或者更简单,只是列值不一样

备注:写入Excel有长度限制,所以在写入content的时候,加了截取字符串的操作
  • 数据库相关操作
    我司用的psg数据库,其他数据库操作类似。
    分为两部分,一个connect_DB 一个check_DB
connect_DB.py
class DB :

    def __init__(self):
        try:
            self.conn = psycopg2.connect(host= host ,
                                         user=user,
                                         port=port,
                                         password=password,
                                         database=db,
                                         )
        except Exception as e:
            print e

    def select(self,sql):
        cusor = self.conn.cursor()
        cusor.execute(sql)
        rows = cusor.fetchall()
        # for row in rows:
        #     print row[0]
        return rows[0][0]

    def close(self):
        self.conn.close()

连接数据的一些参数host、user、port、password、db等写在配置文件config.ini中

check_DB.py
def check(name,rows):
    '''
    查询sql检查
    :param name:sheetname
    :param rows: 行
    :return:
    '''
    execute = int(get.get_data(name,rows,7))
    if execute == 0:
        return ('pass','')
    elif execute == 1:
        sql = sql=get.get_data(name,rows,8)

        actual_result = db.DB().select(sql)
        expext_result = get.get_data(name,rows,9)

        if actual_result == expext_result:
            return ('pass',actual_result)
        else:
            return ('fail',actual_result)

读取Excel的值,如果进行sql校验,就执行,并返回sql执行的结果及校验结果

  • 校验部分
    校验分为3个流程,同时满足:
    • status_code = 200
    • sql校验通过
    • 返回content正则匹配通过
      三个条件则判定为pass,否则就是fail
check_all.py
def checkall(sheetname,i,code,content):
    '''
    检查结果1.status_code 2.db校验 3.content正则匹配
    :param self:
    :param i:  行
    :param code:
    :param content:
    :return:
    '''
    #判断结果是pass还是fail
    if int(code) == 200 :
        if checkdb.check(sheetname,i)[0] == 'pass':
            print re.search(str(get.get_data(sheetname,i,10)),content)!=None
            if re.search(str(get.get_data(sheetname,i,10)),content)!=None:
                return 'pass'
            elif re.search(get.get_data(sheetname,i,10),content) is None:
                return 'fail'
        else:
            return 'fail'
    else:
        return 'fail'

testcase部分介绍

testcase部分,目前是一个模块一个用例,以商品模块为例,代码如下:

  • 从配置文件中读取url
  • 逐行进行数据读取
  • 根据读取的数据发送请求
  • 调用check_all判定结果
  • 将结果写入Excel中
test_pd.py
class Pd(unittest.TestCase):

    def test_pd(self):
        cookie = test_login.login()
        common_url=conf.ReadConfig().getloginConfigValue('url')

        for i in range(int(get.get_nrows('pd'))-1):
            # 判断是否执行
            if int(get.get_data('pd',i+1,4))== 1:
                login_url=get.get_data('pd',i+1,2)
                url = common_url + login_url
                data = get.get_formdata('pd',i+1)
                header = {"Content-Type": "application/x-www-form-urlencoded","Cookie":cookie}
                global r
                print url
                if get.get_data('pd',i+1,3) == 'post':
                    r=requests.post(url=url,headers=header,data=data)

                    if checkall.checkall('pd',i+1,r.status_code,r.content) == 'pass':
                        set.set_result(1,i+1,'pass')
                    elif checkall.checkall('pd',i+1,r.status_code,r.content) == 'fail':
                        set.set_result(1,i+1,'fail')

                    set.set_statuscode(1,i+1,r.status_code)
                    set.set_content(1,i+1,r.content.decode('UTF-8'))
                    set.set_sql(1,i+1,checkdb.check('pd',i+1)[1])

                elif get.get_data('pd',i+1,3) == 'get':
                    r=requests.get(url=url,headers=header,data=data)

                    if checkall.checkall('pd',i+1,r.status_code,r.content) == 'pass':
                        set.set_result(1,i+1,'pass')
                    elif checkall.checkall('pd',i+1,r.status_code,r.content) == 'fail':
                        set.set_result(1,i+1,'fail')

                    set.set_statuscode(1,i+1,r.status_code)
                    set.set_content(1,i+1,r.content.decode('UTF-8'))
                    set.set_sql(1,i+1,checkdb.check('pd',i+1)[1])

            elif int(get.get_data('pd',i+1,4))== 0:
                print 'not execute'
                set.set_result(1,i+1,'not execute')

if __name__ == "__main__":
    Pd()

执行所有用例,用的是

test_runner.py

将需要执行的用例导入即可

from testcase.test_cm import Cm
from testcase.test_pd import Pd


def testsuit():
    suite = unittest.TestSuite()
    suite.addTests([unittest.defaultTestLoader.loadTestsFromTestCase(Cm),
                    unittest.defaultTestLoader.loadTestsFromTestCase(Pd),


                   ])

    runner = unittest.TextTestRunner(verbosity=2)

    runner.run(suite)

if __name__ =="__main__":
    testsuit()

以上所有,代码部分介绍结束

思考

一点小思考,这套模型主要试用与一些基础接口测试,如基础的查询、修改等
如果遇到一些业务上的强依赖,如新增一个订单,一个接口需要调用上一个订单会的值,这种下一个接口依赖上一个接口的,就不能用在一个for 循环中逐行读取数据,在发送请求了。
目前来看,个人觉得有下面几个缺陷:

  • 报告的展示,批量执行时结果可能不太直观(这个可以后期优化,依赖Excel,直接生成饼状图等等)
  • 缺少通知与失败重新跑机制(通知可以后续加上邮件,失败重跑也可以加上判断,fail重新执行一次)
  • 对用例设计要求较高,由于是直接读取的Excel表格,如果表格数据出错,可能就会导致用例失败等情况

还有其他一些缺陷吧,欢迎有想法的小伙伴批评指正。
附上 Github地址,欢迎拍砖!

你可能感兴趣的:(接口测试框架优化(二)---主要代码)