探索框架(七)--在框架驱动程序中设计自定义测试报告以及wxpython单选按钮的使用

导语

        之前已经基本完成了驱动程序调用用例脚本的执行,在探索框架(二)中也总结了如何利用HTMLTestRunner生成测试报告,本次尝试自定义编写测试报告,输出内容较为灵活。

一、修改框架UI原型设计

        输出的测试报告可以选用CSV格式,也可以利用HTMLTestRunner生成测试报告,这里主要是要实践一下wxpython中如何使用单选按钮,修改原型图如下:

图1 原型设计修改

        默认选中“生成CSV形式的测试报告”,这里只能单选其一,且不能取消单选,可以用wx.RadioButton,不得不说,wxpython还是比较好用的,非常方便就可以画好以上的原型图。根据之前探索框架(四) 的分析,这里需要稍作修改,画界面时,将两个单选按钮设计为一组(第二组),利用垂直分布boxsizer即可,将原先的下方的三个按钮设计为第三组,这样要注意在最后加入整体boxsizer中的顺序,具体代码如下:

# 测试框架界面类的实现
class testframe_UI():
    # 初始化方法定义界面窗体控件及容器
    def __init__(self):
        ......
        # 定义选择测试报告类型的单选按钮
        self.csv_radiobut = wx.RadioButton(self.panel, label="生成csv形式的测试报告")
        # 默认选中csv_radiobut
        self.csv_radiobut.SetValue(1)
        self.html_radiobut = wx.RadioButton(self.panel, label="生成html形式的测试报告(仅支持unittest测试用例脚本)")

    # 定义控件布局
    def lauout_UI(self):
        ......
        # 定义垂直放置的boxsizer2,用于存放两个单选按钮
        boxsizer2 = wx.BoxSizer(wx.VERTICAL)
        boxsizer2.Add(self.csv_radiobut, flag=wx.DOWN, border=10)
        boxsizer2.Add(self.html_radiobut)

        # 定义水平放置的boxsizer3,用于存放运行、重置、退出按钮(无改动,省略显示)
        boxsizer3 = wx.BoxSizer()
        ......

        # 定义垂直放置的boxsizer4,用于存放boxsizer1、boxsizer2、boxsizer3
        boxsizer4 = wx.BoxSizer(wx.VERTICAL)
        boxsizer4.Add(boxsizer1, flag=wx.TOP | wx.EXPAND, border=30)
        boxsizer4.Add(boxsizer2, flag=wx.LEFT, border=40)
        boxsizer4.Add(boxsizer3, flag=wx.LEFT, border=20)

        # 设置boxsizer生效
        self.panel.SetSizer(boxsizer4)

        其中“......”省略了之前不需要修改的代码,这样一来,UI就画好了,接下来是与按钮相关的测试报告的生成,需要新设计一个测试报告类,初步设计如下:

图2 测试报告类及方法的设计

 

二、生成测试报告

 1、修改run_driver方法

        因为加入了测试报告的选择,那么在点击“运行”按钮时需要去根据选项来执行相应的方法,所以在“运行”按钮绑定事件的方法run_driver需要做一个判断,修改代码如下:

    def run_driver(self, event):
        # 进行文本框的非空校验(代码不需要修改,在这里省略)
        ......
        # 调用测试驱动程序
        # 实例化测试驱动类
        objdriver = testframe_driver()
        # 根据单选按钮的选项,调用测试驱动类中的不同的执行方法
        if self.csv_radiobut.GetValue() == 1:
            objdriver.run_configfile_csv(self.configfile)
        elif self.html_radiobut.GetValue() == 1:
            objdriver.run_configfile_html(self.configfile)

2、新增CSV报告类和创建报告方法

        根据run_driver方法的修改,而去调用的run_configfile_csv方法(原来为run_configfile)也需要修改,修改如下:

