zoukankan      html  css  js  c++  java
  • Python+Excel+Unittest+HTMLTestRunner实现数据驱动接口自动化测试(二)

    因为小白,这2天研究了好久才算是搞好。先附上一个测试完成后邮件的截图:

    上一篇有提到:

    unittest中实际运行了一个接口的很多条用例,而报告中只会有一条记录。这是因为unittest test case中我只写了一个test方法,循环测试数据。这样写用例更简单,目前在想是从报告中处理,还是测试用例读取部分进行处理。

    而且这个问题会导致后续写test case出错几率大,而且耗时较多。经过几天的思考,写了个简易的解决办法。思路:轻微修改excel读取通过excel名/sheet名/用例id名来返回数据,那我们就可以在一个unittest case中固化test_开头的测试方法,如10条(我们约定excel中每个sheet最多写10条用例)。 这里我们在excel中添加一个“是否执行用例”字段,unittest中启动skipIf方法来确认是否跳过该用例,即可完美解决上一篇的问题。

    excel用例数据截图:(增加runselect字段 YES代表执行用例,No代表不执行)

     那我们的OperateExcel方法也做轻微修改:

    def Readexcelrow_of_sheet(filename,sheet_name,row):
        '''返回某个sheet中某一行数据的列表'''
        folder = "C:\Users\LENOVO\PycharmProjects\Apiautotest-master\testdata\"
        fullfilename = folder + filename
        rb = xlrd.open_workbook(fullfilename)
        sheet = rb.sheet_by_name(sheet_name)
        datalist = []
        for i in range(10):
            if sheet.cell_value(row,9) =="YES":
                try:
                    data = sheet.cell_value(row,i)
                    datalist.append(data)
                except TypeError as f:
                    break
            #print (datalist)
        return datalist
    
    def Readexcelalldata_of_sheet(filename,sheet_name):
        '''返回整个sheet的内容的列表'''
        datalistlist =[]
        for i in range(1,100):
            try:
                data = Readexcelrow_of_sheet(filename,sheet_name,i)
                datalistlist.append(data)
            except IndexError as e:
                break
        #print(datalistlist)
        return  datalistlist
    

    这里我们增加一个数据处理DataProcess方法,把excel读取的整个sheet数据(是一个列表,它的元素也是列表),我们用这个方法,根据行号返回一个json数据,也就是我们每条用例所要测试请求的数据。

    import json
    
    def DataProcess(datalist,myindex):
        '''datalist是一个列表,列表的元素也是列表,是从excel读到的指定sheet全部数据,根据index返回一个标准化的dict'''
        data = datalist[myindex]
        caseid =       data[0]
        casename =     data[1]
        method =       data[2]
        url =          data[3]
        payload =      data[4].encode('utf-8')
        expectedcode = data[5]
        expectedmsg =  data[6]
        expecteddata = data[7]
        headers =      json.loads(data[8])
        runselect =    data[9]
    
        newdict = {"runselect":runselect,
                   "method":method,
                   "caseid":caseid,
                   "url":url,
                   "data":payload,
                   "headers":headers,
                   "expectedcode":expectedcode,
                   "expectedmsg":expectedmsg,
                   "expecteddata":expecteddata}
    
        return newdict
    

      

    我们的test case样子如下:每个test方法除了一个数据处理的入参不一样,其他完全一致,无需更改。 而且我们可以做到所有的测试用例都按这个模板来撰写。

    class LoginTest(unittest.TestCase):
        ''' '''
    
        def setUp(self):
            self.logname = logname
            self.mylog = AddLog.AddLog(self.logname).getlog()
            self.testcaseinfo = OperateExcel.Readexcelalldata_of_sheet(Excelname,Sheetname)
            self.result = {}
            global caseid
            caseid += 1
    
        def tearDown(self):
            self.mylog.info("case:%d completed" % caseid)
    
        @unittest.skipIf((max_testcaseid < 1) or (0 in indexlist),"用例最大id<1或用例标记为'不执行'")
        def test_caseid_1(self):
            testdata = DataProcess.DataProcess(self.testcaseinfo,0)
            headers= {"Content-Type": "application/json"}
            self.result = RunRequest.RunRequests(testdata["method"],
                                                 testdata["url"],
                                                 testdata["data"],
                                                 testdata['headers']).run()
            self.myassert = AssertResult.AssertResult(self.logname, testdata, self.result)
            self.myassert.AssertEqualResult()
    
        @unittest.skipIf((max_testcaseid < 2) or (1 in indexlist),"用例最大id<2或用例标记为'不执行'")
        def test_caseid_2(self):
            testdata = DataProcess.DataProcess(self.testcaseinfo, 1)
            self.result = RunRequest.RunRequests(testdata["method"],
                                                 testdata["url"],
                                                 testdata["data"],
                                                 testdata['headers']).run()
            self.myassert = AssertResult.AssertResult(self.logname,testdata,self.result)
            self.myassert.AssertEqualResult()
    
        @unittest.skipIf((max_testcaseid < 3) or (2 in indexlist),"用例最大id<3或用例标记为'不执行'")
        def test_caseid_3(self):
            testdata = DataProcess.DataProcess(self.testcaseinfo, 2)
            self.result = RunRequest.RunRequests(testdata["method"],
                                                 testdata["url"],
                                                 testdata["data"],
                                                 testdata['headers']).run()
            self.myassert = AssertResult.AssertResult(self.logname,testdata,self.result)
            self.myassert.AssertEqualResult()
    
        @unittest.skipIf((max_testcaseid < 4) or (3 in indexlist), "用例最大id<4或用例标记为'不执行'")
        def test_caseid_4(self):
            testdata = DataProcess.DataProcess(self.testcaseinfo, 3)
            self.result = RunRequest.RunRequests(testdata["method"],
                                                 testdata["url"],
                                                 testdata["data"],
                                                 testdata['headers']).run()
            self.myassert = AssertResult.AssertResult(self.logname,testdata,self.result)
            self.myassert.AssertEqualResult()
    

      因为要用到不同请求方式,我们把他封装在一起了。

    #coding = utf-8
    import requests
    import json
    
    class RunRequests(object):
    
        def __init__(self,method,url,data,headers):
    
            self.url = url
    
            self.method = method
    
            self.data = data
    
            self.headers = headers
    
            self.result = ""
    
    
        def run(self):
    
            if self.method == "POST":
    
                if self.headers != "No":
    
                    self.result = requests.post(self.url, data = self.data, headers = self.headers)
    
                else:
                    self.result = requests.post(self.url, data = self.data)
    
    
            elif self.method == "GET":
    
                if self.headers != "No":
    
                    self.result = requests.get(self.url, data=self.data)
    
                    print("暂未处理headers")
    
                else:
                    self.result = requests.get(self.url,data = self.data)
    
            elif self.method == "PUT":
    
                self.result = 1
    
            elif self.method == "DELETE":
    
                self.result = 1
    
            elif self.method == "HEAD":
    
                self.result = 1
    
            else:
    
                self.result = 1
    
            return  self.result.json()
    

      

    这些都完成后,想到测试完成后需要日志和邮件功能。也添加进来。

    写完后整个框架就如下这个样子:

     如果有朋友看到,觉得可以学习练练手,有需要源码可以留言,看到会及时回复。

  • 相关阅读:
    XGBoost原理解析
    变分贝叶斯学习(variational bayesian learning)及重参数技巧(reparameterization trick)
    Tensorflow Probability Distributions 简介
    树形dp--hdu 1520 anniversary party
    线段树II--区间修改
    leetcode---different ways to add parentheses
    线段树
    实现最大堆
    编写支持对齐分配的malloc和free函数
    指针和引用的区别,指针和数组的区别
  • 原文地址:https://www.cnblogs.com/Sandy-1128/p/appium-python-sandy-0316-1.html
Copyright © 2011-2022 走看看