Python-UnitTest框架

一、UnitTest基本介绍

1、是什么?

UnitTest是python自带的专门用于单元测试的。一般单元测试是开发做的。(框架:解决一类事情的功能集合)

自带的框架:不需要额外安装,只要安装了python就可以使用 第三方框架:想要使用,需要先安装后使用(pytest)

对于测试来说,使用unittest框架来管理运行多个测试用例的。

2、作用

  • 能够组织多个用例去执行
  • 提供丰富的断言方法(让程序代码代替人工自动判断预期结果和实际结果是否相符合
  • 能够生成测试报告

3、核心要素(组成)

  • TestCase(最核心的模块)

    TestCase(测试用例),注意这个测试用例是unittest框架的组成部分,不是手工和自动化中我们所说的用例(Test Case) 主要作用: 每个 TestCase(测试用例)都是一个代码文件,在这个代码文件中,来书写真正的用例代码
    
  • TestSuite(测试套件)

    TestSuite(测试套件),用来管理 组装(打包)多个TestCase(测试用例)的。也是一个代码文件
  • TestRunner(测试执行)

    TestRunner(测试执行、测试运行),用来执行TestSuite(测试套件)的
  • TestLoader(测试加载)

    TestLoader(测试加载),功能是对TestSuite(测试套件)功能的补充
  • Fixture(测试夹具)

    Fixture(测试夹具),书写在TestCase(测试用例)代码中,是一种代码结构,在每个方法执行前后都会执行的内容 例如:登录的测试用例(把相同且重复的内容放到TestCase中,只写一遍,但每次用例方法的执行,都会自动执行Fixture中的代码) 1.打开浏览器 2.输入网址

二、TestCase(测试用例)

  1. 是一个代码文件,在代码文件中,用来书写真正的用例代码。
  2. 代码文件的名字必须按照标识符的规则来书写,可以将代码的作用在文件的开头使用注释说明
  3. 步骤:
  • ① 导包(unittest) ——import unittest

  • ② 自定义测试类

    class 类名(unittest.TestCase): pass
    
  • ③ 在测试类中书写测试方法

    def test_方法名(self): 用例的代码
  • ④ 执行用例

示例

''' 代码的目的:学习TestCase(测试用例)模块的书写方法 ''' # 1. 导包 import unittest # 2.自定义测试类,需要继承unittest模块中的TestCase类 class TestDemo(unittest.TestCase): # 3.书写测试方法,即 用例代码,目前没有真正的用例代码,使用print代替 # 书写要求,测试方法必须以test_ 开头(本质是以test开头) def test_method1(self): print("测试方法1") def test_method2(self): print("测试方法2") # 4.执行用例(方法) # 4.1 将光标放到类名后面,会执行类里所有方法 # 4.2 放到方法名后面,只执行当前的方法```

  1. 代码书写常见错误:
  • 代码文件命名不规范
  • 代码运行没结果(右键运行没有unittests for 的提示)
  • 没有找到用例(测试方法中不是以test_开头的,或者单词写错了)

三、TestSuite和TestRunner的书写

TestSuite管理、打包、组装TestCase文件

TestRunner执行TestSuite (套件)
步骤:

  • ① 导包(unittest)

  • 实例化(创建对象)套件对象

    suite = unittest.TestSuite()
    
  • ③ 使用套件对象添加用例方法

    suite.addTest(unittest.makeSuite(测试类名))或 suite.addTest(测试类名('方法名'))
    
  • ④ 实例化运行对象

    runner= unittest.TextTestRunner()
    
  • ⑤ 使用运行对象去执行套件对象

    runner.run(suite)
    

示例

''' 学习TestSuite和TestRunner的使用 ''' # 1.导包(unittest) import unittest # 2.实例化(创建对象)套件对象 from testCase1 import TestDemo1 from testCase2 import TestDemo2 suite = unittest.TestSuite() # 3.使用套件对象添加用例方法 #方式一,套件对象.addTest(测试类名(‘方法名’))#建议测试类名和方法名直接去复制,不要手写 suite.addTest(TestDemo1('test_method1')) suite.addTest(TestDemo1('test_method2')) suite.addTest(TestDemo2('test_method1')) suite.addTest(TestDemo2('test_method2')) #方式二,将一个测试类中的所有方法进行添加, #套件对象.addTest(unittest.makeSuite(测试类名)) #缺点:makeSuite()不会提示 suite.addTest(unittest.makeSuite(TestDemo1)) suite.addTest(unittest.makeSuite(TestDemo2)) # 4.实例化运行对象 runner = unittest.TextTestRunner() # 5.使用运行对象去执行套件对象 #运行对象.run(套件对象) runner.run(suite)

运行结果注意:

练习

 

#test.py
#1.导包
import unittest
from tools import add
#2. 自定义测试类
class TestAdd(unittest.TestCase):
    # 3. 书写测试方法,就是测试用例
    def test_method1(self):
        #1,2,3
        if add(1,2) == 3:
            print("测试通过")
        else:
            print("测试不通过")
    def test_method2(self):
        if add(10, 20) == 20:
            print("测试通过")
        else:
            print("测试不通过")

#案例练习 #1.导包 import unittest # 2.实例化(创建对象)套件对象 from test import TestAdd suite=unittest.TestSuite() # 3.使用套件对象添加用例方法 suite.addTest(unittest.makeSuite(TestAdd)) # 4.实例化运行对象 runner = unittest.TextTestRunner() # 5.使用运行对象去执行套件对象 runner.run(suite)

四、TestLoader(测试加载)

作用和TestSuite的作用一样,对TestSuite功能的补充,用来组装测试用例的。比如:如果TestCase的代码文件有很多。

步骤

  • 1.导包

  • 2.实例化测试加载对象并添加用例——>得到的是suite对象

    suite = unittest.TestLoader().discover('用例所在的路径',‘用例的代码文件名’)
    
  • 3.实例化 运行对象

  • 4.运行对象执行套件对象

#1.导包 import unittest #2.实例化加载对象并添加用例 #第一种: unittest.TestLoader().discover('用例所在的路径',‘用例的代码文件名’) # 用例所在的路径,建议使用相对路径,用例的代码文件名可以使用* (任意多个任意字符)通配符 # suite=unittest.TestLoader().discover('./case','test*.py') suite=unittest.TestLoader().discover('./case','*case*.py') #第二种:使用默认的加载对象并加载用例,防止忘记加TestLoader()的括号 suite=unittest.defaultTestLoader.discover('case','*case*') #3. 实例化运行对象 runner= unittest.TextTestRunner() #4.执行 runner.run(suite) #将3,4步合并 # unittest.TextTestRunner().run(suite)

五、Fixture(测试夹具)

是一种代码结构,在某些特定的情况下,会自动执行。 (方法级别和类级别前后的方法,不需要同时出现,根据用例代码的需要自行的选择使用)

1. 方法级别(掌握)

每个测试方法(用例代码)执行前后都会自动调用结构。

#方法执行之前 def setUp(self): 每个测试方法执行之前都会执行 pass #方法执行之后 def tearDown(self): 每个测试方法执行之前都会执行 pass

2.类级别(掌握)

每个测试类中所有方法执行前后都会自动调用结构,在整个类中执行之前执行之后使用一次。

#类级别的Fixture方法,是一个类方法 #类中所有方法之前 @classmethode def setUpClass(cls): pass #类中所有方法之后 @classmethod def tearDownClass(cls): pass

3.模块级别

每个模块(代码文件)执行前后执行的代码结构。

#模块级别的需要写在类的外边直接定义函数即可 #代码文件之前 def setUpModule(): pass #代码文件之后 def tearDownModule(): pass

案例:

  • 1.打开浏览器(整个测试过程中就打开一次浏览器)——>类级别
  • 2.输入网址(每个测试方法都要一次)——>方法级别
  • 3.输入用户名、密码和验证码点击登录(不同的测试数据)——>测试方法
  • 4.关闭当前页面(每个测试方法都需要一次) ——>方法级别
  • 5.关闭浏览器(整个测试过程中就关闭一次浏览器)——>类级别

import unittest def login(username,password): if username == 'admin' and password == '123456': return '登录成功' else: return '登录失败' class TestLogin(unittest.TestCase): def setUp(self) -> None: print('输入网址') def tearDown(self) -> None: print('关闭当前页面') @classmethod def setUpClass(cls) -> None: print('1.打开浏览器') @classmethod def tearDownClass(cls) -> None: print('5.关闭浏览器') def test_username_password_ok(self): self.assertEqual(login('admin','123456') ,'登录成功') if login('admin','123456') == '登录成功': print('pass') else: print('fail') def test_username_error(self): self.assertEqual(login('root', '123456'), '登录失败') self.assertIn('失败',login('root', '123456')) if login('root', '123456') == '登录失败': print('pass') else: print('fail')

六、断言

让程序代替人为判读测试程序执行结果是否符合预期结果的过程

优点

  • 1.提高测试效率
  • 2.实现自动化测试(让脚本在无人值守的状态下运行)

结果

  • true,用例通过
  • false,代码抛出异常,用例不通过

常用的UnitTest断言方法

 

self.assertEqual(预期结果,实际结果)#判断预期结果是实际结果是否相等。
1.如果相等,用例通过
2.如果不等,用例不通过,抛出异常

self.assertIn(预期结果,实际结果)#判断预期结果是否包含在实际结果中
1.包含,用例通过
2.不包含,用例不通过,抛出异常

注意:在unittest中使用断言,都需要通过self.断言方法 来调用!

def test_username_password_ok(self): self.assertEqual(login('admin','123456') ,'登录成功') if login('admin','123456') == '登录成功': print('pass') else: print('fail') def test_username_error(self): self.assertEqual(login('root', '123456'), '登录失败') self.assertIn('失败',login('root', '123456')) if login('root', '123456') == '登录失败': print('pass') else: print('fail')

七、参数化

在测试方法中,使用变量来替代具体的测试数据,然后使用传参的方法将测试数据传递给方法的变量。

好处:相似的代码不需要多次书写

工作中场景

  • 1、测试数据一般放在json文件中
  • 2、使用代码读取json文件,提取我们想要的数据——>[( ),( )]或[ [ ],[ ] ]

安装插件

  • unittest框架本身是不支持参数化,想要使用参数化,需要安装插件来完成。

  • 联网安装

    pip install parameterized
  • 验证

    pip list #查看到 parameterized from parameterized import pa...
    

步骤

  • 1.导包:unittest/pa...
  • 2.定义测试类
  • 3.书写测试方法(用到的测试数据使用变量代替)
  • 4.组织测试数据并传参(使用装饰器@parameterized.expand(data))

# 1.导包 # unittest/pa... import unittest from parameterized import parameterized from fixture import login import json #组织测试数据[(),(),()]or[[],[],[]] def build_data(): data = [] with open('data.json',encoding='utf-8') as f: result=json.load(f)#[{},{},{}] for i in result: data.append((i['username'],i['password'],i['expect'])) return data # data =[ # ('admin','123456','登录成功'), # ('admin','123','登录失败'), # ('root','123456','登录失败') # ] # 2.定义测试类 class TestLogin(unittest.TestCase): # 3. 书写测试方法(用到的测试数据使用变量代替) @parameterized.expand(build_data())# 4.组织测试数据并传参(装饰器 @) def test_login(self,username,password,expect): self.assertEqual(expect,login(username,password))

八、跳过

对于一些未完成的或者不满足测试条件测试函数和测试类,不想执行,可以使用跳过(使用装饰器完成)代码书写在TestCase里面

#直接将测试函数标记成跳过 @unittest.skip('跳过原因') #根据条件判断测试函数是否跳过,判断条件成立,跳过 @unittest.skipIf(判断条件,'跳过原因')

示例

import unittest version = 30 class TestDemo(unittest.TestCase): @unittest.skip('没什么原因,就是想跳过') def test_1(self): print("测试方法 1") @unittest.skipIf(version >=30,'如果版本号大于等于30就跳过') def test_2(self): print("测试方法 2") def test_3(self): print("测试方法 3")

九、测试报告

  • 自带的测试报告:只有单独运行TestCase的代码,才会生成测试报告

  • 生成第三方的测试报告HTMLTestRunner):
  1. 获取第三方的 测试运行类模块,将其放在代码的目录中

  2. 导包unittest

  3. 使用 套件对象,加载对象 去添加用例方法

  4. 实例化第三方的运行对象 并运行 套件对象

  1. HTMLTestRunner(参数)
    #stream=sys.stdout,必填,测试报告的文件对象(open),注意,是二进制文件需要用wb打开
    #verbosity=1,可选,报告的详细程度,默认1简略,2详细
    #title=none,可选,测试报告的标题
    #description=none,可选,描述信息,python的版本,pycharm版本
    