# 测试驱动类
class testframe_driver():
    # 定义执行配置文件生成csv报告方法
    def run_configfile_csv(self, configfile):
        # 实例化测试报告类
        objreport = testframe_report()
        # 调用创建并打开文件方法
        objreport.open_report()
        # 读取配置文件内容(后续暂时不修改,省略显示)
        ......

        在已经选好了生成CSV报告后,在读取配置文件运行脚本前,就需要创建打开测试报告,调用open_report方法(新建的类及方法),具体代码如下:

# 测试报告类
class testframe_report():
    def __init__(self):
        # 获取当前路径
        self.curpath = os.getcwd()
        # 获取项目路径
        self.projectpath = os.path.abspath(os.path.dirname(self.curpath) + os.path.extsep + ".")

    # 创建并打开文件
    def open_report(self):
        # 先判断报告是否存在,若存在就移除
        reportpath = self.projectpath + "\\test_report\\fram_report\\framereport.csv"
        if os.path.exists(reportpath):
            os.remove(reportpath)
        self.reportfile = open(reportpath, "a", newline="")
        self.write = csv.writer(self.reportfile)

        创建好了测试报告,接下来就是测试报告标题的设计部分。

3、在已创建的测试报告中写入标题行

        标题一部分可以借用配置文件的标题,配置文件如下图所示

图3 配置文件

         再在“是否执行”后加上一列“测试结论”,这样每个脚本中用例执行的结论也都可以清晰的展示了,这需要在测试报告类testframe_report()中加入新的方法写入标题write_title,具体代码如下:

# 测试报告类
class testframe_report():
    def __init__(self):
    # 创建并打开文件
    def open_report(self):
    # 写入报告标题
    def write_title(self):
        file = open(self.projectpath + "\config\config2.csv", "r")
        table = csv.reader(file)
        title = list(table)[0]
        self.write.writerow(title + ["测试结论"])
        self.reportfile.close()

        仍然是在原先的run_configfile_csv方法中,读取完配置文件就可以去调用write_title写入标题,具体代码如下:

# 测试驱动类
class testframe_driver():
    # 定义执行配置文件生成csv报告方法
    def run_configfile_csv(self, configfile):
        # 实例化测试报告类
        objreport = testframe_report()
        # 调用创建并打开文件方法
        objreport.open_report()
        # 读取配置文件内容
        file = open(configfile, "r")
        table = csv.reader(file)
        # 调用写入报告标题方法
        objreport.write_title()
        # 跳过第一行
        next(table)
        for ele in table:
            casename = ele[1]
            stros = ('python ' + casename)
            ......

        到这里,其实就可以先运行调试一下,看是否如预期一样生成了测试报告,并写入了标题,运行无问题以后,接下来就开始写入相关用例执行情况。

4、在写好的标题行下面逐行写入每个脚本的测试结论

        这里先分析一下报告内容的组成,前面三列是可以从配置文件中去获取的,但是第四列“测试结论”,需要从不同的运行的脚本中去获取,且每个脚本中可能有多条用例,每条用例都会有相应的测试结论,最后需要把这一个脚本中所有的用例结论合在一起写入“测试结论”这一列,这样可以中间用一个临时文件过渡一下,将脚本运行完的所有用例的测试结论写入临时文件中,再去读取临时文件将整个内容写入测试报告的“测试结论”中。

        需要在testframe_report()中先加入两个新方法,代码如下:

# 测试报告类
class testframe_report():
    def __init__(self):
    # 创建并打开文件
    def open_report(self):
    # 写入报告标题
    def write_title(self):

    # 将脚本执行的测试结果写入临时文件中
    def write_tmp(self, scriptresult):
        tmp = open(self.projectpath + "\\test_report\\fram_report\\tmp.txt", "w")
        tmp.write(scriptresult+"\n")
        tmp.close()

    # 读取临时文件
    def read_tmp(self):
        tmp = open(self.projectpath + "\\test_report\\fram_report\\tmp.txt", "r")
        result = tmp.read().split("\n")
        self.result = result[0]
        tmp.close()

        这里需要注意两点,一是在每个脚本中需要去调用这个write_tmp方法,才可以将结论写入临时文件中,代码如下:

# 脚本程序文件内容省略,以下仅显示调用write_tmp方法

if __name__ == '__main__':
    ......
    # 实例化框架脚本中的编写测试报告类
    objreport=testframe_report()
    # 调用测试报告类中的写入临时文件方法,将测试结果写入临时文件中
    objreport.write_tmp(str(scriptresult))

        二是写入临时文件的方式需要用“w”方式,因为每个脚本执行结束都会有新的结论,需要覆盖写入才行。此后就需要在原先的run_configfile_csv方法中,在调用运行完脚本以后,调用read_tmp方法,读取相关结论,代码如下:

# 测试驱动类
class testframe_driver():
    # 定义执行配置文件生成csv报告方法
    def run_configfile_csv(self, configfile):
        ......        
        # 跳过第一行
        next(table)
        for ele in table:
            casename = ele[1]
            stros = ('python ' + casename)
            if ele[2] == "yes":
                # 执行脚本
                os.system(stros)
                # 调用读取临时文件方法,获取测试用例执行结果
                objreport.read_tmp()
                # 调用写入测试结果方法
                objreport.write_result(ele[0], ele[1], ele[2], objreport.result)

        读取完一次临时文件中的内容,就需要调用一次write_result方法,将测试结论写入测试报告中,这样需要在testframe_report()中再加入一个方法write_result,代码如下:

# 测试报告类
class testframe_report():
    def __init__(self):
    # 创建并打开文件
    def open_report(self):
    # 写入报告标题
    def write_title(self):
    
    # 写入报告测试结论
    def write_result(self, casenum, casename, runstate, result):
        self.reportfile = open(self.projectpath + "\\test_report\\fram_report\\framereport.csv", "a", newline="")
        self.write = csv.writer(self.reportfile)
        self.write.writerow([casenum]+[casename]+[runstate]+[result])
        self.reportfile.close()

    # 将脚本执行的测试结果写入临时文件中
    def write_tmp(self, scriptresult):
    # 读取临时文件
    def read_tmp(self):

        到这里需要运行调试一下,看是否如预期将相应的测试结论写入测试报告中,大概报告如下:

图4 测试报告

 5、在csv测试报告中最后写入统计数据

        同样也是需要通过临时文件来过渡,有了之前写好的方法,只需要加上新的参数即可,首先是每个脚本中需要增加新的参数,成功总数和失败总数,代码如下:

# 脚本程序文件内容省略,以下仅显示调用write_tmp方法

if __name__ == '__main__':
    ......
    # 实例化框架脚本中的编写测试报告类
    objreport=testframe_report()
    # 调用测试报告类中的写入临时文件方法,将测试结果、成功总数、失败总数写入临时文件中
    objreport.write_tmp(str(scriptresult), str(obj.sucnum), str(obj.errnum))

        其次是修改write_tmp和read_tmp方法,代码如下:

# 测试报告类
class testframe_report():
    def __init__(self):
    # 创建并打开文件
    def open_report(self):
    # 写入报告标题
    def write_title(self):
    # 写入报告测试结论
    def write_result(self, casenum, casename, runstate, result):

    # 将脚本执行的测试结果写入临时文件中
    def write_tmp(self, scriptresult, sucnum, errnum):
        tmp = open(self.projectpath + "\\test_report\\fram_report\\tmp.txt", "w")
        tmp.write(scriptresult+"\n")
        tmp.write(sucnum+"\n")
        tmp.write(errnum+"\n")
        tmp.close()

    # 读取临时文件
    def read_tmp(self):
        tmp = open(self.projectpath + "\\test_report\\fram_report\\tmp.txt", "r")
        result = tmp.read().split("\n")
        self.result = result[0]
        self.sucnum = result[1]
        self.errnum = result[2]
        tmp.close()

        然后去修改run_configfile_csv方法中关于成功、失败、总耗时的统计,代码如下:

