💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] ## **一、UnitTest框架** ~~~ 1.1 为什么使用UnitTest框架? 1. 批量执行用例 2.提供丰富的断言知识 3.可以生成报告 ​ 1.2 什么是UnitTest框架 python自带一种单元测试框架 ​ 1.3 核心要素 1). TestCase (测试用例) 2). TestSuite (测试套件) 3). TextTestRunner (以文本的形式运行测试用例) 4). TestLoader (批量执行测试用例--搜索指定文件夹内指定字母开头的模块)【推荐】 5). Fixture (固定装置(两个固定的函数,一个初始化时使用,一个结束时使用)) ~~~ **TestCase:** ~~~ 说明:测试用例 ​ 步骤: 1.导包 import unittest 2.新建测试类并继承 unittest.TestCase 3.测试方法必须以 test 字母开头 ​ 运行: 1.运行测试类所有的测试方法,光标定位到类当前行右键运行 2.运行单个测试方法:光标放到测试方法当前行。 ~~~ <details> <summary>testcase01.py</summary> ``` ''' 目标:unittest框架--TestCase使用 步骤: 1.包improt unittest 2.新建类并继承 unittest.TestCase 3.测试方法必须以test字母开头 案例: 编写求和测试函数 ''' import unittest def add(x, y): return x + y # 定义测试类 并 继承 class Test01(unittest.TestCase): # 定义测试方法 注意:以test字母开头 def test_add(self): result = add(1, 1) print("结果为:", result) def test_add2(self): result = add(1, 3) print("结果为:", result) ``` </details> <br /> <details> <summary>test02.py</summary> ``` # test02.py class Test01: def test001(self): print("test001被执行") if __name__ == '__main__': print("__name__的值:", __name__) ''' __name__: 为python中内置变量 值: 1.如果当前运行的模块为当前模块,那么__name__的值为: __main__ 2.如果当前运行的模块不是主模块,那么__name__的值为: 模块名称 ''' 运行结果: ---------------------------------------- __name__的值: __main__ ``` </details> <br /> <br /> **TestSuite:** ~~~ 说明:测试套件 ​ 步骤: 1.导包 2.获取测试套件对象 suite = unittest.TestSuite() 3.调用addrest()方法添加测试用例 ​ 添加测试用例方法: 1. suite.addTest(类名("方法名称"))   # 添加指定类中指定的测试方法 2. suite.addTest(unittest.makeSuite(类名)) #添加指定类中所有已test开头的方法 ~~~ **TextTestRunner:** ``` 说明:执行测试套件方法 步骤: 1.导包 2.实例化后去执行套件对象runner = unittest.TextTestRunner() 3.调用run方法去执行runner.run(suite) ``` <details> <summary>run_main.py</summary> ``` ''' 目标:unittest框架-TestSuite使用 操作: 1.导包 2.实例化获取 TestSuite对象 3.词用addTest方法添加用例到指定套件中 ''' import unittest from day05.testcase01 import Test01 from day05.test02 import Test02 # 实例化 suite suite = unittest.TestSuite() # 调用添加方法 # 写法1 类名("方法名")注意:方法名称使用双引号 # suite.addTest(Test01("test_add")) # suite.addTest(Test01("test_add2")) # 扩展 添加测试类中所有test开头的方法 suite.addTest(unittest.makeSuite(Test02)) # 执行测试套件 runner = unittest.TextTestRunner() runner.run(suite) ``` </details> <br /> <details> <summary>test02.py</summary> ``` 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__的值为:模块名称 ''' ``` </details> <br /> **TestLoader:** ~~~ 说明: 1.将符合条件的测试方法添加到测试套件中 2.搜索指定目录文件下指定字母开头的模块文件下test开始的方法,并将这些方法添加到测试套件中,最后返回测试套件 ​ 操作: 1.导包 import unittest 2.调用TestLoader() 写法1.suite = unittest.TestLoader().discover ("指定搜索的目录文件”,”指定字母开头模块文件") 写法2.suite = unittest.defaultTestLoader.discowex ("指定搜索的目录文件”,”指定字母开头模块文件”【推荐】 注意:如果使用写法1,TestLoader()必须有括号。 3.执行测试套件 ~~~ <details> <summary>run_loader.py</summary> ``` # run_loader.py ''' 目标:演示TestLoader()类的用法 作用:搜索指定月录下指定开头py文件,在Py文件中搜索test开头测试方法, 并且将这些方法添加到测试套件中,最后返回测试套件。 需求: 运行cases目录下teste1.py~teste5.py文件 操作: 1.导包unittest 2.调用TestLoader类下discaver方法 ''' 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) ``` </details> <br /> ``` TestSuite与TestLoader区别: 共同点:都是测试套件 不同点:实现方式不同 TestSuite:要么添加指定的测试类中所有test开头的方法,要么添加指定测试类中指定某个test开头的方法 TestLoader:搜索指定目录下指定字母开头的模块文件中以test字母开头的方法并将这些方法添加到测试套件中,最后返回测试套件。 ``` <br/> ## **二、fixture** ~~~ 说明:装置函数(setUp、tearDown) ​ 级别: 1).函数级别def setUp() / def tearDown() 特性:几个测试函数,执行几次。每个测试函数执行之前都会执行setup,执行之后都会执行tearDown 2).类级别def setUpClass() / def tearDownClass() 特性:测试类运行之前运行一次etupClasg类运行之后运行一次tearDownClass 注意:类方法必须使用eclaggmethod修饰 ​ 3).模块级别:def setUpModule()/def tearDownModule() 特殊:模块运行之前执行一次setUpModule,运行之后运行一次tearDownModule ​ 提示: 无论使用函数级别还是类级别,最后常用场景为: 初始化: 1.获取浏览器实例化对象 2.最大化浏览器 3.隐式等待 结束: 关闭浏览器驱动对象 ~~~ <details> <summary>test03_fixture.py</summary> ``` # test03_fixture.py ''' 目标:unittest 中的fixture用法 fixture其实就是两个函数,这个函数可以一起使用,也可以单独使用 1.初始化函数:def setUp() 2.结束函数:def tearDown() fixture级别: 1.函数级别[常用] 2.类级别[常用] 3.模块级别 ''' import unittest 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("setDown被执行") def test01(self): print('test01被执行') def test02(self): print('test02被执行') ``` </details> <br /> <br /> ## **三、断言** ~~~ 3.1 什么是断言? 让程序代替人为判断执行结果是否与预期结果相等的过程 ​ 3.2为什么要断言? 自动化脚本执行时都是无人值守,需要通过断言来判断自动化脚本的执行是否通过 注:自动化脚本不写断言,相当于没有执行测试一个效果。 ​ 3.3常用断言 1. self.assertEqual(ex1, ex2) # 判断ex1是否相等ex2 2. self.assertIn(ex1, ex2) # ex2是否包含ex1注意:所谓的包含不能跳字符 3. self.assertTure(ex) # 判断ex是否为True ~~~ <details> <summary>test04_assert.py</summary> ``` # test04_assert.py ''' 目标:unitest常用断言 1.assertTrue:如果结果为True通过,否则失败 ''' import unittest class Test02(unittest.TestCase): def test001(self): # 断言是否为True #flag = True flag = False # self.assertTrue(flag) self.assertFalse() # 判断两个字符串是否相等 self.assertEqual("明天,你好!", "昨天,你好!") self.assertEqual("明天,你好!", "明天,你好!") # 判断后面的字符串是否包含前边的字符串 self.assertIn("hello bama", "hello bama,wahaha") self.assertIn("hello wahaha", "hello bama,wahaha") ``` </details> <br /> **3.4 断言练习** ~~~ 目标: topshop登录 方法: def setup(): # 获取 driver # 打开url # 最大化浏览器 # 隐式等待 def tearDown(): # 关闭浏览器驱动 def_test_login_code_null(): # 根据业务流程编写 # 失败截图 ~~~ <details> <summary>test05_tpshop_login.py</summary> ``` # test05_tpshop_login ''' 目标:断言练习 案例: 输入:正确用户名和密码 验证码为空 断言:提示信息是否为,验证码不能为空! 要求:如果新言出错,截屏保存 ''' import time import unittest from selenium import webdriver from time import sleep class TestTpshopLogin(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome("http://localhost") self.driver.maximize_window() self.driver.implicitly_wait(30) 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("139000111") # 输入密码 driver.find_element_by_css_selector("#password").send_keys("12345") # 输入验证码 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) # 定义预期结果 except_result = "验证码不能为空!" try: # 断言 self.assertEqual(result, except_result) except AssertionError: # 截图 driver.get_screenshot_as_file("../image/error.png").format(time.strftime("%Y_%m_%d_%H_%M_%S")) # 抛异常 raise ``` </details> <br /> **3.5 扩展** ~~~ 断言两种实现方式: 方式1:使用 unittest框架中断言,详情请参考以上相关知识点。 方式2:使用 python自带断言 1. assert str1 == str2 # 判断str1 是否与str2相等 2. assert str1 in str2 # 判断str2 是否包含str1 3. assert True/1 # 判断是否为true ~~~ <details> <summary>test06_assert_extend.py</summary> ``` # test06_assert_extend.py ''' 目标断言扩展: 两种实现方式 1.使用 unittest框架中的断言 2.使用 python自带断言 ''' # 使用python自带断言 判断两个字符串是否相等 assert "hello" == "hello" # 不相等 assert "hello" == "hello1" # 第二个字符串是否包含第一个字符串 assert "h" in "hello" assert "ha" in "hello" # 判断是否为True assert True assert False assert 0 assert 1 ``` </details> <br /> <br /> ## **四、参数化** 4.1 为什么要参数化 解决冗余代码问题; 4.2 什么是参数化 说明:根据需求动态获取参数并引用的过程 4.3 参数化应用场景 场景:解决相同业务逻辑,不同测试数据问题。 4.4 应用: ~~~ 1.安装插件 通过命令: 安装: pip install parameterized 验证: pip show parameterize 通过 pycharm:File--> setting--> Project--> 工程名称 ​ 2.应用插件 1.导包 from parameterized import parameterized 2.修饰测试函数 parameterized.expand([数据]) 数据格式: 1.单个参数:类型为列表 2.多个参数:类型为列表嵌套元组 3.在测试函数中的参数设置变量引用参数值,注意:变量的数量必须和数据值的个数相同 ~~~