【Web UI自动化测试】Web UI自动化测试之框架篇(全网最全)

本文大纲截图:

  • UnitTest框架:

  • PyTest框架:

框架: 框架英文单词 framework,为解决一类事情的功能的集合。需要按照框架的规定(套路)去书写代码。

一、UnitTest框架介绍【文末分享自动化测试学习资源】

1、什么是UnitTest框架?

  • 概念:UnitTest是python自带的一个单元测试框架,用它来做单元测试

  • 自带的框架:不需要单独按照,只要安装了 python就可以用

  • 第三方框架:想要使用 需要先安装后使用(如:pytest)

  • 单元测试框架:主要用来做单元测试,一般单元测试是开发做的。对于测试来说,UnitTest 框架的作用是自动化脚本(用例代码)执行框架(使用UnitTest框架来管理 运行多个测试用例的)

2、为什么使用UnitTest框架?

  • 1)能够组织多个用例去执行

  • 2)提供丰富的断言方法(让程序代码代替人工自动的判断预期结果和实际结果是否相符)

  • 3)能够生成测试报告

  • 4)UnitTest框架对于测试来说的作用是:自动化脚本执行框架(使用 UnitTest框架来管理运行多个测试用例的脚本)

3、UnitTest框架核心组成要素

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、输入网址

4、UnitTest框架实践

4.1 TestCase(测试用例)

介绍:

  • 1)每个 TestCase(测试用例)都是一个代码文件,在这个代码文件中 来书写真正的用例代码

  • 2)代码文件的名称必须按照标识符的规则来书写(可以将代码的作用在文件的开头又多行注释说明)

注意:

  • 1)代码文件的命名规范

    • 1>代码文件名字不能以数字开头

    • 2>代码文件名字中不能有空格

    • 3>代码文件名字不能有中文

    • 4>代码文件名字由字母、数字、下划线组成,且不能以数字开头

  • 2)代码运行没结果

    • 原因:右键运行没有 unittest for xxx 的提示 而出现的问题

    • 解决方案1:重新建一个代码文件,将写好的代码复制进去

    • 解决方案2:删除已有的运行方式

  • 3)没有找到用例:测试方法中不是以 test_ 开头的,或者单词写错了

步骤:

  • 1)导包 import unittest

  • 2)自定义测试类

  • 3)在测试类中书写测试方法

  • 4)执行用例

代码:

 
  1. # 1、导包

  2. import unittest

  3. # 2、新建测试类,需要继承 unittest 模块中的 TestCase类 即可

  4. class TestDemo1(unittest.TestCase):

  5.     # 3、书写测试方法(即 用例代码,目前没有真正的用例代码,使用 print 代替)

  6.     # 注意:书写要求;测试方法 必须以 test_ 开头(本质以 test 开头)

  7.     def test_method1(self):

  8.         print("测试方法1")

  9.     def test_method2(self):

  10.         print("测试方法2")

  11. class TestDemo2(unittest.TestCase):

  12.     def test_method3(self):

  13.         print("测试方法3")

  14.     def test_method4(self):

  15.         print("测试方法4")

  16. # 4、执行用例(方法)

  17. # 4.1 将光标放在 类名后边 运行,会执行类中的 所有测试方法

  18. # 4.2 将光标放在 方法名后边 运行,只执行当前的方法

4.2 TestSuite & TestRunner(测试套件&运行)

介绍:

  • 1)TestSuite(测试套件):管理、打包、组装 多个 TestCase(测试用例) 文件

  • 2)TestRunner(测试执行):执行 TestSuite(测试套件)

步骤:

  • 1)导包 import unittest

  • 2)实例化套件对象(创建套件对象)

  • 3)使用套件对象 添加 用例方法

  • 4)实例化运行对象(创建运行对象)

  • 5)使用运行对象 去执行 套件对象

实例化套件对象并添加测试用例:

 
  1. # 导包

  2. import unittest

  3. from UnitTest_study.hm01_unittest import TestDemo

  4. # 实例化套件对象

  5. suite = unittest.TestSuite()

  6. # 方法1:单个添加测试用例(需要导包TestDemo)

  7. suite.addTest(TestDemo('test_001'))

  8. suite.addTest(TestDemo('test_002'))

  9. # 方法2:批量添加测试用例(需要导包TestDemo)

  10. suite.addTest(unittest.makeSuite(TestDemo))

实例化运行对象:

 
  1. # 导包

  2. import unittest

  3. # 实例化运行对象

  4. runner = unittest.TextTestRunner()

  5. # 运行测试套件

  6. runner.run(suite)

查看测试执行结果的方法:

  • 说明: .运行通过;F用例不通过;E用例代码有问题

代码:

方法一:使用套件对象单个(单个方法)添加用例并运行

  • 添加用例基本格式:unittest.TestSuite().addTest(类名('方法名'))

  • 特点:逐条添加测试用例

  • 运行用例基本格式:unittest.TextTestRunner().run(测试用例集)

 
  1. # 1、导包

  2. import unittest

  3. from unittest_testcase import TestDemo1, TestDemo2

  4. # 2、实例化套件对象(创建套件对象)

  5. suite = unittest.TestSuite()

  6. # 3、使用套件对象 添加 用例方法

  7. suite.addTest(TestDemo1('test_method1'))

  8. suite.addTest(TestDemo1('test_method2'))

  9. suite.addTest(TestDemo2('test_method1'))

  10. suite.addTest(TestDemo2('test_method2'))

  11. # 4、实例化运行对象(创建运行对象)

  12. runner = unittest.TextTestRunner()

  13. # 5、使用运行对象 去执行 套件对象

  14. # 格式:运行对象.run(套件对象)

  15. runner.run(suite)

