pytest测试框架介绍

1、pytest基本介绍

pytest是一个功能强大且易于使用的python测试框架,用于编写单元测试、集成测试和功能测试。

提供了丰富的功能和灵活的用法,使得编写和运行测试边得简单而高效。

1.1 pytest框架优点

  • 简单易用:pytest语法非常简洁清晰,对于编写测试用例来说,非常友好,几乎可以在几分钟内上手。
  • 自动发现测试:pytest能够自动发现项目中的测试文件和测试函数,无需手动编写繁琐的配置。
  • 丰富的断言库:pytest内置了丰富的断言库,可以轻松地进行测试结果的判断。
  • 支持参数化测试:pytest支持参数化测试,能够快速地对多组输入进行测试。
  • 插件丰富:pytest有着丰富的插件生态系统,可以通过插件扩展各种功能,比如覆盖率测试,测试报告生成等。

1.2 安装

# 安装
pip install pytest
# 查看版本
pytest --version

2、pytest基本使用

2.1 pytest的组成部分

pytest由两部分组成:
① 用例主体部分(通常单独放在一个py文件):主体部分写测试用例
② 用例运行语句(通常放在一个main文件):执行测试用例

2.2 pytest用例规范

1) 文件:必须以test_开头或_test结尾
2) 类:以Test开头,或者继承unittest.TestCase的任意名称的类
3) 方法:以test_开头的方法
4) 注意:测试类中,不可以添加init()构造函数,pytest不识别init()的类内的测试方法

2.3 pytest的运行方式

# 主函数运行方式
import pytest

if __name__ == "__main__":
  pytest.main()
  
  # 指定文件运行
  pytest.main(["./testcase/test_01.py"])
  
  # 指定目录运行
  pytest.main(["./testcase"])
  
  # 指定运行的测试类中的用例
  pytest.main(["./testcase/test_01.py"::TestDemo])
  
  # 指定运行的测试类中的某一条用例
  pytest.main(["./testcase/test_01.py"::TestDemo::test_01])
  
  # 匹配包含关键词的用例(匹配目录名、模块名、类型、用例名)
  # -k demo表示匹配包含demo的用例,可以使用and、or
  pytest.main(['-k', 'demo'])
  
  # -v显示详细信息,输出调试信息
  pytest.main(['-v', './testcase'])
  
  # -s输出更详细的信息,如:文件名、用例名
  pytest.main(['-vs', './testcase'])
  
  # -x 只要有一个用例执行失败,就停止执行测试
  pytest.main(['-vsx', './testcase'])
  
  # --maxfail 出现N个测试用例失败,就停止测试
  pytest.main(['-vs', '--maxfail=3', './testcase'])
  
  # --html=report.html 生成html格式的报告
  pytest.main(['-vsx', '--html=./report/report.html', './testcase'])

3、pytest夹具 fixture

pytest框架中,fixture是一个强大的功能,用于在测试执行过程中提供固定的测试环境或数据。这使得测试更加模块化、可重用、并且易于维护。

3.1 什么是fixture

在pytest中,fixture是一个函数,它在测试执行之前被调用,用于设置测试所需的环境和数据,例如:可以使用fixture来创建一个数据库连接、加载测试数据或者模拟外部服务。
前置:环境准备、数据准备
后置:清理工作、数据清理

3.2 pytest的fixture实现方式

(1)xunit-style
跟unittest框架机制非常相似,即setup/teardown

# 1) 测试函数/方法级别
每一个测试函数都会执行的前置和后置

# 测试类内部的测试方法,模块
前置函数:setup_method
后置函数:teardown_method

# 模块下的测试函数
前置函数:setup_function
后置函数:teardown_function


# 2) 测试类级别
一个测试类只执行一次前置和后置
前置函数:setup_class
后置函数:teardown_class
# 注意:用@classmethod装饰


# 3) 模块级别
一个测试模块只执行一次前置和后置
前置函数:setup_module
后置函数:teardown_module
def setup_method():
  print("模块级别setup操作")

def teardown_method():
  print("模块级别teardown操作")
  
def setup_function():
  print("函数级别setup操作")
  
def teardown_function():
  print("函数级别teardown操作")
  
class TestSys:
  @classmethod
  def setup_class():
  print("类级别setup操作")
  
  @classmethod 
  def teardown_class():
    print("类级别teardown操作")

(2)fixture机制
通过@pytest.fixture装饰器来定义fixture

  • fixture通过函数来实现
  • 使用@pytest.fixture进行装饰
  • 前置和后置都放在同一个函数当中,通过yield关键字区分前置和后置,yield前面的为前置,yield后面的为后置
import pytest

@pytest.fixture
def init_test():
  print("测试前置代码")
  yield
  print("测试后置代码")

