【软件测试】python——Unittest

UnitTest 框架

笔记来自于黑马程序员python自动化测试教程,python从基础到Uinttest框架管理测试用例。

链接:[黑马程序员python自动化测试教程,python从基础到Uinttest框架管理测试用例](https://www.bilibili.com/video/BV1av411q7dT?spm_id_from=333.788.player.switch&vd_source=ecc19dcfc171f374d54c63c80b6e2a19&p=197)

定义:UnitTest 是 python 自带的一个单元测试框架,可以用来进行单元测试。

作用:自动化脚本(用例代码)执行框架(使用unittest框架莱管理运行多个测试用例的)。

好处

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

组成

  1. TestCase

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

  2. TestSuite

    TestSuite(测试套件),用来 管理 组装(打包)多个 TestCase(测试用例)的

  3. TestRunner

    TestRunner(测试执行,测试运行),用来 执行 TestSuite(测试套件)的

  4. TestLoader

    TestLoader(测试加载),功能是对 Testsuite(测试套件)功能的补充管理 组装(打包)多个 Testcase(测试用例)的

  5. Fixture

    Fixture(测试夹具),书写在 Testcase(测试用例)代码中,是一个代码结构,可以在每个方法执行前后都会执行的内容
    举例:
    登录的测试用例,每个用例中重复的代码就可以写在Fixture 代码结构中,只写一遍,但每次用例方法的执行,都会执行Fixture 中的代 码
    1.打开浏览器
    2.输入网址


一、TestCase(测试用例)

  1. 是一个代码文件,在代码文件中 来书写真正的用例代码
  2. 代码文件的名字必须按照标识符的规则来书写(可以将代码的作用在文件的开头使用注释说明)
步骤
1. 导包(unittest)
2. 自定义测试类
3. 在测试类中书写测试方法
4. 执行用例
代码
python文件:(testcase1.py)
'''
代码的目的:学习 TestCase(测试用例)模块的书写方法
'''
# 1. 导包
import unittest
	
# 2. 自定义测试类,血药继承unittest模块中的TestCase类
class TestDemo1(unittest.TestCase):
	# 3.书写测试方法,即 用例代码,目前没有真正的用例代码,使用print代替
	# 书写要求:测试方法必须以test_开头
	def test_method1(self):
		print('测试方法1-1)
	
	def test_method2(self):
		print('测试方法1-2)
python文件:(testcase2.py)
'''
代码的目的:学习 TestCase(测试用例)模块的书写方法
'''
# 1. 导包
import unittest
	
# 2. 自定义测试类,血药继承unittest模块中的TestCase类
class TestDemo2(unittest.TestCase):
	# 3.书写测试方法,即 用例代码,目前没有真正的用例代码,使用print代替
	# 书写要求:测试方法必须以test_开头
	def test_method1(self):
		print('测试方法2-1)
	
	def test_method2(self):
		print('测试方法2-2)

二、TestSuite(测试套件) & TestRunner(测试执行)

TestSuite:管理 打包 组装 TestCase 文件的
TestRunner:执行 TestSuite 套件的

步骤
1. 导包(unittest)
2. 实例化(创建对象),套件对象
3. 使用套件对象添加用例方法
4. 实例化运行对象
5. 使用运行对象去执行套件对象
代码
python文件:(suite_runner.py)
'''
学习 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(测试类名))
suite.addTest(unittest.makeSuite(TestDemo1))
suite.addTest(unittest.makeSuite(TestDemo2))
# 4. 实例化运行对象
runner = unittest.TextTestRunner()
# 5. 使用运行对象去执行套件对象
# 运行对象.run(套件对象)
runner.run(suite)

运行结果解释
在这里插入图片描述


三、TestLoader(测试加载)

TestLoader(测试加载),作用和 Testsuite 的作用是一样的,对 Testsuite 功能的补充,用来组装测试用例的
比如:
如果 Testcase 的代码文件有很多,(10,20,30)

步骤
1. 导包(unittest)
2. 实例化测试加载对象并添加用例  ---> 得到的是suite对象
4. 实例化运行对象
5. 运行对象去执行套件对象
代码实现

在一个项目中 TestCase的代码,一般放在一个单独的目录中

'''
TestLoader的使用
'''
# 1. 导包
import unittest
	
# 2. 实例化加载对象并添加用例
# unittest.TestLoader().discover('用例所在路径', pattern='用例的代码文件名.py')
# 用例所在的路径建议使用相对路径,用例的代码文件名可以使用 *(任意多个任意字符) 通配符
	
# 使用自己创建的加载对象TestLoader()
suite = unittest.TestLoader().discover('./case', pattern='test*.py')
# 使用默认加载对象defaultTestLoader
suite = unittest.defaultTestLoader.discover('./case', pattern='test*.py')
	
# # 3. 实例化运行对象
# runner = unittest.TextTestRunner()
# # 4. 执行
# runner.run(suite)
	
# 可以将3,4布变为一步
unittest.TextTestRunner().run(suite)

四、Fixture(测试夹具)

Fixture(测试夹具)是一种代码结构
在某些特定的情况下 会自动执行	
方法级别【掌握】
在每个测试方法(用例代码)执行前后都会自动调用的结构
# 方法执行之前
def setUp(self):
	# 每个测试方法执行之前都会执行
	pass
	
# 方法执行之后
def tearDown(self):
	# 每个测试方法执行之后都会执行
	pass
类级别【掌握】
在每个测试类中,所有方法执行前后,都会自动调用的结构(在整个类中,执行之前执行之后各一次)
# 类级别的Fixture方法,是一个类方法
	# 类中所有方法之前
	@classmethod
	def setUpClass(cls):
		pass
	
	# 类中所有方法之后
	@classmethod
	def tearDownClass(cls):
		pass
模块级别【了解】
模块:代码文件
在每个代码文件执行前后执行的代码结构
#模块几倍的需要写在类的外边直接定义函数即可
# 代码文件之前
def setUpModule():
	pass
	
# 代码文件之后
def tearDownModule():
	pass
方法级别和类级别的 前后的方法,不需要同时出现,根据用例代码的需要自行的选择使用

案例——登录

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

    import unittest
    
    
    class TestLogin(unittest.TestCase):
        def setUp(self):
            '''每个测试方法之前执行'''
            print('-----2. 输入网址。。。')
    
        def tearDown(self):
            '''每个测试方法之后执行'''
            print('-----4. 关闭当前页面。。。')
    
        @classmethod
        def setUpClass(cls) -> None:
            '''所有测试方法之前执行'''
            print('-----1. 打开浏览器。。。')
    
        @classmethod
        def tearDownClass(cls) -> None:
            '''所有测试方法之后执行'''
            print('-----5. 关闭浏览器。。。')
    
        def test_login1(self):
            print('-----3. 输入正确用户名密码验证码,点击登录1')
    
        def test_login2(self):
            print('-----3. 输输入错误用户名密码验证码,点击登录2')
    

    运行结果
    在这里插入图片描述


五、断言

概念:让程序代替人工自动判断预期结果与实际结果是否相符

断言的结果有两种:
> True:案例通过
> False:案例不通过
在unittest中使用断言,都需要通过self.断言方法来验证
1、常见的断言方法
序号断言方法断言描述
1assertTrue(expr, msg=None)验证expr是true,如果为false,则fail
2assertFalse(expr, msg=None)验证expr是false,如果为true,则fail
3assertEqual(expected, actual, msg=None)验证expected==actual,不等则fail【掌握】
4assertNotEqual(first, second, msg=None)验证first!=second,相等则fail
5assertIsNone(obj, msg=None)验证obj是None,不是则fail
6assertIsNotNone(obj, msg=None)验证obj不是None,是则fail
7assertIn(member, container, msg=None)验证是否member in container【掌握】
8assertNotIn(member, container, msg=None)验证是否member not in container
python文件:tools.py
def login(username, password):
    if username == 'admin' and password == '123456':
        return '登陆成功'
    else:
        return '登陆失败'
python文件:assert.py
import unittest

from tools import login

class TestLogin(unittest.TestCase):
    def test_username_password_ok(self):
        self.assertEqual('登陆成功', login('admin', '123456'))

    def test_username_error(self):
        self.assertEqual('登陆失败', login('root', '123456'))

    def test_password_error(self):
        self.assertEqual('登陆失败', login('admin', '123123'))

    def test_username_password_error(self):
        self.assertEqual('登陆失败', login('aaa', '123123'))
2、参数化
参数化:在测试方法中,使用变量来代替具体的测试数据,然后使用传参的方法将测试数据传递给方法的变量
好处:相似的代码不需要多次书写

工作场景:
 - 测试数据一般放在json文件中
 - 使用代码读取json文件,提取我们想要的数据 ---> [(), ()] or  [[], []]
安装插件
unittest 框架 本身不支持 参数化,想要使用参数化,需要安装插件来完成
- 联网安装
 pip install parameterized
  • 代码
    1. 导包 unittest/parameterized
    2. 定义测试类
    3. 书写测试方法(用到的测试数据用变量替代)
    4. 组织测试数据并传参
# 1.导包 unittest / parameterized
import unittest
from parameterized import parameterized
from tools import login

# 4.组织测试数据
# 【注】列表中有几组数据,就是几个测试用例
data = [
    ('admin', '123456', '登陆成功'),
    ('root', '123456', '登陆失败'),
    ('admin', '123123', '登陆失败'),
    ('aaa', '123123', '登陆失败')
]

# 2.定义测试类
class TestLogin(unittest.TestCase):
    # 4.参数化装饰器 @parameterized.expand(data)
    @parameterized.expand(data)
    # 3.书写测试方法(用到的测试数据用变量替代)
    def test_login(self, username, password, expect):
        self.assertEqual(expect, login(username, password))

代码结果:
在这里插入图片描述

【注】data中的数据和函数的参数列表中的参数要保持一致

若从data.json文件中导入所需要的数据,代码如下:
# python文件:data.json
[
  {
    "desc": "正确的用户名和密码",
    "username": "admin",
    "password": "123456",
    "expect": "登陆成功"
  },
  {
    "desc": "错误的用户名",
    "username": "root",
    "password": "123456",
    "expect": "登陆失败"
  },
  {
    "desc": "错误的密码",
    "username": "admin",
    "password": "123123",
    "expect": "登陆失败"
  },
  {
    "desc": "错误的用户名和密码",
    "username": "aaa",
    "password": "123123",
    "expect": "登陆失败"
  }
]
# 1.导包 unittest / parameterized
import unittest
import json
from parameterized import parameterized
from tools import login

# 4.组织测试数据
# 方式二:从文件中读取测试数据
def build_data():
    data = []
    with open('data.json', 'r', encoding='utf-8') as f:
        result = json.load(f)
        for item in result:
            data.append((item.get('username'), item.get('password'), item.get('expect')))
    return data

# 2.定义测试类
class TestLogin(unittest.TestCase):
    # 4.参数化装饰器 @parameterized.expand(data)
    @parameterized.expand(build_data())
    # 3.书写测试方法(用到的测试数据用变量替代)
    def test_login(self, username, password, expect):
        self.assertEqual(expect, login(username, password))

在这里插入图片描述


六、跳过

对于一些未完成的或者不满足测试条件的测试函数和测试类,可以跳过执行
代码书写在TestCase文件中
1、使用方法
# 直接将测试函数标记成跳过
@unittest.skip('跳过的原因')

# 根据条件判断测试函数是否跳过
@unittest.skipIf(condition, reason)
import unittest

version = 30

class TestDemo(unittest.TestCase):
    @unittest.skip('跳过测试方法1')
    def test_method1(self):
        print('TestCase1-1')

    @unittest.skipIf(version > 20, '版本大于20不用测试')
    def test_method2(self):
        print('TestCase1-2')

    def test_method3(self):
        print('TestCase1-3')

在这里插入图片描述


七 、测试报告

  • 自带的测试报告

    只有单独运行TestCase的代码,才会生成测试报告
    
  • 第三方的测试报告-HTMLTestRunner【重点】

    1. HTMLTestRunner介绍

      • HTMLTestRunner是一个第三方的类库,用来执行测试用例并生成HTML格式的测试报告
      • 网上有多种不同的实现版本,用法都类似,只是生成的HTML报告样式有差别
      • 注意:下载的文件要与Python的版本兼容(有些版本只支持Python2.x)
        本课程中介绍两种模板文件,HTMLTestRunner.py 和 HTMLTestRunner_PY3.py
        HTMLTestRunner.py:样式比较简单,不需要依赖外部JS和CSS文件
        HTMLTestRunner_PY3.py:样式比较美观,需要依赖外部JS和CSS文件
        
    2. 使用方法

      1. 获取第三方的 测试运行类模块, 将其放在代码的目录中
      2. 导包 unittest
      3. 可以使用套件对象,加载对象,去添加用例方法
      4. 实例化 第三方的运行对象 并运行套件对象
      
    3. 代码

      # 1.获取第三方的测试运行类模块, 将其放在代码的目录中
      # 2.导包unittest
      import unittest
      from HTMLTestRunner import HTMLTestRunner
      
      # 3.可以使用套件对象,加载对象,去添加用例方法
      suite = unittest.defaultTestLoader.discover('.', pattern='parameter.py')
      # 4.实例化第三方的运行对象并运行套件对象
      HTMLTestRunner(stream=open('report.html', 'wb')).run(suite)
      # stream=sys.stdout, 测试报告的文件对象(open),注意:要用 wb 打开  (必填)
      # verbosity=1, 报告的详细程度,默认 1-简略,2-详细 (选填)
      # title=None, 测试报告的标题 (选填)
      # description=None, 描述信息,python版本,pycharm版本 (选填)
      

      在这里插入图片描述
      在这里插入图片描述

  1. 组织用例文件(Testcase 里边),书写参数化,书写断言,书写 Fixture,书写 跳过,
  2. 如果单个测试测试文件,直接运行,得到测试报告,如果有多个测试文件,需要组装运行生成测试报告
  3. 使用 套件对象组装,或者使用 加载对象组装
  4. 运行对象 运行
    4.1 运行对象 = 第三方的运行类(文件对象(打开文件需要使用 wb 方式))
    4.2 运行对象.run(套件对象)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值