方法二:使用套件对象批量(单个类)添加用例并运行

  • 添加用例基本格式:unittest.TestSuite().addTest(unittest.makeSuite(类名))

  • 特点:批量添加测试用例

  • 运行用例基本格式:unittest.TextTestRunner().run(测试用例集)

 
  1. # 1、导包

  2. import unittest

  3. from unittest_testcase import TestDemo1, TestDemo2

  4. # 2、实例化套件对象(创建套件对象)

  5. suite = unittest.TestSuite()

  6. # 3、使用套件对象 添加 用例方法

  7. suite.addTest(unittest.makeSuite(TestDemo1))

  8. suite.addTest(unittest.makeSuite(TestDemo2))

  9. # 4、实例化运行对象(创建运行对象)

  10. runner = unittest.TextTestRunner()

  11. # 5、使用运行对象 去执行 套件对象

  12. # 格式:运行对象.run(套件对象)

  13. runner.run(suite)

4.3 TestLoader(测试加载)

介绍: TestLoader(测试加载),和 TestSuite 的作用一样,是对 TestSuite 功能的补充,用来管理组装(打包)多个 TestCase。在一个项目中 TestCase(测试用例)的代码,一般放在一个单独的目录(case)中

步骤

  • 1)导包 import unittest

  • 2)实例化测试加载对象并添加用例(得到的是 suite 对象)

  • 3)实例化 运行对象

  • 4)运行对象执行套件对象

代码:

  • 基本格式一:suite = unittest.TestLoader().discover('case', 'test_*.py')

  • 基本格式二:suite = unittest.defaultTestLoader.discover('case', 'test_*.py')

 
  1. # 导包

  2. import unittest

  3. # 方法1:实例化对象并添加测试用例

  4. suite = unittest.TestLoader().discover('case', 'test_*.py')

  5. # 方法2:实例化对象并添加测试用例(说明:插件代码中有一句:defaultTestLoader = TestLoader(),所以有了方法2)

  6. suite = unittest.defaultTestLoader.discover('case', 'test_*.py')

  7. # 运行测试套件

  8. unittest.TextTestRunner().run(suite)

4.4 Fixture(测试夹具)

介绍: Fixture(测试夹具)是一个代码结构,书写在 TestCase代码中,可以在每个方法执行前后都会执行的内容(在某些特定情况下会自动执行)。Fixture是一个概述,对一个测试用例环境的初始化和销毁就是一个Fixture。

Fixture控制级别: 方法级别、类级别、模块级别

方法级别【掌握】

  • 作用:在每个测试方法(用例代码)执行前后都会自动调用的结构

  • 关键字:setUptearDown

  • 格式:

 
  1. class TestDemo(object):

  2.     """测试示例类"""

  3.     def setUp(self):

  4.         """每个方法执行之前都会执行"""

  5.         print("方法 -> 开始")

  6.     def tearDown(self):

  7.         """每个方法执行之后都会执行"""

  8.         print("方法 -> 结束")

类级别【掌握】

  • 作用:在每个测试类中所有方法执行前后 都会自动调用的结构(在整个类中 执行之前执行之后各一次)

  • 说明:类级别的fixture 是一个 类方法,要用@classmethod来装饰

  • 关键字:setUpClasstearDownClass

  • 格式:

 
  1. class TestDemo(object):

  2.     """测试示例类"""

  3.     @classmethod

  4.     def setUpClass(cls):

  5.         """每个方法执行之前都会执行"""

  6.         print("类 -> 开始")

  7.     @classmethod

  8.     def tearDownClass(cls):

  9.         """每个方法执行之后都会执行"""

  10.         print("类 -> 结束")

模块级别【了解】

  • 作用:在每个模块(代码文件)执行前后执行的代码结构

  • 关键字:setUpModuletearDownModule

  • 格式:

 
  1. # 模块级别的需要写在类的外边,直接定义函数即可

  2. def setUpModule(self):

  3.     """每个方法执行之前都会执行"""

  4.     print("模块 -> 开始")

  5. def tearDownModule(self):

  6.     """每个方法执行之后都会执行"""

  7.     print("模块 -> 结束")

  8. class TestDemo(object):

  9.     """测试示例类"""

代码:

 
  1. import unittest

  2. class TestLogin(unittest.TestCase):

  3.     def setUp(self) -> None:

  4.         """每个测试方法执行之前都会先调用的方法"""

  5.         print('输入网址...')

  6.     def tearDown(self) -> None:

  7.         """每个测试方法执行之后都会调用的方法"""

  8.         print('关闭当前页面...')

  9.     @classmethod

  10.     def setUpClass(cls) -> None:

  11.         print('1、打开浏览器...')

  12.     @classmethod

  13.     def tearDownClass(cls) -> None:

  14.         print('...5、关闭浏览器')

  15.     def test_01(self):

  16.         print('输入正确用户名密码验证码,点击登录')

  17.     def test_02(self):

  18.         print('输入错误用户名密码验证码,点击登录')

4.5 跳过

介绍:

  • 使用场景:对于一些未完成的或者不满足测试条件的测试函数和测试类,不想执行,可以使用跳过

  • 使用方法:利用装饰器来完成,代码书写在 TestCase 文件中

  • 格式一:直接将测试函数标记成跳过

    • @unittest.skip('跳过原因')

  • 格式二:根据条件判断测试函数是否跳过,判断条件成立则跳过

    • @unittest.skipIf(判断条件, '跳过原因')

代码:

 
  1. import unittest

  2. # version = 30

  3. version = 29

  4. class TestDemo(unittest.TestCase):

  5.     @unittest.skip('没有什么原因,就是不想执行')

  6.     def test_01(self):

  7.         print('测试方法01')

  8.     @unittest.skipIf(version >= 30, '版本大于 30,不用测试')

  9.     def test_02(self):

  10.         print('测试方法02')

  11.     def test_03(self):

  12.         print('测试方法03')

