5. UnitTest 框架 . fixture . 断言

target

  1. UnitTest 框架
  2. fixture
  3. 断言
  4. HTML测试报告

一、UnitTest 框架

单元测试 - 白盒测试
就是对程序源代码进行测试

framework 框架:为解决一类事情的功能集合

为什么使用UnitTest框架

  1. 能够组织多个用例去执行
  2. 提供丰富的断言方法
  3. 能够生成测试报告

UnitTest核心要素

1. TestCase 测试用例
2. TestSuite 测试套件
3. TestRunner  测试执行  (TextTestRunner  以文本的形式运行测试用例)
4. TestLoader  批量执行测试用例,搜索指定文件夹里的模块,方法,类等等,推荐使用)
5. Fixture    固定装置:两个固定的函数,一个初始化的时候使用,一个结束的时候使用

测试用例

使用;

  1. 导包: import unittest
  2. 定义测试类 :新建测试类必须继承 unittest.TestCase
  3. 定义测试方法:测试方法名称命名必须以 test 开头

执行测试用例

方式一:
使用pycharm在代码上点击鼠标右键,选择使用UnitTest运行
方式二:
调用 unittest.main() 来运行
# TestCase 使用
# case:求和测试函数

import unittest

# 求和函数
def add(x,y):
    return x+y
# 定义测试类 并 继承  大驼峰是类
class Test01(unittest.TestCase):
    # 定义测试方法: 注意:以test 开头
    def test_add(self):
        # 调用 要测试的函数
        result = add(1,1)
        print("结果为:",result)
if __name__ == '__main__':
    unittest.main()


class Test01:
    def test001(self)
        print("test001被执行"):
if __name__ == '__main__':
    print("__name__ 的值为:",__name__)

""""
    __name__: 为python中内置变量
    值:
        1.如果当前运行的模块是主模块,那么  __name__ 的值为:__main__
        2.如果当前运行的模块不是主模块,那么  __name__ 的值为:模块名称
"""

TestCase:
说明:测试用例
步骤:
1. 导包 import unittest
2. 新建测试类并继承 unittest.TestCase
3. 测试方法必须以test字母开头
运行:
1. 运行测试类所有的测试方法,光标定位到类当前行右键运行
2. 运行单个测试方法:光标放到测试方法当前行。

测试套件 + 执行 —— testSuit TextTestRunner

TestSuite:
说明:测试套件
步骤:
1. 导包
2. 获取测试套件对象 suite = unittest.TestSuite()
3. 调用addTest()方法 添加测试用例

	添加测试用例方法: 
		1. suite.addTest(类名("方法名称"))      # 添加指定类中指定的测试方法
		2. suite.addTest(unittest.makeSuite(类名))     # 添加指定类中所有已test开头的方法

TextTestRunner:
说明:执行测试套件方法
步骤:
1. 导包
2. 实例化后去执行套件对象 runner = unittest.TextTestRunner()
3. 调用run方法去执行 runner.run(suite)

import unittest


class Test02(unittest.TestCase):
    def test001(self):
        print("test001被执行")

    def test002(self):
        print("test002被执行")

    def test003(self):
        print("test003被执行")

    def test004(self):
        print("test004被执行")

if __name__ == '__main__':
    print("__name__的值:", __name__)


"""
    __name__: 为python中内置变量
        值:
            1. 如果当前运行的模块为当前模块,那么__name__的值为:__main__
            2. 如果当前运行的模块不是主模块,那么__name__的值为:模块名称
"""

TestLoader

核心代码就这三句

import unittest
suite = unittest.defaultTestLoader.discover("指定搜索的目录文件","指定字母开头模块文件") 
unittest.TextTestRunner().run(suite)
说明:
	1.  将符合条件的测试方法添加到测试套件中
	2.  搜索指定目录文件下指定字母开头的模块文件下test开始的方法,并将这些方法添加到测试套件中,最后返回测试套件
操作: 
	1. 导包
			import unittest
	2. 调用TestLoader()
			写法1. suite = unittest.TestLoader().discover("指定搜索的目录文件","指定字母开头模块文件")
			写法2. suite = unittest.defaultTestLoader.discover("指定搜索的目录文件","指定字母开头模块文件") 【推荐】
			注意:如果使用写法1,TestLoader()必须有括号。
	3. 执行测试套件
			unittest.TextTestRunner().run(suite)   
