unittest框架
文章大致内容
- unittest框架的组成
- 断言
- 跳过(某些用列由于某些原因不想执行)
- 参数化
- 测试报告
UnitTest框架
- 什么是Unittest框架?
概念:unittest是python自带的一个单元测试框架,用他来做单元测试
unittest框架作用是自动化脚本(用例代码)执行框架(使用unittest框架来管理运行多个测试用例) - 为什么使用unittest框架?
- 能够组织多个用例去执行
- 提供丰富的断言方法(让程序代替人工自动的判断预期结果和实际结果是否相符)
- 能够生成测试报告
- UnitTest核心要素(unittest的组成部分)
- TestCase(最核心的模块)
TestCase(测试用列),注意这个测试用例是unittest框架的组成部分,不是手工和自动化中我们说的用列(Test case)
主要作用:每个TestCase(测试用例)都是一个代码,在这个代码文件中 来书写 真正的用例代码 - TestSuite
TestSuite(测试套件),用来管理组装(打包)多个TestCased的
- TestRunner
TestRunner(测试执行,测试运行) 用来执行TestSuite(测试套件)的
- TestLoader
TestLoader(测试加载),功能是对TestSuite(测试套件)功能的补充
管理组装(打包)多个TestCase(测试用例)的 - Fixture
Fixture(测试夹具),书写TestCase(测试用例)代码中,是一个代码结构,可以在每个方法执行前后都会执行的内容
比如: 测试登录,每个用中都要重复书写的代码可以写在Fixture代码结构中,只写一遍,但是每次用例方法的执行,都会执行Fixture中的代码.1.打开浏览器,2.输入网址
- TestCase(最核心的模块)
TestCase(测试用例)
- 是一个代码文件
- 文件名称必须按照标识符的规则来书写,diamante作用可以在文件开头注释出来
- 步骤:
- 导包 unittest
- 自定义测试类
- 在测试类中书写测试方法
- 执行用例
- 代码
'''
代码的目的:学习TestCase(测试用例)模块的书写方法
'''
#1.导包
import unittest
#2.自定义测试类,需要继承unittest模块中的TestCase类即ke
class TestDemo3(unittest.TestCase):# 3.书写测试方法,即用列代码,目前没有真正的用例代码,使用print代替# 书写要求,测试方法 必须以test_开头(本质是以test开头)def test_method31(self):print('测试方法3-1')def test_method32(self):print('测试方法3-2')
#4 执行用列(方法)
#4.1 将光标放在 类名的后边 运行,会执行类中的所有的测试方法
#4.2 将光标放在 方法名的后边 运行,只执行当前的方法
文件的命名不规范
- 数字开头
- 有空格
- 有中文
- 其他特殊符号
(应该是数字,字母,下划线组成,不能以数字开头)
代码运行没有结果
右键运行没有unittest For的提示,出现的问题
解决方案:
- 重新新建一个代码文件,将写好的代码复制进去
- 删除已有的运行方式
没有找到用例
测试方法中不是以test_开头的,或者单词写错了
Testsuite & TestRunner
Testsuite(测试套件):管理 打包 组装 TestCase(测试用例)文件的
TestRunner(测试执行):执行TestSuite(套件)
- 步骤
- 导包(unittest)
- 实例化(创建对象)套件对象
- 使用套件对象添加用例方法
- 实例化运行对象
- 使用运行对象去执行套件对象
- 代码
TestSuite(测试套件):是用来管理多个TestCase(测试用例)的
先创建多个TestCase(测试用列)文件
'''
代码的目的:学习TestCase(测试用例)模块的书写方法
'''
#1.导包
import unittest
#2.自定义测试类,需要继承unittest模块中的TestCase类即ke
class TestDemo(unittest.TestCase):# 3.书写测试方法,即用列代码,目前没有真正的用例代码,使用print代替# 书写要求,测试方法 必须以test_开头(本质是以test开头)def test_method01(self):print('测试方法1-1')def test_method02(self):print('测试方法1-2')
# 4 执行用列(方法)
#4.1 将光标放在 类名的后边 运行,会执行类中的所有的测试方法
#4.2 将光标放在 方法名的后边 运行,只执行当前的方法
'''
代码的目的:学习testCase(测试用列)模块的书写方法
'''
#1导包
import unittest
#2自动定义测试列
class TestDemo2(unittest.TestCase):#3书写测试方法,即用例代码def test_method11(self):print('测试方法2-1')def test_method12(self):print('测试方法2-2')# 4执行用列(方法)
#
'''
学习TestSuite和TestRunner的使用
'''
#1.导包(unittest)
import unittest
from TestDemo1 import TestDemo
from TestDemo2 import TestDemo2
# 2. 实例化(创建对象)套件对象
suite = unittest.TestSuite()
# 3. 使用套件对象添加用例方法
#方式一,套件对象.addTest(测试类名('方法名'))
#建议测试类名和方法名直接赋值,防止写错
suite.addTest(TestDemo('test_method01'))
suite.addTest(TestDemo('test_method02'))
suite.addTest(TestDemo2('test_method11'))
suite.addTest(TestDemo2('test_method12'))
# 4实例化运行对象
runner = unittest.TextTestRunner()
#5使用运行对象
#运行对象.run(套件对象)
runner.run(suite)
'''
学习TestSuite和TestRunner的使用
'''
#1.导包(unittest)
import unittest
from TestDemo1 import TestDemo
from TestDemo2 import TestDemo2
# 2. 实例化(创建对象)套件对象
suite = unittest.TestSuite()
# 3. 使用套件对象添加用例方法
#方式二,将一个测试类中的所有方法进行添加
#套件对象.addTest(unittest.makeSuite(测试类名))
# 缺点:makeSuite() 不会提示
suite.addTest(unittest.makeSuite(TestDemo))
suite.addTest(unittest.makeSuite(TestDemo2))
# 4实例化运行对象
runner = unittest.TextTestRunner()
#5使用运行对象
#运行对象.run(套件对象)
runner.run(suite)
Unittest组成
TestLoader(测试加载)
TestLoader(测试加载),作用和TestSuite的作用是一样的,对Testsuite功能的补充,用来组装测试用列的
如下:如果TestCase的代码文件有很多(10,20,30)
使用步骤:
- 导包
- 实例化测试加载对象并添加用例 ----> 得到的是suite对象
- 实例化,运行对象
- 运行对象执行套件对象
#1.导包
import unittest
#2.使用默认的加载对象并加载用例
suite = unittest.defaultTestLoader.discover('case','test*.py')#3.实例化运行对象并运行
unittest.TextTestRunner().run(suite)
Fixture(测试夹具)
fixture(测试夹具)是一种代码结构,在某种特定情况下会自动执行
import unittest
class TestLogin(unittest.TestCase):def setUp(self):'''每个测试方法执行前都会先调用这个方法'''print('输入网址')def tearDown(self):'''每个测试方法执行之后都会调用这个方法'''print('关闭页面')@classmethoddef setUpClass(cls) -> None:'''类,执行前调用这个方法'''print('打开浏览器')@classmethoddef tearDownClass(cls) -> None:'''类,执行后调用这个方法'''print('关闭浏览器')def test_login(self):print('输入正确的用户名和密码')def test_login2(self):print("输入错误的用户名和密码")
断言
让程序代替人工自动的判断预期结果和实际结果是否相符
断言的结果有两种:
True,用列通过
False,代码抛出异常,用列不通过
在unittest中使用断言,都需要通过self.断言方法 来试验
-
assertEqual
self.assertEqual(预期结果,实际结果)
相等通过,不相等不通过,抛出异常 -
assertIn
self.assertIn(预期结果,实际结果)
包含,通过,不包含不通过抛出异常
import unittestfrom Day_One.tools import loginclass TestLogin02(unittest.TestCase):def test_username_password_ok(self):"""正确的用户名和密码: admin, 123456, 登录成功"""self.assertEqual('登录成功',login('admin', '123456'))def test_username_error(self):"""错误的用户名: root, 123456, 登录失败"""self.assertEqual('登录失败',login('root', '123456'))def test_password_error(self):"""错误的密码: admin, 123123, 登录失败"""self.assertEqual('登录失败',login('admin', '123123'))def test_username_password_error(self):"""错误的用户名和错误的密码: aaa, 123123, 登录失败"""self.assertIn('失败', login('aaa', '123123'))
参数化
参数化,在测试方法中,使用变量来替代具体的测试数据,然后使用传参的方法将测试数据传递给方法的变量
好处:相似代码不需要多次书写
工作中的场景
- 测试数据一般放在json文件中
- 使用代码读取json文件,提取需要的数据[(),()]or[[],[]]
安装插件
unittes框架不支持,参数化,想要使用参数化,需要安装插件来完成
联网安装(cmd窗口安装)
pip install parameterizedpip 是python中包的管理工具
#导包 unittest/pa
import unittest
from parameterized import parameterized
#组织测试数据[(),(),()] or [[],[],[]]
from Day_One.tools import logindata=[('admin','123456','登录成功'),('root','12344','登录失败'),('admin','123123','登录失败')]
#定义测试类
class TestLogin23(unittest.TestCase):#书写测试方法(用到的测试数据使用变量代替@parameterized.expand(data)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')
第三方测试报告HTMLTestRunner
#1 获取第三方的测试运行类模块,将其放在代码的目录中
#2 导包unittest
import unittest
from HTMLTestRunner import HTMLTestRunner# 使用套件对象,加载对象,去添加用例方法
suite = unittest.defaultTestLoader.discover('.','Test_parameterized.py')
# 实例化第三方运行对象,并运行 套件对象
# HTMLTestRunner()参数如下
# stream=sys.stdout,文件对象 open
# verbosity=1, 报告详细程度 1简单 2详细
# title=None, 报告文件标题
# description=None 描述信息file = 'reort1.html'
with open(file,mode='wb') as f:runner = HTMLTestRunner(f,2,'ceshi','python3.6')#运行对象执行套件runner.run(suite)