Unittest

1.1 UnitTest 框架

1.1.1 基础
  • 框架
1.框架英文单词framework
2.为解决一类事情的功能集和
> 按照框架的规定去书写代码
  • UnitTest 框架
UnitTest是python中自带的一个单元测试框架,用于单元测试,框架不需要额外安装.
UnitTest作用是:用自动化脚本(用例代码)执行框架,使用UnitTest框架来管理运行多个测试用例
  • 使用原因
1> 能够组织多个用例去执行
2> 提供丰富的方法(程序代码代替人工自动的判断预期结果与世界结果是否相符)
3> 生成测试报告
  • 核心要素(组成)
1> TestCase(最核心模块)
   TestCase(测试用例)是一个代码文件,里面书写真正的用例代码
   是unittest的组成部分,不是手工和自动化中的测试用例
2> TestSuite(测试套件)
   用于管理(组装)多个TestCase(测试用例)
3> TestRunner(测试执行)
   用于执行TestSuite(测试套件)
4> TestLoader(测试加载)
   用于对TestSuite(测试套件)功能的补充
5> Fixture(测试夹具)----类似于前置条件
   书写在TestCase(测试用例)代码中,是一个代码结构,每个方法执行前后都会执行的内容
eg:登录的测试用例(每个用例中重复的代码可以写在Fixture代码结构中,只用写一遍,每次执行用例时都会执行Fixture中的代码,类似于前置条件)
   1.打开浏览器2.输入网址
1.1.2 TestCase等测试用例的书写
代码文件依据标识符规则写(将代码的作用在文件开头使用注释说明)
步骤:
	1> 导包(unittest)
	2> 自定义测试类
	3> 在测试类中书写测试方法
	4> 执行用例

!!!!注: 运行相关问题:(耗时三天我服了啊)
运行问题参考文档: “Python: Configure Tests“ not found解决方案
注:这个错误改了n遍,放弃!!
参考文档: ERROR conda.cli.main_run:execute(125)
心死之人哪里还能改错

TestSuite & TestRunner

TestSuite(测试套件):管理打包组装TestCase(测试用例)文件的
TestRunner(测试执行):执行TestSuite(套件)
# 步骤----先多创建几个TestCase测试文件
1> 导包
2> 实例化(创建对象)套件对象
3> 使用套件对象添加用例方法
4> 实例化运行对象
5> 使用运行对象去执行套件对象
## TestSuite & TestRunner的使用
# 1> 导包
import unittest
from test_01 import TestDemo22
from test_unittest import TestDemo11

# 2> 实例化(创建对象)套件对象
suite=unittest.TestSuite()

# 3> 使用套件对象添加用例方法,使用方法一:套件对象.addTest(测试类名('方法名'))
suite.addTest(TestDemo22('test1'))
suite.addTest(TestDemo22('test2'))
suite.addTest(TestDemo11('test11'))
suite.addTest(TestDemo11('test22'))

# 3> 使用套件对象添加用例方法,使用方法二: 将一个测试类中的所有方法进行添加
# 套件对象.addTest(unittest.makeSuite(测试类名))
suite.addTest(unittest.makeSuite(TestDemo11))
suite.addTest(unittest.makeSuite(TestDemo22))

# 4> 实例化运行对象
runner =unittest.TextTestRunner()	# 固定写法

# 5> 使用运行对象去执行套件对象,运行对象.run(套件对象)
runner.run(suite)
# 示例 在tools模块中定义add函数,对两个数字进行求和计算
#     书写TestCase代码对于add()进行测试 
def add(a,b):
    return a+b

def func():
    print('我是tools 模块中的func函数')

num1=add(1,2)
num2=add(10,20)
num3=add(2,3)
import unittest
from tools import add

class TestAdd(unittest.TestCase):
    def test_method1(self):
        # 1 2 3
        if add(1,2)==3:
            print('测试通过')
        else:
            print('测试不通过')

    def test_method2(self):
        if add(10,20)==30:
            print('测试通过')
        else:
            print('测试不通过')

    def test_method3(self):
        if add(2,3)==5:
            print('测试通过')
        else:
            print('测试不通过')
# 套件和指定代码
import unittest
from test_demo import TestAdd

# 2> 实例化套件对象
suite=unittest.TestSuite()