4.6 断言

介绍:

  • 概念:让程序代替人为判断测试程序执行结果是否符合预期结果的过程

  • 作用:

    • 1)提高写实效率

    • 2)实现自动化测试(让脚本在无人值守状态下运行)

  • 断言结果:

    • True,用例通过

    • False,代码抛出异常,用例不通过

  • 说明:

    • 1)UnitTest中提供了非常丰富的断言方法

    • 2)复杂的断言方法在自动化测试中几乎使用不到,所以掌握几个常用的即可

    • 3)在unittest中使用断言,都需要通过 self.断言方法 来使用

UnitTest断言方法:

self.assertEqual(预期结果, 实际结果)

  • 含义:判断预期结果和实际结果 是否相等

  • 返回结果:如果相等,用例通过;如果不相等,用例不通过,抛出异常。

self.assertIn(预期结果, 实际结果)

  • 含义:判断预期结果 是否包含 在实际结果中

  • 结果:包含,用例通过;不包含,用例不通过,抛出异常。

代码:

 
  1. import unittest

  2. from UnitTest_study.hm07_login import login

  3. class TestLogin(unittest.TestCase):

  4.     def test_uername_password_ok(self):

  5.         """正确用户名和密码:admin,123456,登录成功"""

  6.         self.assertEqual('登录成功', login('admin', '123456'))

4.7 参数化

介绍:

  • 好处:相似代码不需要多次书写

  • 说明:

    • 1)在测试方法中,使用 变量 来代替具体的测试数据,然后使用传参的方法将测试数据传递给方法的变量

    • 2)unittest框架本身不支持 参数化,要使用参数化需要安装插件来完成

  • 场景:

    • 1)测试数据一般放在 json 文件中

    • 2)使用代码读取 json 文件,提取出符合要求格式的数据—>>[(), ()] 或 [[], []]

  • 安装:pip install parameterized

  • 步骤:

    • 1)导包 unittest,parameterized

    • 2)定义测试类

    • 3)书写测试方法(用到的测试数据使用变量代替)

    • 4)组织测试数据并传参

  • 测试数据:

    • 1)测试数据放在 json 文件中

    • 2)新建函数读取 json文件中的 测试数据,读取的数据格式:[(), (), ()] 或 [[], [], []]

 
  1. # 组织测试数据 [(), (), ()]

  2. def build_data():

  3.     with open('data.json', encoding='utf-8') as f:

  4.         result = json.load(f)  # [{}, {}, {}]

  5.         data = []

  6.         for i in result:  # i -> {}

  7.             data.append((i.get('username'), i.get('password'), i.get('expect')))  # [(), (), ()]

  8.     return data

  • 3)利用装饰器给函数变量传递数据

  • @parameterized.expand(build_data())

代码示例1:

 
  1. import unittest

  2. from parameterized import parameterized

  3. from UnitTest_study.hm07_login import login

  4. # 组织测试数据 [(), (), ()]

  5. data = [

  6.     ('admin', '123456', '登录成功'),

  7.     ('root', '123456', '登录失败'),

  8.     ('admin', '123123', '登录失败')

  9. ]

  10. # 定义测试类

  11. class TestLogin(unittest.TestCase):

  12.     # 书写测试方法(用到的测试数据使用变量代替)

  13.     # 组织测试数据并传参(装饰器 @)

  14.     @parameterized.expand(data)

  15.     def test_login(self, username, password, expect):

  16.         """正确用户名和密码:admin,123456,登录成功"""

  17.         self.assertEqual(expect, login(username, password))

代码示例2:

测试数据文件: data.json

代码:

 
  1. import json

  2. import unittest

  3. from parameterized import parameterized

  4. from UnitTest_study.hm07_login import login

  5. # 组织测试数据 [(), (), ()]

  6. def build_data():

  7.     with open('data.json', encoding='utf-8') as f:

  8.         result = json.load(f)  # [{}, {}, {}]

  9.         data = []

  10.         for i in result:  # i -> {}

  11.             data.append((i.get('username'), i.get('password'), i.get('expect')))  # [(), (), ()]

  12.     return data

  13. # 定义测试类

  14. class TestLogin(unittest.TestCase):

  15.     # 书写测试方法(用到的测试数据使用变量代替)

  16.     # 组织测试数据并传参(装饰器 @)

  17.     @parameterized.expand(build_data())

  18.     def test_login(self, username, password, expect):

  19.         """正确用户名和密码:admin,123456,登录成功"""

  20.         self.assertEqual(expect, login(username, password))

4.8 测试报告插件

自带的测试报告:

只有单独运行 TestCase 的代码时,才会生成测试报告;位置在控制台左侧区域的右上角

第三方测试报告:

  • 1)获取第三方的 测试运行类模块,并将其放在代码目录中

  • 2)导包 unittest、HTMLTestRunner、HTMLTestReportCN

  • 3)实例化 套件对象,并使用 加载套件加载用例

  • 4)实例化 第三方的运行对象,运行 套件对象,并生成测试报告

HTMLTestRunner 插件:

  • HTMLTestRunner

 
  1. # 导包

  2. import unittest

  3. from UnitTest_study.HTMLTestRunner import HTMLTestRunner

  4. suite = unittest.defaultTestLoader.discover('.', 'hm08_parameterized1.py')

  5. file = 'report.html'

  6. with open(file, 'wb') as f:

  7.     runner = HTMLTestRunner(f, 2, '测试报告', 'python 3.7')

  8.     runner.run(suite)

  • HTMLTestRunnerCN

 
  1. # 导包

  2. import unittest

  3. from UnitTest_study.HTMLTestRunnerCN import HTMLTestReportCN

  4. suite = unittest.defaultTestLoader.discover('.', 'hm08_parameterized1.py')

  5. with open('report_CN.html', 'wb') as f:

  6.     HTMLTestReportCN(f).run(suite)

