Pytest中5种不同的方法解析JSON数据

关注开源优测不迷路

大数据测试过程、策略及挑战

测试框架原理,构建成功的基石

在自动化测试工作之前,你应该知道的10条建议

在自动化测试中,重要的不是工具

JavaScript 对象表示法(JSON)可以说是网络上最流行的数据交换格式之一。

Web 服务使用序列化技术将数据从底层数据结构转换为 JSON 格式,以便接收服务能够轻松地对其进行反序列化。

在编写单元测试时,测试 JSON 输入和输出的需求至关重要。

测试数据、API 响应,有时甚至配置文件都是用 JSON 定义的,这使得使用 Pytest 理解如何读取和写入 JSON 变得十分必要。

在本文中,我们将探索在 Pytest 中读取 JSON 数据的 5 种简单方法,这样你就可以用它来验证输入的测试数据、配置文件、API 响应等等。

目标

在本文结束时,你应该能够:

  1. 使用 5 种不同的方法在 Pytest 中解析 JSON 数据。

  2. 理解如何使用 Pytest 的 fixture(夹具)和参数将 JSON 数据解析到单元测试中。

入门

在开始操作前,请按以下目录组织你的代码结构

本文中不需要特殊的库,只需要 pytest 和一个代码格式化检查工具。

现在让我们来看看在 Pytest 中解析 JSON 输入的 5 种不同方法。

源代码

我们的源代码是一个非常简单的示例,它接受一个 JSON 字符串输入,并根据 "age" 字段计算出 "birth_year"(出生年份)。

read_json/core.py

kotlin 复制代码
import json  def compute_birth_year(input_data: str):      # 将JSON数据解析为Python字典            data = json.loads(input_data)                  # 计算出生年份            birth_year = 2023 - data["age"]                  return f"{data['name']} was born in {birth_year}"
go 复制代码
让我们看看如何用5种不同的方式来测试这个函数。
  1. 在测试中定义 JSON

测试这个函数最简单的方法之一是在我们的单元测试中定义输入的 JSON。

tests/unit/test_read_json.py

makefile 复制代码
def test_compute_birth_year_1():  input_data = '{"name": "John", "age": 30, "city": "New York"}'              expected = "John was born in 1993"              assert compute_birth_year(input_data) == expected
go 复制代码
虽然这种方法很简单,但灵活性较差。

如果你想用新的 JSON 数据运行测试,就必须修改测试模块(这很不方便)。

  1. 读取外部 JSON 文件

一种有趣且方便的读取 JSON 文件的方法是将其单独保存,放在测试模块之外。

这样你就可以动态地对其进行修改,而无需更改测试本身。

tests/unit/test_read_json.py

cs 复制代码
def test_compute_birth_year_2():      file = pathlib.Path("tests/unit/test_data/input1.json")                  with open(file) as f:                input_data = f.read()                      expected = "Jerry was born in 1968"                  assert compute_birth_year(input_data) == expected
go 复制代码
在这里,我们使用了 pathlib 模块来解析文件,但你也可以使用 json 模块。

这种方法的好处是我们将输入与测试模块解耦了,但如果输入文件不可用,你就会遇到测试错误。

  1. 将 JSON 数据作为 fixture 提供

另一种方法(也是我非常喜欢的一种)是将输入数据作为 Pytest 的 fixture 提供。

如果你不熟悉 Pytest 的 fixture 及其工作原理,这篇文章提供了很好的基础介绍。

简而言之,fixture 是 Pytest 函数(通常在 conftest.py 中定义),可以在一个或多个测试模块中轻松使用,并通过 scope 参数进行状态控制。

我们定义 JSON 的 fixture:

tests/unit/conftest.py

ruby 复制代码
@pytest.fixture(scope="session")  def input_json():       return json.dumps({        "name": "Eric",         "age": 32,         "city": "London"        })
go 复制代码
现在我们可以在单元测试中使用它了。

tests/unit/test_read_json.py