# 添加测试方法
suite.addTest(unittest.makeSuite(TestAdd))

# 实例化执行对象
runner=unittest.TextTestRunner()
runner.run(suite)

TestLoader及Fixture等

是对TestSuite功能的补充,用于组装测试用例
步骤:比如TestCase的代码文件有很多(10 20,30)
1> 导包
2> 实例化测试加载对象并添加用例		--->得到suite对象
3> 实例化运行对象
4> 运行对象执行套件对象
"""textloader使用"""
import unittest

# 2.实例化加载对象---unittest.TestLoader().discover('用例所在的路径','用例代码文件名')
# 用例所在路径建议使用相对路径,用例的代码文件名可以使用*(rf)通配符
# 没discover是加载对象,有discover是suite对象
suite=unittest.TestLoader().discover('./testloader','test_*.py') 

# 3.实例化运行对象
runner=unittest.TextTestRunner()
# 4.执行
runner.run(suite)
# 或写成34合并:unittest.TextTestRunner().run(suite)
import unittest
# 1.使用默认的加载对象并加载用例
suite=unittest.defaultTestLoader.discover('testloader','test_*.py')
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.关闭浏览器(整个测试过程只关闭一次服务器)    类级别
import unittest
class TestLogin(unittest.TestCase):
    def setUp(self):
        # 每个方法执行之前先调用
        print("输入网址....")

    def tearDown(self)->None:
        # 每个测试方法执行之后都会调用的方法
        print('关闭当前页面...')

    @classmethod
    def setUpClass(cls)->None:
        print('-----1.打开浏览器')
    
    @classmethod
    def tearDownClass(cls):
        print('-----5.关闭浏览器')

    def test11(self):
        print("输入正确的用户名密码验证码,点击登录1")
    
    def test22(self):
        print("输入错误的用户名密码验证码,点击登录2")

断言

概念: 程序代替人为判断测试程序执行结果是否符合预期,成功为true,失败为false则抛出异常
在unittest中使用断言,需要通过self.断言方法 来试验
  • assertEqual
self.assertEqual(预期结果,实际结果)		# 判断预期结果与实际结果是否相等
如果相等,通过,不等则不通过抛出异常
  • assertIn
self.assertIn(预期结果,实际结果)		    # 判断预期结果是否包含在实际结果中
包含用例通过,不包含用例不通过抛出异常

assertIn('admin','admin')			# 包含
assertIn('admin','adminnnnn')		# 包含
import unittest

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

# 错误的用户名:root,123456,登陆失败  
    def test_username_error(self):
        self.assertEqual('登录失败',login('root','123456'))

# 错误的密码:admin,123123,登录失败
    def test_password_error(self):
        self.assertEqual('登录失败',login('root','123123'))
     
# 错误的用户名和密码:aaa,123123,登陆失败
    def test_password_uername_error(self):
    	# 注:两种写法!!!
        self.assertEqual('登录失败',login('root','123123'))
        self.assertIn('失败',login('root','123123'))

参数化

参数化:在测试方法中,使用变量来代替具体的测试数据,通过传参将测试数据传给方法的变量,减少代码重复
工作场景:测试数据一般在json中,使用代码提取数据--->[(), ()]or[[],[]]

安装插件

unittest框架本身不支持参数化,安装unittest扩展插件parameterzed实现参数化
pip install parameterized
步骤:
1> 导包 unittest /pa
2> 定义测试类
3> 书写测试方法(用到的测试数据使用变量代替)
4> 组织测试数据并传参
import unittest
from parameterized import parameterized # type: ignore
from tools import login

# 组织测试数据
data=[
    ('admin','123456','登录成功'),
    ('root','123456','登陆失败'),
    ('admin','123123','登陆失败')
]

class TestLogin(unittest.TestCase):
    # 3.书写测试方法(用到测试数据使用变量代替)
    @parameterized.expand(data)
    def test_login(self,username,password,expect):
        self.assertEqual(expect,login(username,password))

# 4.组织测试数据并传参

跳过

对于不满足条件测试条件的函数和类可以执行跳过,使用装饰器,代码书写在TestCase文件中
# 直接将测试函数标记为跳过
@unittest.skip('跳过原因')
# 根据条件判断测试函数是否跳过
@unittest.skipIf(判断条件,'跳过原因')
import unittest

# version = 30
version = 29

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')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值