4.9 总结

1)TestCase(测试用例):组织用例文件(TestCase)里面,书写 跳过、断言、参数化,使用Fixture夹具;单个测试文件直接运行,可以得到测试报告;有多个测试文件运行,则需要组装运行生成测试报告。

2、添加测试用例 到 测试套件中

  • TestSuite(测试套件):套件对象组装测试用例

 
  1. # 导包

  2. import unittest

  3. from UnitTest_study.hm01_unittest import TestDemo

  4. # 实例化套件对象

  5. suite = unittest.TestSuite()

  6. # 方法1:单个添加测试用例(需要导包TestDemo)

  7. suite.addTest(TestDemo('test_001'))

  8. suite.addTest(TestDemo('test_002'))

  9. # 方法2:批量添加测试用例(需要导包TestDemo)

  10. suite.addTest(unittest.makeSuite(TestDemo))

  • TestLoader(测试加载):默认加载对象加载测试用例

 
  1. # 导包

  2. import unittest

  3. # 方法1:实例化对象并添加测试用例

  4. suite = unittest.TestLoader().discover('case', 'hm*.py')

  5. #  方法2:实例化对象并添加测试用例

  6. suite = unittest.defaultTestLoader.discover('case', 'hm*.py')

  7. # 运行测试套件

  8. unittest.TextTestRunner().run(suite)

3、实例化运行对象 运行 测试条件

  • TestRunner(运行对象)

 
  1. # 导包

  2. import unittest

  3. # 实例化运行对象

  4. runner = unittest.TextTestRunner()

  5. # 运行测试套件

  6. runner.run(suite)

  • 运行并生成测试报告

  • 基本格式:

    • with open('./report.html', 'wb') as f:

    • # 实例化第三方运行对象

    • 第三方运行对象 = 第三方运行类(f)

    • 第三方运行对象.run(套件对象)

  • 第三方运行类(文件对象(打开文件需要使用 wb 方式))

    • HTMLTestRunner

 
  1. import unittest

  2. from UnitTest_study.HTMLTestRunner import HTMLTestRunner

  3. suite = unittest.defaultTestLoader.discover('.', 'hm08_parameterized1.py')

  4. file = 'report.html'

  5. with open(file, 'wb') as f:

  6.     runner = HTMLTestRunner(f, 2, '测试报告', 'python 3.7')

  7.     runner.run(suite)

  • HTMLTestRunnerCN

 
  1. import unittest

  2. from UnitTest_study.HTMLTestRunnerCN import HTMLTestReportCN

  3. suite = unittest.defaultTestLoader.discover('.', 'hm08_parameterized1.py')

  4. with open('report_CN.html', 'wb') as f:

  5.     runner = HTMLTestReportCN(f)

  6.     runner.run(suite)

二、PyTest框架介绍

1、什么是PyTest框架?

PyTest是python中一种单元测试框架,同自带的UnitTest测试框架类似,相比于UnitTest框架使用起来更简洁,效率更高。在自动化测试中充当测试执行的功能,并可以与UnitTest互换。

2、为什么使用PyTest框架?

  • 1)非常容易上手,入门简单,文档丰富,文档中有很多实例可以参考,官方文档:https://docs.pytest.org/en/6.2.x/

  • 2)支持简单的单元测试和复杂的功能测试

  • 3)支持参数化,UnitTest需要通过插件扩展参数化功能

  • 4)执行测试过程中可以将某些测试跳过,或者对某些预期失败的Case标记成失败

  • 5)支持重复执行失败的Case:通过安装插件实现

  • 6)支持运行由Nose,UnitTest编写的测试Case。注:pytest框架的脚本在UnitTest下无法执行

  • 7)具有很多第三方插件,并且可以自定义扩展。插件获取:https://docs.pytest.org/en/latest/reference/plugin_list.html

  • 8)方便的和持续集成工具集成

3、PyTest框架安装与基本使用

与UnitTest不同的是,pytest需要先安装才能使用。注意:如果pytest命令无法使用,则需要以管理员身份重新安装pytest。

安装步骤:

  • 打开cmd窗口,输入命令:

  • 安装:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pytest

  • 确认版本:pytest --version

  • 查看:pip show pytest

测试形式:

  • 测试函数形式

    • 1)新建hm01.py文件,文件中编写函数名以test开头的测试函数

    • 2)打开Terminal,切换到.py文件路径下,输入pytest -s hm01.py

    • 3)控制台查看执行结果

  • 测试类形式:

    • 1)新建hm02.py文件,文件中编写类名以Test开头的测试类,测试方法名必须以 test 开头

    • 2)打开Terminal,切换到.py文件路径下,输入pytest -s hm02.py

    • 3)控制台查看执行结果

运行方式:

  • 命令行模式【建议】

    • 命令行中执行:pytest -s 测试脚本文件

    • 如:pytest -s test_login.py

  • 主函数模式

    • 在 测试脚本文件中增加主函数:

 
  1. # 主函数模式基本格式:

  2. if __name__ = '__main__':

  3.     pytest.main(["-s", "文件名.py"])

  4. #举例:在 test_login.py 文件中增加主函数:

  5. if __name__ = '__main__':

  6.     pytest.main(["-s", "test_login.py"])

  • 说明:

    • 1)-s 表示支持控制台打印,如果不加,print不会出现任何内容

    • 2)主函数模式需要导包 import pytest

4、PyTest框架实践

4.1 配置文件

介绍:

  • 场景:使用配置文件后可以快速的使用配置的项来选择执行哪些测试模块

