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

前言

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

结构介绍

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

common部分主要是进行:

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

testcase部分主要是各个case:

  • 逐行读取Excel
  • 发送请求
  • 将返回的结果写入Excel
结构.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地址,欢迎拍砖!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容