"""
    目标:演示TestLoader()类的用法
    作用:搜索指定目录下指定开头的py文件,在Py文件中搜索test开头测试方法,并且将这些方法添加到测试套件中,最后返回测试套件
    需求:
        运行 cases目录下test01.py~test05.py文件
    操作:
        1. 导包 unittest
        2. 调用TestLoader类下discaver方法
        3. 执行测试用例
"""
# 导包
import unittest
# 调用方法
# suite = unittest.TestLoader().discover("../cases")

# 扩展 指定 tpshop开头的模块
# suite = unittest.TestLoader().discover("../cases", pattern="tpshop*.py")

# 扩展 使用 推荐使用
suite = unittest.defaultTestLoader.discover("../cases")

# 执行 套件 方法 TextTestRunner
unittest.TextTestRunner().run(suite)


TestSuite与TestLoader区别:

共同点:都是测试套件
不同点:实现方式不同
	TestSuite: 要么添加指定的测试类中所有test开头的方法,要么添加指定测试类中指定某个test开头的方法
	TestLoader: 搜索指定目录下指定字母开头的模块文件中以test字母开头的方法并将这些方法添加到测试套件中,最后返回测试套件

二、fixture —— (setUp、tearDown) 很重要

就是两个函数,初始化函数,结束函数

说明:装置函数(setUp、tearDown)
级别:
	1). 函数级别 def setUp() / def tearDown()
		特性:几个测试函数,执行几次。每个测试函数执行之前都会执行 setUp,执行之后都会执行tearDwon
	2). 类级别 def setUpClass() / def tearDownClass()
		特性:测试类运行之前运行一次setUpClass 类运行之后运行一次tearDownClass
		注意:类方法必须使用 @classmethod修饰
	3). 模块级别:def setUpModule() / def tearDownModule()
		特殊:模块运行之前执行一次setUpModule ,运行之后运行一次tearDownModule
			
提示:
	无论使用函数级别还是类级别,最后常用场景为:
		初始化:
			1. 获取浏览器实例化对象
			2. 最大化浏览器
			3. 隐式等待
		结束:
			关闭浏览器驱动对象

def setUp()是TestCase 的子类,TestCase是父类,要继承class Test04(unittest.TestCase):
使用TestCase就要导包 import unittest

"""
    目标:unittest 中的fixture用法
    fixture其实就是两个函数,这个函数可以一起使用,也可以单独使用
        1. 初始化函数:def setUp()
        2. 结束函数: def tearDown()

    fixture级别:
        1. 函数级别 [常用]:有几个测试函数,setup 就运行几次。 好处:每次初始化和结束都不会出错,方便。   缺点:启动慢,每次都要调用setup
        2. 类级别 [更常用]:在测试类运行之前,首先会执行setup 里面的方法,然后在类执行之后后执行teardown 里面的方法
        3. 模块级别:模块运行之前执行一次setUpModule ,运行之后运行一次tearDownModule
"""
import unittest

def setUpModule():
    print("setUpModule")

def tearDownModule():
    print("tearDownModule")


class Test03(unittest.TestCase):  # 这是继承

    @classmethod
    def setUpClass(cls):
        print("setUpClass被执行")

    @classmethod
    def tearDownClass(cls):
        print("tearDownClass被执行")

    def setUp(self):
        print("setUp被执行")

    def tearDown(self):
        print("tearDown被执行")

    def test01(self):
        print("test01被执行")

    def test02(self):
        print("test02被执行")


class Test04(unittest.TestCase):

	# 类方法 ,用的多
    @classmethod   # 修饰类方法,类方法必须修饰

    def setUpClass(cls):
        print("setUpClass被执行")

    @classmethod
    def tearDownClass(cls):
        print("tearDownClass被执行")

    def setUp(self):
        print("setUp被执行")

    def tearDown(self):
        print("tearDown被执行")

    def test01(self):
        print("test01被执行")

    def test02(self):
        print("test02被执行")

三、断言 —— assert 就是测试

1 什么是断言?
	让程序代替人为判断执行结果是否与预期结果相等的过程
2 为什么要断言?
	自动化脚本执行时都是无人值守,需要通过断言来判断自动化脚本的执行是否通过
	注:自动化脚本不写断言,相当于没有执行测试一个效果。
3 常用断言
	1. self.assertEqual(ex1, ex2)  #判断ex1 是否相等ex2
	2. self.assertIn(ex1 ,ex2) # ex2是否包含ex1 注意:所谓的包含不能跳字符
	3. self.assertTrue(ex) # 判断ex是否为True
	