步骤:

  • 1)项目下新建scripts模块

  • 2)将测试脚本文件放到scripts中

  • 3)pytest的配置文件放在自动化项目目录下

  • 4)名称为pytest.ini

  • 5)命令行运行时会使用该配置文件中的配置

  • 6)第一行内容为[pytest]

示例:

  • [pytest]  # 告知系统该文件的例行

  • testpaths = ./case  # testpaths指定测试用例存放位置

  • addopts = -s  # 添加pytest命令选项

  • python_files = test*.py  # 指定测试脚本文件名前缀

  • python_classes = Test*  # 指定测试类名前缀

  • python_functions = test*  # 指定测试函数/测试方法名前缀

注意:

  • 1、在Windows系统下,pytest配置文件中,不允许写注释信息

  • 2、一个工程内只需要一个 pytest.ini 配置文件,并且需要保证文件名正确

  • 3、一般情况,只需要将 pytest.ini 配置文件 置于工程根目录下

  • 4、配置有 pytest.ini 配置文件的工程,只需要打开命令行输入 pytest 命令,即可执行测试(注意:必须要cd切换到和配置文件同一级的目录下输入pytest)

默认配置:

  • 说明:测试用例文件名/测试类名/测试方法名均为 Test/test开头(没有配置文件的默认规则)

  • 代码:

  • [pytest]

  • testpaths = ./case

  • addopts = -s

  • python_files = test*.py

  • python_classes = Test*

  • python_functions = test*

自定义规则:

  • 说明:测试用例文件名/测试类名/测试方法名,需要根据具体项目进行设置,以下以Hm/hm为例

  • 扩展:指定单个文件/类/方法执行,只需要在配置文件中写死即可

  • 代码:

    • [pytest]

    • testpaths = ./case

    • addopts = -s

    • python_files = hm*.py

    • python_classes = Hm*

    • python_functions = hm*

4.2 特殊方法

函数级别方法: setupteardown

介绍:

  • 场景:

    • pytest在运行自动化脚本的前后会执行两个特殊的方法,分别setup和teardown。

    • 在执行脚本之前会执行setup方法,在执行脚本之后会执行teardown方法。

    • 有了这两个方法,我们可以在setup中进行获取驱动对象的操作,在teardown中进行关闭驱动对象的操作。

  • 说明:特殊方法名写法固定,没有代码提示,需要手写。

代码格式:

 
  1. import pytest

  2. class TestDemo(object):

  3.     """测试示例类"""

  4.     def setup(self):

  5.         """开始方法"""

  6.         print("方法 -> 开始")

  7.     def teardown(self):

  8.         """结束方法"""

  9.         print("方法 -> 结束")

  10.     """

举例:函数级别 setupteardown

 
  1. """

  2. import pytest

  3. class TestDemo(object):

  4.     """测试示例类"""

  5.     # 说明:特殊方法名写法固定,没有代码提示,需要手写。

  6.     def setup(self):

  7.         """开始方法"""

  8.         print("函数 -> 开始")

  9.     def teardown(self):

  10.         """结束方法"""

  11.         print("函数 -> 结束")

  12.     def test_method1(self):

  13.         """示例测试方法"""

  14.         print("测试方法1")

  15.     def test_method2(self):

  16.         """示例测试方法"""

  17.         print("测试方法2")

  18. if __name__ == '__main__':

  19.     pytest.main(['-s', 'hm05_pytest.py'])

类级别方法: setup_classteardown_class

介绍: 运行于测试类的始末,在一个测试内只运行一次setup_class和teardown_class,不关心测试类内有多少个测试函数

代码格式:

 
  1. import pytest

  2. class TestDemo(object):

  3.     """测试示例类"""

  4.     def setup_class(self):

  5.         """开始方法"""

  6.         print("类 -> 开始")

  7.     def teardown_class(self):

  8.         """结束方法"""

  9.         print("类 -> 结束")

  10.     """

举例:类级别 setup_classteardown_class

 
  1. """

  2. import pytest

  3. class TestDemo(object):

  4.     """测试示例类"""

  5.     # 说明:特殊方法名写法固定,没有代码提示,需要手写。

  6.     def setup_class(self):

  7.         """开始方法"""

  8.         print("类 -> 开始")

  9.     def teardown_class(self):

  10.         """结束方法"""

  11.         print("类 -> 结束")

  12.     def test_method1(self):

  13.         """示例测试方法"""

  14.         print("测试方法1")

  15.     def test_method2(self):

  16.         """示例测试方法"""

  17.         print("测试方法2")

  18. if __name__ == '__main__':

  19.     pytest.main(['-s', 'hm06_pytest.py'])

举例:函数级别和类级别同时使用

 
  1. """

  2. 特殊方法:函数级别和类级别同时使用

  3. """

  4. import pytest

  5. class TestDemo(object):

  6.     """测试示例类"""

  7.     # 执行顺序:1 ->3 ->5 ->4 ->3 ->6 ->4 ->2

  8.     def setup_class(self):  # 1

  9.         print("类级别 ->> 开始")

  10.     def teardown_class(self):  # 2

  11.         print("类级别 ->> 结束")

  12.     def setup(self):  # 3

  13.         print("函数级别 -> 开始")

  14.     def teardown(self):  # 4

  15.         print("函数级别 -> 结束")

  16.     def test_method1(self):  # 5

  17.         """示例测试方法"""

  18.         print("测试方法1")

  19.     def test_method2(self):  # 6

  20.         """示例测试方法"""

  21.         print("测试方法2")

  22. if __name__ == '__main__':

  23.     pytest.main(['-s', 'hm07_pytest.py'])

4.3 执行顺序插件