# 测试驱动类
class testframe_driver():
    # 定义执行配置文件生成csv报告方法
    def run_configfile_csv(self, configfile):
        ......
        # 调用写入报告标题方法
        objreport.write_title()
        sucnum = 0
        errnum = 0
        starttime = datetime.datetime.now()
        # 跳过第一行
        next(table)
        for ele in table:
            casename = ele[1]
            stros = ('python ' + casename)
            if ele[2] == "yes":
                # 执行脚本
                os.system(stros)
                # 调用读取临时文件方法,获取测试用例执行结果
                objreport.read_tmp()
                # 调用写入测试结果方法
                objreport.write_result(ele[0], ele[1], ele[2], objreport.result)
                sucnum = sucnum + int(objreport.sucnum)
                errnum = errnum + int(objreport.errnum)
        endtime = datetime.datetime.now()
        totaltime = (endtime-starttime).seconds
        # 调用写入统计方法
        objreport.write_count(sucnum, errnum, totaltime)

        最后在测试报告类中加入最后的统计方法write_count,代码如下:

# 测试报告类
class testframe_report():
    def __init__(self):
    # 创建并打开文件
    def open_report(self):
    # 写入报告标题
    def write_title(self):
    # 写入报告测试结论
    def write_result(self, casenum, casename, runstate, result):

    # 写入测试统计结果
    def write_count(self, sucnum, errnum, totaltime):
        self.reportfile = open(self.projectpath + "\\test_report\\fram_report\\framereport.csv", "a", newline="")
        self.write = csv.writer(self.reportfile)
        totalnum = sucnum + errnum
        self.write.writerow(["测试用例总数"] + [totalnum] + ["条"])
        self.write.writerow(["测试用例成功数"] + [sucnum] + ["条"])
        self.write.writerow(["测试用例失败数"] + [errnum] + ["条"])
        self.write.writerow(["执行用例总耗时"] + [totaltime] + ["秒"])
        self.reportfile.close()

    # 将脚本执行的测试结果写入临时文件中
    def write_tmp(self, scriptresult, sucnum, errnum):
    # 读取临时文件
    def read_tmp(self):

        至此,自定义的测试报告设计就完成了,最终的效果大概如下图(图5),其中的内容会根据配置文件的变化而相应的变化。

图5 最终测试报告

 6、利用HTMLTestRunner生成测试报告

        最后一项任务,是当选择了"生成html形式的测试报告(仅支持unittest测试用例脚本)"时,需要去调用相应的方法,这里需要说明的是,只有脚本是基于unittest编写的才会生效。由于是利用HTMLTestRunner生成测试报告,路径名和脚本名需要分开使用,可以设计新的配置文件,如下:

图6 基于unittest脚本的配置文件

        在测试驱动类testframe_driver中加入新的方法run_configfile_html,代码如下:

# 测试驱动类
class testframe_driver():
    # 定义执行配置文件生成csv报告方法
    def run_configfile_csv(self, configfile):

    # 定义执行配置文件生成html报告方法
    def run_configfile_html(self, configfile):
        file = open(configfile, "r")
        table = csv.reader(file)
        next(table)
        i = 1
        for content in table:
            if content[2] == "yes":
                discover = unittest.defaultTestLoader.discover(content[0], pattern=content[1], top_level_dir="父路径")
                htmlreport = open("测试报告路径\htmlreport" + str(i) + ".html", "wb")
                working = HTMLTestRunner(stream=htmlreport, title="html测试报告", description="这是一个简单的描述信息")
                working.run(discover)
                i = i + 1
        file.close()

        由于是执行一个脚本输出一个报告,所以会存在多个报告,在报告名称中就加入了变量i。

        至此,整个关于在框架驱动脚本中加入测试报告的内容就基本结束了,后续可以根据情况再做优化调整。

三、总结

        本次学习如何使用wxpython中的单选按钮,并在原先的框架驱动程序中加入了生成测试报告这一个环节,可以根据需要去选择测试报告的格式,最后再做一个整个程序的梳理,如下图:

图7 总结

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值