zoukankan      html  css  js  c++  java
  • Unittest框架(生成报告,管理case,添加断言)

    1.安装python的时候自带了unittest

    2.创建一个类的时候必须要继承unittest

    class TestMethod(unittest.TestCase)

    3.setUp、tearDown方法

    setUp():setUp()方法用于测试用例执行前的初始化工作。如测试用例中需要访问数据库,可以在setUp中建立数据库连接并进行初始化。如测试用例需要登录web,可以先实例化浏览器。

    tearDown():tearDown()方法用于测试用例执行之后的善后工作。如关闭数据库连接。关闭浏览器。

    #每次方法之前执行
    def
    setUp(self): print(‘test-setup’)
    #每次方法之后执行
    def tearDown(self): print(‘test-teardown’)

    4.加上类方法

    # -*- coding: utf-8 -*-
    import unittest
    class TestMethod(unittest.TestCase):
       @classmethod   #说明是类方法,只会执行一次
       def setUpClass(cls):
         print('类执行之前的方法')
       @classmethod
       def tearDownClass(cls):
         print('类执行之后的方法')
        
    #每次方法之前执行
       def setUp(self):
          print('test-setup')
    #每次方法之后执行
       def tearDown(self):
          print('test-teardown')
       def test_01(self):
        print('第一个测试')
       def test_02(self):
        print('第二个测试')
    
    if __name__ == '__main__':
       unittest.main()

    有2条测试用例,所以都会调用2次setup和teardown方法,为了只调用一次,加入了类方法

    执行结果:

    把setup和teardown方法去掉

    # -*- coding: utf-8 -*-
    import unittest
    class TestMethod(unittest.TestCase):
       @classmethod   #说明是类方法,只会执行一次
       def setUpClass(cls):
         print('类执行之前的方法')
       @classmethod
       def tearDownClass(cls):
         print('类执行之后的方法')
       def test_01(self):
        print('第一个测试')
       def test_02(self):
        print('第二个测试')
    
    if __name__ == '__main__':
       unittest.main()

    执行结果:

     5.unittest和requests重构封装

     把demo.py和本脚本放在一个目录下,导入demo的RunMain类。

    #demo.py

    import
    requests import json class RunMain: #当前类的第一个参数是self def send_get(self,url): res = requests.get(url=url).json() r = json.dumps(res,indent=2,sort_keys=True) return r def send_post(self,url,data): res = requests.post(url=url,data=data).json() r = json.dumps(res,indent=2,sort_keys=True) return r def run_main(self,url,method,data=None): #把data数据默认为空,因为get不用传数据,空参数要放在有值参数后面 res = None if method == 'GET': res = self.send_get(url) else: res = self.send_post(url,data) return res if __name__ == '__main__': #这种写法就是每次都要先实例化,然后再去调用run_main run = RunMain() url = 'http://127.0.0.1:8000/login/?username=dajiu&password=123' data = { 'username':'dajiu', 'password':'123456' } print(run.run_main(url,'POST',data))
    #uni_test.py

    import
    unittest from demo import RunMain #导入类 class TestMethod(unittest.TestCase): def setUp(self): self.run = RunMain() #每次都实例化 def test_01(self): url = 'http://127.0.0.1:8000/login/?username=dajiu&password=123' data = { 'username':'dajiu2', 'password':'123456' } res = self.run.run_main(url,'POST',data) print(res) def test_02(self): url = 'http://127.0.0.1:8000/login/?username=dajiu&password=123' data = { 'username':'dajiu1', 'password':'123456' } res = self.run.run_main(url,'POST',data) print(res) if __name__ == '__main__': unittest.main()

    运行结果:

     注意,case里面的url必须和demo.py里的url一致。

    6.增加断言

    另外使用一个post地址进行实践,该接口返回本来就是json格式,所以这里做接口测试的时候就不用再做数据处理

    #demo.py

    import
    requests class RunMain: #当前类的第一个参数是self def send_get(self,url): res = requests.get(url=url) return (res.text) def send_post(self,url,data): res = requests.post(url=url,data=data) return res def run_main(self,url,method,data=None): #把data数据默认为空,因为get不用传数据,空参数要放在有值参数后面 res = None if method == 'GET': res = self.send_get(url) else: res = self.send_post(url,data) return (res.text) if __name__ == '__main__': #这种写法就是每次都要先实例化,然后再去调用run_main run = RunMain() url = 'http://10.1.30.118:3200/provider/user/user/login?loginName=15519560000&loginModel=0&password=12345678&loginType=01' data = { 'loginName':'15519560000', 'loginModel':'01', 'password':'12345678', 'loginModel':'0', 'timeStamp':'1582616038764' } print(run.run_main(url,'POST',data))

    调用

    #uni_test.py
    #
    -*- coding: utf-8 -*- import unittest import json from demo import RunMain #导入方法 class TestMethod(unittest.TestCase): def setUp(self): self.run = RunMain() #每次都实例化 print('执行开始') def tearDown(self): print('执行结束')
    def test_01(self): url = 'http://10.1.30.118:3200/provider/user/user/login?loginName=15519560000&loginModel=0&password=12345678&loginType=01' data = { 'loginName':'15519560000', 'loginModel':'01', 'password':'12345678', 'loginModel':'0', 'timeStamp':'1582616038764' } res = self.run.run_main(url,'POST',data) r = json.loads(res) #需要用print(type(res))判断返回值的类型是不是字典,如果不是,应该把数据处理成json格式(字典)打印出来
    self.assertEqual(r[
    'code'],'501',‘测试失败’) #增加断言,判断返回的code是否等于501,如果相等,无输出,如果不等,输出测试失败 def test_02(self): url = 'http://10.1.30.118:3200/provider/user/user/login?loginName=15519560001&loginModel=0&password=12345678&loginType=01' data = { 'loginName':'15519560001', 'loginModel':'01', 'password':'12345678', 'loginModel':'0', 'timeStamp':'1582616038764' } res = self.run.run_main(url,'POST',data) r = json.loads(res) self.assertEqual(r['code'],'202',‘测试失败’) if __name__ == '__main__': unittest.main()

    运行结果:

     说明第一条用例通过,第二条失败。

    7.管理case及运用case

    执行case是根据case名称升序执行

    定义全局变量,使case形成依赖关系。如果case顺序相反,就会报错

       def test_01(self):
          globals()['userid'] = '999'  #定义全局变量,把test01和test02建立依赖关系,可用于平时需要保存信息,比如token等
        def test_02(self):
          print(userid)

    运行结果:

     使用类函数跳过case

     @unittest.skip('test_02')   #跳过第二个case,只执行第一个case

    使用测试集TestSuite来执行case

    # -*- coding: utf-8 -*-
    import unittest
    import json
    from demo import RunMain   #导入方法
    class TestMethod(unittest.TestCase):
        def setUp(self):
          self.run = RunMain()   #每次都实例化
        def test_01(self):
          url = 'http://10.1.30.118:3200/provider/user/user/login?loginName=15519560010&loginModel=0&password=12345678&loginType=01'
          data = {
        'loginName':'15519560010',
        'loginModel':'01',
        'password':'12345678',
        'loginModel':'0',
        'timeStamp':'1582616038764'
        }
          res = self.run.run_main(url,'POST',data)
          r = json.loads(res)
          self.assertEqual(r['code'],'501')
          print('第一个case')
          #globals()['userid'] = '999'  #定义全局变量,把test01和test02建立依赖关系,可用于平时需要保存信息,比如token等
        #@unittest.skip('test_02')   #跳过第二个case,只执行第一个case
        def test_02(self):
          #print(userid)
          url = 'http://10.1.30.118:3200/provider/user/user/login?loginName=15519560000&loginModel=0&password=12345678&loginType=01'
          data = {
        'loginName':'15519560000',
        'loginModel':'01',
        'password':'12345678',
        'loginModel':'0',
        'timeStamp':'1582616038764'
        }
          res = self.run.run_main(url,'POST',data)
          r = json.loads(res)
          self.assertNotEqual(r['code'],'202','测试失败')   #不等于
          print('第二个case')
    if __name__ == '__main__':
        sutie = unittest.TestSuite()#创建一个容器,放case
        sutie.addTest(TestMethod('test_02'))
        sutie.addTest(TestMethod('test_01'))#想放几个case就放几个case,一个case一条语句,按照添加case的顺序作为执行顺序
        unittest.TextTestRunner().run(sutie)

    8.unittest和HTMLTestRunner结合生成报告

    下载HTMLTestRunner(要下载python3版本的才可以用,不然会报错)

    下载地址:http://pan.baidu.com/s/1dEZQ0pz  

    把文件放在安装目录的Lib下

    使用cmd,import HTMLTestRunner检查是否安装成功

    # -*- coding: utf-8 -*-
    import unittest
    import json
    from demo import RunMain   #导入方法
    import HTMLTestRunner
    class TestMethod(unittest.TestCase):
        def setUp(self):
          self.run = RunMain()   #每次都实例化
        def test_01(self):
          url = 'http://10.1.30.118:3200/provider/user/user/login?loginName=15519560000&loginModel=0&password=12345678&loginType=01'
          data = {
        'loginName':'15519560000',
        'loginModel':'01',
        'password':'12345678',
        'loginModel':'0',
        'timeStamp':'1582616038764'
        }
          res = self.run.run_main(url,'POST',data)
          r = json.loads(res)
          self.assertEqual(r['code'],'501')
          print('第一个case')
          #globals()['userid'] = '999'  #定义全局变量,把test01和test02建立依赖关系,可用于平时需要保存信息,比如token等
        #@unittest.skip('test_02')   #跳过第二个case,只执行第一个case
        def test_02(self):
          #print(userid)
          url = 'http://10.1.30.118:3200/provider/user/user/login?loginName=15519560001&loginModel=0&password=12345678&loginType=01'
          data = {
        'loginName':'15519560001',
        'loginModel':'01',
        'password':'12345678',
        'loginModel':'0',
        'timeStamp':'1582616038764'
        }
          res = self.run.run_main(url,'POST',data)
          r = json.loads(res)
          self.assertNotEqual(r['code'],'202','测试失败')   #不等于
          print('第二个case')
    if __name__ == '__main__':
        filepath = "../report/test_report.html"  #打开文件
        fp = open(filepath,'wb')     #以读写模式打开文件
        sutie = unittest.TestSuite()#创建一个容器,放case
        sutie.addTest(TestMethod('test_02'))
        sutie.addTest(TestMethod('test_01'))#想放几个case就放几个case,一个case一条语句,按照添加case的顺序作为执行顺序
        runner = HTMLTestRunner.HTMLTestRunner(stream=fp,title='This is my first testreport')#设置报告的流文件和报告名字
        runner.run(sutie)#调用case集合,使htmltestrunner与unittest结合起来
        #unittest.TextTestRunner().run(sutie)

    运行结果:

    查看报告:

     修改代码,使用例执行失败:

    扩展:使用unittest编写测试用例思路

    设计基本思路如下:

    Project:使用unittest框架编写测试用例思路'''#3.导入unittest模块import unittest#4.定义测试类,父类为unittest.TestCase。#可继承unittest.TestCase的方法,如setUp和tearDown方法,不过此方法可以在子类重写,覆盖父类方法。#可继承unittest.TestCase的各种断言方法。class Test(unittest.TestCase):

        #5.定义setUp()方法用于测试用例执行前的初始化工作。#注意,所有类中方法的入参为self,定义方法的变量也要“self.变量”#注意,输入的值为字符型的需要转为int型def setUp(self):

            self.number=raw_input('Enter a number:')

            self.number=int(self.number)#6.定义测试用例,以“test_”开头命名的方法#注意,方法的入参为self#可使用unittest.TestCase类下面的各种断言方法用于对测试结果的判断#可定义多个测试用例#最重要的就是该部分def test_case1(self):

            print self.number

            self.assertEqual(self.number,10,msg='Your input is not 10')

        def test_case2(self):

            print self.number

            self.assertEqual(self.number,20,msg='Your input is not 20')

        @unittest.skip('暂时跳过用例3的测试')

        def test_case3(self):

            print self.number

            self.assertEqual(self.number,30,msg='Your input is not 30')#7.定义tearDown()方法用于测试用例执行之后的善后工作。#注意,方法的入参为selfdef tearDown(self):

            print'Test over'#8如果直接运行该文件(__name__值为__main__),则执行以下语句,常用于测试脚本是否能够正常运行if__name__=='__main__':#8.1执行测试用例方案一如下:#unittest.main()方法会搜索该模块下所有以test开头的测试用例方法,并自动执行它们。#执行顺序是命名顺序:先执行test_case1,再执行test_case2    unittest.main()'''#8.2执行测试用例方案二如下:#8.2.1先构造测试集#8.2.1.1实例化测试套件    suite=unittest.TestSuite()#8.2.1.2将测试用例加载到测试套件中。#执行顺序是安装加载顺序:先执行test_case2,再执行test_case1    suite.addTest(Test('test_case2'))    suite.addTest(Test('test_case1'))#8.2.2执行测试用例#8.2.2.1实例化TextTestRunner类    runner=unittest.TextTestRunner()#8.2.2.2使用run()方法运行测试套件(即运行测试套件中的所有用例)    runner.run(suite)

    ''''''#8.3执行测试用例方案三如下:

    #8.3.1构造测试集(简化了方案二中先要创建测试套件然后再依次加载测试用例)

    #执行顺序同方案一:执行顺序是命名顺序:先执行test_case1,再执行test_case2

        test_dir = './'

        discover = unittest.defaultTestLoader.discover(test_dir, pattern='test_*.py')

    #8.3.2执行测试用例

    #8.3.2.1实例化TextTestRunner类

        runner=unittest.TextTestRunner()

    #8.3.2.2使用run()方法运行测试套件(即运行测试套件中的所有用例)

        runner.run(discover)  '''

    使用方案一执行测试用例结果如下:

    Enter a number:10

    10

    Test over

    Enter a number:.10

    Fs

    Ran 3 tests in 6.092s

    FAILED (failures=1, skipped=1)

    10

    Test over

    因为先执行test_case1,再执行test_case2,所以第一次输入10时,执行通过,返回. 第二次输入10时,执行不通过,返回F,最终一个用例通过,一个用例失败,还有一个用例是直接跳过的(装饰器)。

    使用方案二执行测试用例结果如下:

    Enter a number:10

    10

    Test over

    Enter a number:F10

    .

    Ran 2 tests in 4.973s

    FAILED (failures=1)

    10

    Test over

    因为先执行test_case2,再执行test_case1,所以第一次输入10时,执行不通过,返回F , 第二次输入10时,执行通过,返回. ,最终一个用例通过,一个用例失败。

  • 相关阅读:
    SQL Server XML数据解析
    c# XML和实体类之间相互转换(序列化和反序列化)
    C#解析XML详解(XPath以及带命名空间NameSpace)
    Jquery实现按钮点击遮罩加载,处理完后恢复
    jquery控制div随滚动条滚动效果
    asp.net中利用Jquery+Ajax+Json实现无刷新分页(二)
    easyUI tree点击文字展开节点
    201805牛客模拟考
    策略模式
    非线程安全演变成线程安全---原子性与加锁机制
  • 原文地址:https://www.cnblogs.com/dydxw/p/12361385.html
Copyright © 2011-2022 走看看