介绍:

  • 场景:现实生活中,如果想下订单,必须先登录,我们可以通过插件的形式来控制函数执行的顺序。

  • 安装:pip3 install pytest-ordering

  • 使用:

    • 1)标记于被测试函数,@pytest.mark.run(order=x)

    • 2)根据order传入的参数来解决运行顺序

    • 3)order值全为正数或全为负数时,运行顺序:值越小,优先级越高

    • 4)正数和负数同时存在:正数优先级高

    • 5)控制方法执行顺序对测试类同样有效,使用方法一样

  • 格式:@pytest.mark.run(order=x)

代码:

 
  1. """

  2. pytest 控制方法执行顺序插件

  3. """

  4. import pytest

  5. @pytest.mark.run(order=2)

  6. class TestDemo1(object):

  7.     """测试示例类"""

  8.     # 语法:@pytest.mark.run(order=序号)

  9.     # 注意:run(order=序号)没有代码提示,需要手写

  10.     @pytest.mark.run(order=3)

  11.     def test_method1(self):

  12.         """示例测试方法"""

  13.         print("测试方法1")

  14.     @pytest.mark.run(order=1)

  15.     def test_method2(self):

  16.         """示例测试方法"""

  17.         print("测试方法2")

  18.     @pytest.mark.run(order=2)

  19.     def test_method3(self):

  20.         """示例测试方法"""

  21.         print("测试方法3")

  22. # 扩展:序号支持正数和负数,以及正负混合

  23. # 1、纯正数:数越小,优先级越高【掌握】

  24. # 2、纯负数:数越小,优先级越高【了解】

  25. # 3、正负混合:正数先按照顺序执行,负数最后执行【了解】

  26. # 注意:控制方法执行顺序对测试类同样有效

  27. @pytest.mark.run(order=1)

  28. class TestDemo2(object):

  29.     """测试示例类"""

  30.     def test_method(self):

  31.         """示例测试方法"""

  32.         print("测试类2 -> 测试方法")

  33. if __name__ == '__main__':

  34.     pytest.main(['-s', 'hm08_pytest.py'])

4.4 失败重试插件

介绍:

  • 场景:自动化测试脚本可能会使用到网络,如果网络不好可能最终会使脚本不通过。像这种情况可能并不是脚本本身的问题,仅仅是因为网络忽快忽慢,那么我们可以使用失败重试的插件,当失败后尝试再次运行。一般情况最终成功可以视为成功,但最好进行排查看是否是脚本问题。

  • 安装:pip3 install pytest-rerunfailures

  • 使用:在配置文件中的命令行参数中增加 --reruns n

    • n:为失败重试几次

    • 如:addopts = -s --html=./report/test_report.html --self-contained-html --reruns 3

  • 说明:

    • 1)正式脚本一般设置不超过3次,测试脚本设置1次即可

    • 2)当脚本执行报错时,会自动重新执行设置次数

  • 格式:addopts = -s --reruns 3

代码: 配置文件

  • [pytest]

  • testpaths = ./case

  • addopts = -s --reruns 3

  • python_files = test*.py

  • python_classes = Test*

  • python_functions = test*

4.5 跳过

介绍:

  • 场景:同一个软件在不同的设备上可能会有不同的效果,比如,iOS的3d touch操作是需要6s以上设备支持的,6和6s都可以安装同一款应用,如果设备不支持,那根本没有必要去测试这个功能,此时,可以让这种函数进行跳过。

  • 说明:同样支持跳过测试类,使用方式一样

  • 格式:@pytest.mark.skipif(condition, reason=None)

    • 在需要跳过的测试脚本之上加上装饰器

    • condition 跳过的条件,必传参数;

    • reason 标注原因,必传参数

    • 注意:reason= 不能省略,否则会报错!

代码:

 
  1. @pytest.mark.skipif(condition, reason='xxx')

  2.   """

  3. pytest 跳过测试

  4. """

  5. import pytest

  6. version = 25  # 模拟软件版本号

  7. class TestDemo(object):

  8.     """测试示例类"""

  9.     def test_method1(self):

  10.         """示例测试方法"""

  11.         print("测试方法1")

  12.     # 注意:reason= 不能省略,否则会报错!

  13.     @pytest.mark.skipif(version >= 25, reason='当前版本不执行')

  14.     def test_method2(self):

  15.         """示例测试方法"""

  16.         print("测试方法2")

  17.     def test_method3(self):

  18.         """示例测试方法"""

  19.         print("测试方法3")

  20. # 说明:同样可以跳过测试类

  21. @pytest.mark.skipif(version >= 25, reason='当前版本不执行')

  22. class TestDemo2(object):

  23.     """测试示例类"""

  24.     def test_method(self):

  25.         """示例测试方法"""

  26.         print("测试类2->测试方法")

  27. if __name__ == '__main__':

  28.     pytest.main(['-s', 'hm09_pytest.py'])

4.6 断言

Python自带断言:

  • 预期相等:assert 1 == 1

  • 预期包含:assert 'admin' in '欢迎 admin 归来!'

代码:

 
  1. import pytest

  2. def add_func(num1, num2):

  3.     """加法函数"""

  4.     return num1 + num2

  5. class TestDemo(object):

  6.     """示例测试类"""

  7.     # 调用被测函数

  8.     result = add_func(1, 2)

  9.     # 断言判断结果

  10.     assert 3 == result

4.7 参数化

介绍:

  • 应用场景:登录功能都是输入用户名,输入密码,点击登录。但登录的用户名和密码如果想测试多个值是没有办法用普通的操作实现的。数据参数化可以帮我实现这样的效果。

  • 格式:@pytest.mark.parametrize(argnames, argvalues, indirect, ids=None, scope=None)

    • 在需要参数化的测试脚本之上加上装饰器

    • argnames:参数名

    • argvalues:参数对应值,类型必须为可迭代类型,一般使用list