示例

# 1.获取第三方的 测试运行类模块,将其放在代码的目录中 from HTMLTestRunner import HTMLTestRunner # 2. 导包unittest import unittest # 3.使用 套件对象,加载对象 去添加用例方法 suite = unittest.defaultTestLoader.discover('.','para*.py')#加载对象 # 4.实例化第三方的运行对象 并运行 套件对象 file= "E:\test\Unittest\report1.html" with open(file,'wb') as f: runner = HTMLTestRunner(f,2,'测试报告','python 3.8') runner.run(suite)

查看测试报告

 

流程总结

1、组织用例文件(TestCase里边)书写参数化,书写断言,书写Fixture,书写 跳过如果是单个测试文件,直接运行,得到测试报告如果有多个测试文件,需要组织运行生成测试报告

2、使用 套件对象(TextSuite)组装,或者使用加载对象(TextLoader)组装

3、运行对象(TestRunner) 运行

1.运行对象 = 第三方的运行类(文件对象:使用wb方式打开) 2.运行对象.run(套件对象)

学习安排上

作为一位过来人也是希望大家少走一些弯路,在这里我给大家分享一些软件自动化测试的学习资源,希望能给你前进的路上带来帮助。【无套路免费白嫖】

视频文档获取方式:

这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片即可自行领取。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值