@pytest.fixture
def init_test02():
  print("没有yeild关键字,这段代码在用例执行之前运行")
  
@pytest.fixture
def init_test03():
  yield
  print("这段代码在测试用例执行之后执行")

3.3 fixture的作用域

fixture有4个作用域

测试会话 session
测试模块 module
测试类 class
测试用例 function

设置fixture的作用域,通过@pytest.fixture(scope=作用域)来设置,默认情况下,scope=function
取值范围说明
function函数级每个函数或方法都会调用
class类级别每个测试类只运行一次
module模块级每个.py文件只调用一次
package包级每一个python包只调用一次
session会话级每次会话只需要运行一次,会话内所有方法及类、模块都共享这个方法

3.3 fixture的返回值

在测试用例中,要使用fixture生成数据时,需要fixture返回数据,使用yield进行返回

import pytest
from selenium import webdriver

# 类级别fixture,只执行一次fixture
@pytest.fixture(scope="class")
def init_test():
  print("类级别fixture,执行所有用例之前,执行该代码")
  driver = webdriver.Chrome()
  # 返回driver对象
  yield driver 

  print("类似teardown,测试用例全部执行完后,执行该代码")
  driver.quit()

3.4 conftest共享机制

# 共享实现
1) 在项目根目录下,创建一个conftest.py文件
2) 文件名必须是conftest.py,大小写敏感,不可改名字
3) conftest.py当中,可以编写多个fixture
4) 在测试用例文件当中,不需要引入conftest.py文件,直接调用fixture的函数名 ,会自动去conftest.py文件中查找

conftest.py层级作用域
项目根目录下的conftest.py,作用域是整个项目,项目中所有的测试用例,都可以使用conftest.py中定义的fixture

子目录里的conftest.py,只有在子目录中的测试用例可以使用

测试用例执行时,调用的fixture的顺序,按就近原则调用

测试用例文件中的fixture > 当前目录中的fixture > 上级目录中的fixture > 根目录中的fixture

3.5 fixture的嵌套

嵌套的fixture允许在创建一个fixture时候,本身依赖另外一个fixture,这样可以构建出更加复杂和模块化的测试环境

定义嵌套fixture
嵌套fixture通常在测试用例中通过依赖注入的方式使用

# 1) 定义基础fixture
import pytest

@pytest.fixture
def base_setup():
  print("我是基础的fixture,前置处理")
  
  yield # yield语句之后的内容,在测试完成后执行
  
  print("我是基础的fixture,后置处理")


# 2) 定义嵌套fixture
# 当前定义的fixture,可以依赖上面的基础fixture
def next_setup(base_setup):
  print("我是嵌套的fixture,前置处理")
  
  yield # yeild语句之后的内容,在测试完成后执行
  
  print("我是嵌套的fixture,后置处理")
  
# 3) 在测试用例中,使用嵌套fixture
def test_with_demo_01(next_setup):
  print("测试用例代码")
# 以上执行顺序
① base_setup的执行,基础设置
② next_setup的执行,嵌套设置
③ 测试用例执行 test_with_demo_01
④ next_setup的情况,嵌套清理
⑤ base_setup的清理,基础清理

3.6 fixture的优势

  • 减少重复代码:通过将公共的资源或环境初始化放在fixture中,可以避免在每个测试用例中重复编写相同的代码
  • 提高代码可读性:通过将测试用例的依赖项以参数的形式传入,使得测试用例的意图更加明确,便于阅读和维护
  • 便于扩展和维护:通过将复杂的测试环境或资源抽象为fixture,使得后续的扩展和维护变更更加容易;可以根据需要添加更多的fixture来满足不同的测试需求
  • 支持依赖注入:fixture不仅可以为测试用例提供数据和环境,还可以支持依赖注入。这样可以将一个对象或服务的实例传递给需要它的多个测试用例
数据库连接:在测试数据库相关的操作时,我们通常需要先建立数据库连接。通过使用fixture,可以确保每个测试用例都有干净的数据库环境

模拟数据:在测试过程中,我们可能需要模拟一些数据来满足特定的条件。通过fixture,我们可以轻松地创建和初始化模拟数据

配置初始化:对于一些配置相关的测试,我们可以使用fixture来初始化配置文件或环境变量,这样每个测试用例都可以基于相同的配置进行验证

外部服务连接:当测试设计到外部服务时,我们可以使用fixture来建立与服务器之间的连接,并在测试结束后关闭连接

依赖注入:对于一些复杂的对象或服务,我们可以将其实例化并作为fixture传递给需要它的测试用例,这样,不同的测试用例可以共享一个示例,而无需在每个测试中重新创建
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值