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 数据了。

相关推荐
bossface7 分钟前
ES的简单讲解
服务器·c++·json·gtest·etcd·spdlog
村中少年1 小时前
使用DeepSeek/chatgpt等AI工具辅助网络协议流量数据包分析
网络协议·chatgpt·wireshark·json·aigc
ClaNNEd@1 小时前
Flutter&JSON
flutter·json
不求大富大贵只求富可敌国7 小时前
Gtest, Junit,以及pytest对比理解
junit·pytest
xing25161 天前
pytest下放pytest.ini文件就导致报错:ERROR: file or directory not found: #
pytest
只会写Bug的程序员1 天前
面试之《nodejs中,网络请求时stream和json的区别》
网络·面试·json
C_V_Better1 天前
Java 接收 XML 格式参数并转换为 JSON
xml·java·开发语言·数据结构·后端·算法·json
kongba0072 天前
EIDE搭配cursor编译GD32的项目 需要的一些c_cpp_properties设置 json文件
c语言·开发语言·json
电商数据girl2 天前
关于酒店旅游信息的数据采集API接口返回||包含参数说明
java·大数据·开发语言·数据库·json·旅游