4 断言练习
	目标:tpshop登录
	方法:
		def setUp():
			# 获取driver
			# 打开url
			# 最大化浏览器
			# 隐式等待
		def tearDown():
			# 关闭浏览器驱动
		
		def test_login_code_null():
			# 根据业务流程编写
			# ...
			# 失败截图
	
5 扩展
	断言两种实现方式
		方式1:使用unittest框架中断言,详情请参考以上相关知识点。
		方式2:使用python自带断言
			1. assert str1 == str2 # 判断str1 是否与str2相等
			2. assert str1 in str2 # 判断str2 是否包含str1
			3. assert True/1 # 判断是否为True

3 常用断言

self.assertTrue(ex)          # 判断ex是否为True
self.assertEqual(ex1, ex2)   #判断ex1 是否相等ex2
self.assertIn(ex1 ,ex2       # ex2是否包含ex1   注意:所谓的包含不能跳字符
import unittest
"""
    目标:unittest常用断言
        1. assertTrue : 如果结果为True通过,否则失败
        
"""

class Test02(unittest.TestCase):  #继承case
    def test001(self):  #  子类调用父类方法用 self
        # 断言是否为True
        # flag = True
        # flag = False
        # self.assertTrue(flag)
        # self.assertFalse(flag)

        # 判断两个字符串是否相等
        # self.assertEqual("你好,斑马!", "你好,奥码!")
        # self.assertEqual("你好,斑马!", "你好,斑马!")

        # 判断后边的字符串是否包含前边的字符串
        # self.assertIn("hello bama", "hello bama,wahaha")
        # self.assertIn("hello wahaha", "hello bama,wahaha")

        # 判断是否为None
        flag = None
        # self.assertIsNone(flag)
        self.assertIsNotNone(flag)

4 断言练习

"""
    目标:断言练习
    案例:
        输入:正确用户名和密码  验证码为空
        断言:提示信息是否为,验证码不能为空!
        要求:如果断言出错,截屏保存。
"""
# 导包
import unittest
import time
from time import sleep
from selenium import webdriver


# 定义测试类 并 继承 unittest.TestCase
class TestTphopLogin(unittest.TestCase):

    # 定义初始化方法
    def setUp(self):
        # 获取浏览器驱动对象     
        # 因为后面teardown要关闭浏览器,和此时的函数不是一个函数,意思就是跨函数了,所以需要self ,这样后面就可以访问到了,可以顺利退出
        self.driver = webdriver.Firefox()
        # 打开 url
        self.driver.get("http://localhost")
        # 最大化浏览器
        self.driver.maximize_window()
        # 隐式等待
        self.driver.implicitly_wait(30)

    # 定义teardown
    def tearDown(self):
        # 关闭浏览器驱动
        sleep(2)
        self.driver.quit()

    # 定义登录测试方法 验证码为空
    def test_login_code_null(self):
        driver = self.driver
        # 点击登录连接
        driver.find_element_by_partial_link_text("登录").click()
        # 输入用户名
        driver.find_element_by_css_selector("#username").send_keys("13800001111")
        # 输入密码
        driver.find_element_by_css_selector("#password").send_keys("123456")

        # 输入验证码
        driver.find_element_by_css_selector("#verify_code").send_keys("")

        # 点击登录
        driver.find_element_by_css_selector(".J-login-submit").click()
        # 获取登录后提示信息
        result = driver.find_element_by_css_selector(".layui-layer-content").text
        print("result:", result)
        # 定义预期结果
        # expect_result = "验证码不能为空!"
        # 测试断言错误
        expect_result = "验证码不能为空!!"
        # try 捕获异常
        try:
            # 断言
            self.assertEqual(result, expect_result)
        except AssertionError:
            # 截图
            driver.get_screenshot_as_file("../image/{}.png".format(time.strftime("%Y_%m_%d_%H_%M_%S")))
            # 抛异常
            raise

断言两种实现方式 —— unit test 和 python自带的

"""
    目标断言扩展:
        两种实现方式:
            1. 使用unittest框架中的断言
            2. 使用python自带断言
"""
# 使用python自带断言 判断两个字符串是否相等
# assert "hello" == "hello"
# 不相等
# assert "hello" == "hello1" "出错啦啦啦!!!这俩不相等"

# 第二个字符串是否包含第一个字符串
# assert "h" in "hello"
# assert "ha" in "hello"

# 判断是否为True
# assert True
# assert False
# 0 为False ; 1为True
# assert 0
# assert 1

四、参数化

4.1 为什么要参数化
	解决冗余代码问题;
4.2 什么是参数化
	说明:根据需求动态获取参数并引用的过程
4.3 参数化应用场景
	场景:解决相同业务逻辑,不同测试数据问题。
	
4.4 应用:
	1. 安装插件
		通过命令:
			安装:
				pip install parameterized
			验证:
				pip show parameterized
		通过pycharm:File-->setting-->Project 工程名称
		
	2. 应用插件
		1. 导包 from parameterized import parameterized
		2. 修饰测试函数 @parameterized.expand([数据])
			数据格式:
				1. 单个参数:类型为列表
				2. 多个参数:类型为列表嵌套元祖
				3. 在测试函数中的参数设置变量引用参数值,注意:变量的数量必须和数据值的个数相同
import unittest
from parameterized import parameterized

def add(x, y):
    return x+y

"""
    问题:
        如果有三组数据需要测试?
        [(1,1,2), (1,2,3), (0,3,3)]
"""


def get_data():
    return [(1, 2, 3), (3, 0, 3), (2, 1, 3)]


# 定义测试类 并 继承
class Test01(unittest.TestCase):
    # 定义测试方法 注意:以test字母开头
    @parameterized.expand(get_data())
    def test_add(self, a, b, expect):
        # 调用 要是的函数
        result = add(a, b)
        assert result == expect

parameterized 插件应用

import unittest
from parameterized import parameterized

"""
    目标:parameterized 插件应用
    步骤:
        1. 导包 from parameterized import parameterized
        2. 修饰测试函数 @parmeterized.expand(列表类型数据)
        3. 在测试函数中使用变量接收,传递过来的值。
        
    语法:
        1. 单个参数:值为列表
        2. 多个参数:值为列表嵌套元组 如:[(1,2,3),(2,3,4)]
"""


# 定义测试类 并 继承
class Test01(unittest.TestCase):
    # 单个参数使用方法
    # @parameterized.expand(["1", "2", "3"])
    # def test_add_one(self, num):
    #     print("num:", num)

    # 多个参数使用方法 写法1
    # @parameterized.expand([(1, 2, 3), (3, 0, 3), (2, 1, 3)])
    # def test_add_more(self, a, b, result):
    #     print("{}+{}={}:".format(a, b, result))

    # data = [(1, 2, 3), (3, 0, 3), (2, 1, 3)]
    # 写法2
    # @parameterized.expand(data)
    # def test_add_more(self, a, b, result):
    #     print("{}+{}={}:".format(a, b, result))


    # 写法 3 推荐
    def get_data(self):
        return [(1, 2, 3), (3, 0, 3), (2, 1, 3)]

    @parameterized.expand(get_data())
    def test_add_more(self, a, b, result):
        print("{}+{}={}:".format(a, b, result))

注意;
写法三在写的时候,应该先写把调用的函数写前面,不然执行不了
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
unittest是Python自带的单元测试框架,可以方便地进行单元测试。 unittest框架的基本组成部分: 1. TestCase:测试用例,是一个单元测试的最小单位。每个测试用例都是继承unittest.TestCase类的一个方法。 2. TestSuite:测试套件,是由多个测试用例组成的集合。可以用来批量执行多个测试用例。 3. TestRunner:执行器,用于执行测试用例和生成测试报告。 4. TestFixture:测试夹具,包括setUp()和tearDown()方法,用于测试前的准备和测试后的清理。 unittest框架的使用流程: 1. 导入unittest模块。 2. 编写测试用例,继承unittest.TestCase类,并实现测试方法。 3. 使用TestLoader类的loadTestsFromTestCase()方法,将测试用例加载到测试套件中。 4. 使用TestRunner类的run()方法,执行测试套件中的测试用例,并生成测试报告。 5. 在测试用例中可以使用断言方法,如assertEqual()、assertTrue()等来进行测试结果的验证。 unittest框架的优点: 1. 可以自动化执行测试用例,并生成测试报告。 2. 支持批量执行多个测试用例。 3. 支持测试用例之间的依赖关系。 4. 支持测试用例覆盖率统计。 5. 支持测试用例的并发执行。 总之,unittest是Python自带的一个功能强大的单元测试框架,可以方便地进行单元测试,并且可以自动生成测试报告,对于Python开发者来说,是一个不可或缺的工具。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值