cpp 复制代码
def test_compute_birth_year_3(input_json):    expected = "Eric was born in 1991"          assert compute_birth_year(input_json) == expected
go 复制代码
4. 使用 Pytest 参数定义 JSON

你也可以利用 Pytest 中的参数来定义测试输入。

为此,我们使用 @pytest.mark.parametrize 标记。让我们来看一下。

tests/unit/test_read_json.py

swift 复制代码
@pytest.mark.parametrize( "input_data, expected", [('{"name": "Robin", "age": 55, "city": "Los Angeles"}', "Robin was born in 1968"),])  def test_compute_birth_year_4(input_data, expected):
      assert compute_birth_year(input_data) == expected
go 复制代码
在标记中,我们定义了输入数据和预期值,然后定义了一个输入值列表(每个元素都是一个元组)。

Pytest 会将这个输入值列表传递给测试。非常简洁!

  1. 在运行时提供 JSON

将 JSON 解析到单元测试中的最后一种方法是在运行时将其作为命令行界面(CLI)输入提供。

为此,我们在 conftest.py 中定义几个 fixture。

conftest.py

swift 复制代码
def pytest_addoption(parser):      parser.addoption(    "--input-json",     action="store",     default='{"name":"Rick", "age": 50, "city": "NY"}',     help="Input JSON")        @pytest.fixture  def input_json_command_line(request):      return request.config.getoption("--input-json")
go 复制代码
我们使用内置的解析器将 --input-json 标志解析给 Pytest,指定一个默认值,最后将其用作 fixture。

然后我们可以在单元测试中使用它。

tests/unit/test_read_json.py

ruby 复制代码
@pytest.fixture  def input_json_command_line(request):      return request.config.getoption("--input-json")
go 复制代码
这种方法虽然简单,但扩展性不好,特别是当你需要解析多个 JSON 时。

运行单元测试

要运行单元测试,只需运行:

bash 复制代码
pytest tests/unit/test_read_json.py -v -s --input-json="{'name': 'Ravi', 'age': 90, 'city': 'New Delhi'}"

结论

在本文中,我们研究了在单元测试中解析 JSON 的 5 种方法。

在编写单元测试、集成测试、端到端测试或 API 测试时,知道如何解析 JSON 尤为重要,因为几乎所有的数据交换都是通过 JSON 格式进行的。

你学习了各种技术,包括使用 fixture 和参数、通过外部文件和命令行传递 JSON。

有了这些知识,你现在可以在 Python 单元测试中高效地解析 JSON 数据了。

相关推荐
10km6 分钟前
java:json-path支持fastjson作为JSON解析提供者的技术实现
java·json·fastjson·json-path
哈哈~haha8 小时前
ui5_Walkthrough_Step 7:JSON Model
json·mvc·module·ui5
随风一样自由10 小时前
React内逐行解释这个 package.json 文件,最近搞了个工厂AI生产平台,顺便来学习一下
学习·react.js·json·package
wtsolutions11 小时前
Excel to JSON by WTSolutions 4.0.0 版本更新公告
json·excel·wps·插件·转换·加载项·wtsolutions
wtsolutions11 小时前
Excel to JSON by WTSolutions 4.0.0 Update Announcement
json·excel·wps·addin·wtsolutions·conversion
学网安的肆伍11 小时前
【036-安全开发篇】JavaEE应用&第三方组件&Log4j日志&FastJson序列化&JNDI注入
安全·java-ee·log4j
爱学习的小可爱卢11 小时前
JavaEE——Spring IoC与DI核心揭秘:从入门到精通
spring·java-ee·log4j·springioc
最笨的羊羊1 天前
Flink CDC系列之:Kafka 变更日志 JSON 格式工厂类 ChangeLogJsonFormatFactory
json·flink cdc系列·changelog·kafka 变更日志·json 格式工厂类·formatfactory
于是我说1 天前
Python Requests Session Cookies 与 JSON 文件的存取
python·json·dubbo
YAY_tyy1 天前
详解 3D Tiles 核心入口文件:tileset.json 结构与实战解析
3d·json·3dtiles