单个参数:

  • 介绍:

    • 1)argnames为字符串类型,根据需求决定合适的参数名

    • 2)argvalues为列表类型,根据需求决定列表元素中的内容

    • 3)在测试脚本中,参数名字与argnames保持一致

    • 4)在测试脚本中正常使用

  • 格式:@pytest.mark.parametrize('参数变量', ['数值1', '数值2', ...])

  • 代码:

 
  1. """

  2. pytest 参数化功能:单个参数

  3. """

  4. import pytest

  5. class TestDemo(object):

  6.     """示例测试类"""

  7.     # @pytest.mark.parametrize('参数变量', ['数值1', '数值2', ...])

  8.     @pytest.mark.parametrize('name', ['小米', '小新'])

  9.     def test_method1(self, name):

  10.         """示例测试方法"""

  11.         print("获取的名字是:", name)

  12. if __name__ == '__main__':

  13.     pytest.main(['-s', 'hm10_pytest.py'])

多个参数:

  • 介绍:

    • 1)多个参数必须置于同一个字符串内!

    • 2)数据格式必须是:[(),()]或者[[], []]

  • 格式一:@pytest.mark.parametrize('参数1, 参数n', [('数值1-1', '数值2-2'), ('数值2-1', '数值2-2'), ...])

  • 格式二:@pytest.mark.parametrize(('参数1', '参数n'), [('数值1-1', '数值2-2'), ('数值2-1', '数值2-2'), ...])

代码示例1:

 
  1. """

  2. pytest 参数化功能:多个参数

  3. """

  4. import pytest

  5. class TestDemo(object):

  6.     """示例测试类"""

  7.     @pytest.mark.parametrize('name, pwd', [('admin', 123456), ('test', 654321)])

  8.     def test_method1(self, name, pwd):

  9.         """示例测试方法"""

  10.         print("账号:{} 的秘密是:{}".format(name, pwd))

  11. if __name__ == '__main__':

  12.     pytest.main(['-s', 'hm11_pytest.py'])

代码示例2:

 
  1. import pytest

  2. def build_test_data():

  3.     """构造测试数据函数"""

  4.     # 中间代码略

  5.     return [('admin', 123456), ('test', 654321), ('xxx', 'yyy')]

  6. class TestDemo(object):

  7.     """示例测试类"""

  8.     # 通过方法引入数据,pytest中必须带小括号

  9.     @pytest.mark.parametrize('name, pwd', build_test_data())

  10.     def test_method1(self, name, pwd):

  11.         """示例测试方法"""

  12.         print("账号:{} 的秘密是:{}".format(name, pwd))

4.8 测试报告插件

介绍:

  • 应用场景:自动化测试脚本最终执行是通过还是不通过,需要通过测试报告进行体现。

  • 安装:pip3 install pytest-html

  • 使用:在配置文件中的命令行参数中增加 --html=用户路径/report.html

  • 扩展:在 --html 后面加上 --self-contained-html,可以把CSS样式内嵌到html报告文件中(防止分享报告时丢失样式)

  • 示例:

    • addopts = -s --html=./report/test_report.html

    • addopts = -s --html=./report/test_report.html --self-contained-html

  • 格式:addopts = -s --html=./report/test_report.html --self-contained-html

代码: 配置文件

  • [pytest]

  • testpaths = ./case

  • addopts = -s --html=./report/test_report.html --self-contained-html

  • python_files = test*.py

  • python_classes = Test*

  • python_functions = test*

4.9 PyTest框架运行UnitTest的TestCase

在配置文件中把python_files的名字修改为TestCase测试用例的文件名(xxx.py)即可。

4.10 总结

配置文件:

  • 位置:项目/pytest.ini

  • 内容:

    • [pytest]

    • testpaths = ./case

    • addopts = -s --html=./report/test_report.html --self-contained-html --reruns 3

    • python_files = test*.py

    • python_classes = Test*

    • python_functions = test*

 最后: 下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/411061.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用canal增量同步ES索引库数据

Canal增量数据同步利器 Canal介绍 canal主要用途是基于 MySQL 数据库增量日志解析,并能提供增量数据订阅和消费,应用场景十分丰富。 github地址:https://github.com/alibaba/canal 版本下载地址:https://github.com/alibaba/c…

鸿蒙开发:深入浅出Stage模型(UIAbility组件)

🚀一、UIAbility组件 🔎1.概述 HarmonyOS中的Stage模型是一种基于UIAbility组件的应用程序架构。UIAbility是HarmonyOS系统中用于构建用户界面的基本组件之一。它负责处理应用程序界面的显示和交互。 在Stage模型中,每个应用程序都有一个或…

LLM —— 强化学习(RLHF-PPO和DPO)学习笔记

强化学习整体流程 智能体执行动作与环境进行交互,根据奖励R的反馈结果不断进行更新。 价值函数 奖励将会考虑两个方面的奖励,一个当下的奖励,一个是未来的奖励(为了防止陷入局部最优解)。 LLM强化学习 强化学习模型分…

CTF—杂项学习

1 文件操作隐写 1.1 文件类型识别 1.1.1 File命令 当文件没有后缀名或有后缀名而无法打开时,根据识别出的文件类型来修改后缀名即可正常打开文件,file是Linux下的文件识别命令。 file 文件名 使用场景:不知道后缀名,无法打开文件…

【STM32开发笔记】STM32H7S78-DK上的CoreMark移植和优化--兼记STM32上的printf重定向实现及常见问题解决

【STM32开发笔记】STM32H7S78-DK上的CoreMark移植和优化--兼记STM32上的printf重定向实现及常见问题解决 一、CoreMark简介二、创建CubeMX项目2.1 选择MCU2.2 配置CPU时钟2.3 配置串口功能2.4 配置LED引脚2.5 生成CMake项目 三、基础功能支持3.1 支持记录耗时3.2 支持printf输出…

SEO之网站结构优化(十三-网站地图)

** 初创企业搭建网站的朋友看1号文章;想学习云计算,怎么入门看2号文章谢谢支持: ** 1、我给不会敲代码又想搭建网站的人建议 2、“新手上云”能够为你开启探索云世界的第一步 博客:阿幸SEO~探索搜索排名之道 网站无论大小&…

京存分布式赋能EDA应用

合抱之木,生于毫末;九层之台,起于累土;千里之行,始于足下。——《老子德经第六十四章》 EDA(Electronic Design Automation 电子设计自动化)是利用计算机,完成对VLSI (V…

OpenCV绘图函数(8)填充凸多边形函数fillConvexPoly()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 填充一个凸多边形。 函数 cv::fillConvexPoly 绘制一个填充的凸多边形。这个函数比 fillPoly 函数快得多。它可以填充的不仅仅是凸多边形&#…

25届最近5年自动化考研院校分析

哈尔滨工程大学 目录 一、学校学院专业简介 二、考试科目指定教材 三、近5年考研分数情况 四、近5年招生录取情况 五、最新一年分数段图表 六、初试大纲复试大纲 七、学费&奖学金&就业方向 一、学校学院专业简介 二、考试科目指定教材 1、考试科目介绍 2、指定…

C++ | Leetcode C++题解之第377题组合总和IV

题目&#xff1a; 题解&#xff1a; class Solution { public:int combinationSum4(vector<int>& nums, int target) {vector<int> dp(target 1);dp[0] 1;for (int i 1; i < target; i) {for (int& num : nums) {if (num < i && dp[i - …

《JavaEE进阶》----4.<SpringMVC①简介、基本操作>

本篇博客讲解 MVC思想、及Spring MVC&#xff08;是对MVC思想的一种实现&#xff09;。 Spring MVC的基本操作、学习了六个注解 RestController注解 RequestMappering注解 RequestParam注解 RequestBody注解 PathVariable注解 RequestPart注解 MVC View(视图) 指在应⽤程序中…

四大名著改编的ip大作,一个巨亏2亿,一个狂赚20亿!选择决定成败!

最近讨论热度比较高的当属《红楼梦》和《西游记》了 胡玫导演的《红楼梦之金玉良缘》耗费了18年的心血&#xff0c;投资了2个多亿 却仅仅只有600万票房&#xff0c;还被网友调侃称“一黛不如一黛” 而由《西游记》改编的游戏《黑神话悟空》&#xff0c;研发10年投资6亿&…

【drools】Rulesengine构建及intelj配置

7.57.0.FinalRulesengineApplication 使用maven构建 intelj 打开文件资源管理器实在是太慢了所以直接把pom 扔到其主页识别为maven项目,自动下载maven包管理器 然后解析依赖: 给maven加一个代理 -DproxyHost=127.0.0.1 -DproxyPort=7890 还是卡主

机器人拾取系统关节机械臂通过NY-PN-EIPZ进行命令控制

关节机械臂是一种精密的机器&#xff0c;旨在模拟人类手臂在订单拣选操作中的运动。这些多功能机器人由多个关节组成&#xff0c;通常有 4 到 7 个轴&#xff0c;使它们能够高度自由地移动&#xff0c;并在仓库内以各种方向和位置接触物品。 制造工厂智能仓库系统中的关节机械臂…

Mobile-Agent项目部署与学习总结(DataWhale AI夏令营)

前言 你好&#xff0c;我是GISer Liu&#xff0c;一名热爱AI技术的GIS开发者&#xff0c;本文是DataWhale 2024 AI夏令营的最后一期——Mobile-Agent赛道&#xff0c;这是作者的学习文档&#xff0c;这里总结一下&#xff0c;和作者一起学习这个多模态大模型新项目吧&#x1f6…

AMEYA360 :“Radisol”,一款可改善智能手机Wi-Fi天线性能的村田电子新产品

株式会社村田制作所开发了村田首款(1)天线抗干扰器件‘Radisol’。Radisol是一款可配备到天线上来抑制无线性能下降的新产品&#xff0c;该产品已于2024年6月开始量产&#xff0c;并已用在Motorola Mobility LLC 2024年8月开始销售的智能手机“Edge系列”新机型。摩托罗拉通过采…

【Qt】垂直布局管理器QVBoxLayout

垂直布局管理器QVBoxLayout 在之前学习Qt的过程中&#xff0c;将控件放在界面上&#xff0c;都是依靠“手动”的方式来布局的&#xff0c;但是手动调整的方式是不科学的。 手动布局的方式非常复杂&#xff0c;而且不精确无法对窗口大小进行自适应 因此Qt引入布局管理器来解决…

缓存Mybatis一级缓存与二级缓存

缓存 为什么使用缓存 缓存(cache)的作用是为了减去数据库的压力,提高查询性能,缓存实现原理是从数据库中查询出来的对象在使用完后不销毁,而是存储在内存(缓存)中,当再次需要获取对象时,直接从内存(缓存)中提取,不再向数据库执行select语句,从而减少了对数据库的查询次数,因此…

无法启动此程序,因为计算机中丢失dll,整理了7种解决方法!

当电脑出现“无法启动此程序&#xff0c;因为计算机中丢失dll”的错误弹窗时&#xff0c;这通常意味着系统中的DLL文件出现了缺失或错误。DLL文件是动态链接库文件&#xff0c;它们在软件运行中起着至关重要的作用。 造成dll文件缺失和错误的原因有很多&#xff0c;大部分问题都…

python爬虫,使用pyppeteer异步,爬取,获得指定标签内容

获得指定 #pip install pyppeteer,使用 Pyppeteer&#xff08;异步方案&#xff09; import asyncio from pyppeteer import launch async def main():browser await launch()page await browser.newPage()await page.goto(http://xxx/#/login)# 等待页面加载完成await page…