Karate API 测试:DSL 实战指南

想让接口测试像英语一样易读?本文带你深入开源框架 Karate。无需编写复杂的胶水代码,使用简单的 BDD 语法即可实现强大的 JSON 断言、数据驱动测试及 CI 集成,让 API 自动化测试更高效!

用 Apifox,节省研发团队的每一分钟

Karate API 测试:DSL 实战指南

免费使用 Apifox

相关推荐

最新文章

API

一体化协作平台

API 设计

API 文档

API 调试

自动化测试

API Mock

API Hub

立即体验 Apifox
目录

你希望 API 测试读起来像普通的英语,能够与代码一起存放在 Git 中,并且可以在任何 CI 流水线中运行。Karate 正是为此而生。它使用了一种领域特定语言(DSL),让你能够以 Given / When / Then 步骤的形式编写测试,而不是编写 Java 方法。本指南将介绍 Karate 是什么、它的 feature 文件如何工作,并提供一个可运行的示例。

什么是 Karate

Karate 是一个基于 Java 的开源 API 自动测试框架。你可以在 .feature 文件中,使用源自行为驱动开发(BDD)的 Given/When/Then 结构,将每个测试描述为一个场景。与 Cucumber 等工具不同的是,你无需编写步骤定义(step-definition)的胶水代码。Karate 内置了 HTTP 步骤、断言和 JSON 处理功能,因此一个可运行的 API 测试完全不需要 Java 代码。

该项目不仅包含 API 测试。其代码仓库中还包含了用于 mock、性能测试(通过 Gatling)和 UI 自动化的模块。本指南将重点关注 API 测试核心功能,这也是大多数团队最先接触的部分。

由于测试是纯文本文件,因此它们非常易于进行版本控制。Pull Request 中的差异对比(diff)能清晰地展示出哪个断言发生了改变。这能很好地与代码评审(code review)以及基于 Git 原生、基于代码的工作流相结合。

如果你对 Given/When/Then 风格还不熟悉,可以阅读我们的行为驱动开发入门指南,了解其起源以及团队使用它的原因。

工作原理:Feature 文件和 karate-config.js

Karate 测试始于 feature 文件。每个文件包含一个 Feature: 块和一或多个 Scenario: 块。在场景内部,你使用 Given 设置请求,使用 When 发送请求,并使用 Then 进行断言。

以下是 Karate 官方快速入门中展示的结构:

Feature: User API

Scenario: List all users
  Given url 'https://jsonplaceholder.typicode.com'
  And path 'users'
  When method get
  Then status 200
  And match response == '#[10]'

自上而下阅读该代码。url 设置了前置 URL。path 拼接了资源路径。method get 发送请求。status 200 检查 HTTP 状态码。最后一行断言响应是一个正好包含 10 个项的 JSON 数组。其中的 #[10] 是 Karate 标记,而不是 JavaScript。有关这些标记的更多信息,请参阅断言章节。

这里的 Gherkin 是标准的 Given/When/Then。如果你你想深入了解该语法本身,请参阅我们的 BDD 与 API 测试的 Gherkin 指南。

大多数项目都需要环境特定的值:例如开发环境的前置 URL、预发环境的 Token,以及生产环境的接口。Karate 通过一个名为 karate-config.js 的文件来处理这些问题。它在你的测试运行前执行一次,并返回一个每个场景都可以读取的配置 object。

function fn() { var env = karate.env || 'dev'; var config = { baseUrl: 'https://jsonplaceholder.typicode.com' }; if (env === 'qa') { config.baseUrl = 'https://qa.example.com'; } return config; }

karate.env 来自于你在运行时传入的系统属性。无需修改任何 feature 文件即可切换环境。如此一来,在测试场景中你只需编写 Given url baseUrl,而无需硬编码地址。

示例测试场景

我们来编写一个包含请求 body 的用例。该测试场景将创建一个用户、检查状态并验证响应的结构。

gherkin Feature: Create user
Background:
url baseUrl
Scenario: Create a new user returns 201 Given path 'users' And request { name: 'Ada', job: 'engineer' } When method post Then status 201 And match response.name == 'Ada' And match response.id == '#string'

有几点需要注意。Background: 模块在文件中的每个测试场景运行之前执行,因此你只需设置一次前置 URL。* 是一个通配符步骤;Karate 将 * 视为与 GivenWhenThen 相同,这使你在编写初始化步骤时无需担心语法问题。request 关键字直接接收 JSON 载荷(payload),无需序列化器,也无需 POJO。而 #string 是一个模糊匹配器,用于断言 id 字段存在且为字符串,而无需将其固定为特定值。

断言与 JSON 匹配

断言是 Karate 的核心优势所在。其核心关键字是 match。它将实际值与预期值进行比较,并在出现任何不匹配时使测试失败。

精确匹配检查等价性:

gherkin And match response == { id: '#number', name: 'Ada', job: 'engineer' }

#number#string#boolean#uuid 等 Token 是模糊匹配器。它们只断言类型和是否存在,而不要求具体的字面值。当服务端返回自动生成的 ID 或时间戳时,这有助于保持测试的稳定性。

当你只关心部分字段时,可以使用 contains

gherkin And match response contains { name: 'Ada' }

只要 name 等于 Ada,该断言就会通过,即使响应中还包含其他十个字段。Karate 还支持 !containscontains onlycontains anycontains deep,以便对部分匹配进行更精细的控制。

你也可以验证数组。match response == '#[10]' 用于断言一个长度为 10 的数组。你可以使用 each 将数据模型应用到每个元素:

gherkin And match each response == { id: '#number', name: '#string' }

仅需这一行代码,即可检查数组中的每个 object 是否都拥有数字类型的 id 和字符串类型的 name。在通用的测试框架中,这种结构验证通常需要编写循环和多个断言。如果你想全面了解如何校验响应,我们关于 API 断言的实用指南介绍了各种工具中的常用模式。

数据驱动测试与 CI

实际的测试套件通常需要针对许多不同的输入运行相同的逻辑。Karate 通过 Scenario OutlineExamples 表格来处理这种情况。尖括号中的占位符会替换为每一行中的对应数据。

Scenario Outline: Create users from a table
Given url baseUrl
And path 'users'
And request { name: '', job: '' }
When method post
Then status 201
And match response.name == ''

Examples:
| name | job |
| Ada | engineer |
| Grace | scientist |
| Alan | analyst |

这会运行该场景三次,每行运行一次。您还可以从外部文件读取行,而不是使用内联表,这样可以避免将大型数据集写入您的 feature 文件中:

  Examples:
    | read('classpath:test-data/users.json') |

Karate 以这种方式读取 JSON 和 CSV 文件,因此您的测试数据可以存放在团队偏好管理的任何位置。

对于持续集成,您有两条路径。在 Maven 或 Gradle 项目中,Karate 通过 JUnit 5 运行。您只需添加 karate-junit5 依赖项,并将 runner 指向您的 feature 文件,这样 mvn test 就会像执行任何其他单元测试一样执行它们。这意味着您现有的 CI 步骤不需要特殊的工具。

第二条路径是独立的 jar 包,它不需要构建工具。从项目的 releases 中下载 karate.jar 并直接运行 feature 文件。请注意,该 jar 包需要较新版本的 Java,因此请查看发行说明(release notes)以了解最低版本要求。

java -jar karate.jar src/test/java/features

您可以按标签进行过滤、并行运行并选择输出目录:

java -jar karate.jar --tags @smoke --threads 4 --output reports src/test/java/features

通过系统属性传递环境,该属性会流入到 karate-config.js 中的 karate.env

java -jar karate.jar -Dkarate.env=qa src/test/java/features

Karate 在每次运行后都会向输出目录写入一份 HTML 报告,因此在流水线产物中很容易排查失败原因。有关更广泛的 CI 全景,请参阅如何在 CI/CD 中实现 API 测试自动化。

优势与折中

Karate 具有明显的优势。测试的阅读感非常接近纯英语,这为不熟悉 Java 的人降低了门槛。内置的 JSON 匹配(包括模糊匹配和 each)省去了大量的断言模板代码。所有内容都以文本文件的形式保存在 Git 中,因此测试可以像源码一样进行评审(review)和比对差异(diff)。此外,它涵盖的不止是 HTTP,团队以后可以在不更换工具的情况下添加 mock 或进行性能测试。

但折中也是显而易见的。Karate 运行在 JVM 上,因此您需要安装 Java,并且在处理基础之上的内容时,需要对 JVM 生态系统有一定的了解。DSL 本身也需要学习;虽然语法读起来很容易,但编写正确的匹配器和重用模式需要练习。可重用的逻辑、自定义助手和复杂的设置往往会把您拉回到 JavaScript 函数或 Java 互操作上。而且因为测试即代码,团队中的非开发人员通常在没有帮助的情况下无法编写或编辑它们。

这些并不是什么缺点,而是“代码优先”框架的典型特征。关键在于这是否符合您团队的工作方式。

Karate 对比无代码方案 (Apifox)

Karate 是基于代码且 Git 原生的。你需要编写 feature 文件,提交它们,然后通过构建工具或 jar 包运行它们。这非常适合那些希望将测试与应用程序一起放入版本控制,并且熟悉 JVM 的工程师。

Apifox 则通过可视化的无代码方式来实现相同的目标。你可以在 UI 中构建测试场景、串联请求,并通过点击而不是编写 DSL 来添加断言。由于整个 API 生命周期(设计、调试、mock、文档)都集中在一个地方,测试可以复用你已经定义的接口和数据模型。这降低了 QA 工程师和不想管理 Java 项目的产品人员的门槛。

这种可视化套件并不局限于 UI 界面。Apifox 支持在 CI 中通过 Apifox CLI 以无头模式运行它们,因此无代码套件仍然可以无缝接入自动化流水线。你可以使用 Node 来安装它:

npm install -g apifox-cli

然后通过 ID 触发已保存的测试场景或套件,指定环境并选择报告格式:

apifox run --access-token "$APIFOX_ACCESS_TOKEN" -t <scenarioOrSuiteId> -e <environmentId> -r cli,html,junit

-t 参数指向测试场景、目录或套件;-e 用于选择环境;-r 用于指定一个或多个报告器(clihtmljsonjunit)。对于数据驱动的运行,-d(或 --iteration-data)可以接收数据文件路径或测试数据 ID。该 CLI 是无头的,可以在任何支持运行 Node 的 CI 步骤中执行。它运行的是你保存的 Apifox 测试场景,而不是一个交互式的请求发送器或负载生成器。有关完整指南,请参阅 Apifox CLI 中的 CI/CD,以及与其他运行器的对比:Apifox CLI vs Newman。

这两种方法都能生成在 CI 中无头运行的自动化 API 测试。两者的区别主要在于编写风格:Karate 需要你在 Git 中编写 DSL;而 Apifox 则让你在 UI 中进行点击操作,同时也能导出到流水线中。

如何选择

如果你的团队以 proto 开发者为主、熟悉 JVM,并且希望将测试作为代码与应用程序一起进行版本控制,请选择 Karate。当工程师端到端地掌控测试套件时,纯文本的 feature 文件和内置的 JSON 匹配功能将发挥巨大的威力。

如果测试编写人员包括 QA 和产品人员,或者你希望将测试与现有的设计和文档工作流相结合,又或者你不想为了运行 API 检查而维护 Java 构建,请选择像 Apifox 这样的无代码工具。你仍然可以通过 CLI 获得 CI 覆盖率。

一些团队会两者结合使用:Karate 用于深度、以代码为核心的回归测试套件,而可视化工具则用于非开发人员也可以扩展的广泛、快速的测试覆盖。如果你仍在权衡选择,我们关于如何选择 API 自动化测试框架的概述阐述了决策标准。

FAQ

使用 Karate 需要懂 Java 吗? 不需要,编写基础的 API 测试不需要懂 Java。Feature 文件使用 Gherkin DSL,且 Karate 内置了 HTTP 和断言步骤。你需要安装 Java 来运行测试,而如果你需要自定义辅助函数或进行复杂的复用,了解一些 Java 或 JavaScript 会很有帮助。

Karate 和 Cucumber 有什么区别? 两者都使用 Gherkin 的 Given/When/Then 语法。在 Cucumber 中,你需要编写步骤定义代码来支持每个步骤的执行。而 Karate 已经为你提供了 API 测试步骤,因此对于标准的 HTTP 测试,你无需维护任何粘合代码。

Karate 可以在没有 Maven 或 Gradle 的情况下运行吗? 可以。从项目的 Release 页面下载独立的 karate.jar,然后使用 java -jar karate.jar <path> 运行 feature 文件。它支持标签、并行线程以及自定义输出目录,无需任何构建工具。

#string#[10] 语法是什么意思? 这些是 Karate 的模糊匹配器(fuzzy matchers)。#string 断言某个字段是任意值的字符串,#number 断言其为数字,而 #[10] 则断言其为一个长度为 10 的 JSON 数组。它们允许你在不硬编码生成值的情况下校验响应的结构。

无代码的 API 测试还可以在 CI 中运行吗? 可以。像 Apifox 这样的可视化工具可以将保存的测试场景导出到 Apifox CLI,它是无头(headless)的,可以在任何运行 Node 的 CI 步骤中执行。因此,你可以在 UI 中编写测试,但仍然可以进行自动化的流水线运行。

开发必备:API 全流程管理神器 Apifox

介绍完上文的内容,我想额外介绍一个对开发者同样重要的效率工具 —— Apifox。作为一个集 API 文档、调试、设计、测试、Mock、自动化测试于一体的工具,Apifox 是目前提升研发效率的首选。

如果你正在开发项目,不妨试试其极其友好的界面设计,它完全兼容 Postman 和 Swagger 数据格式,导入数据非常方便,,即使是新手也能很快上手,点击这里即可注册使用

Apifox

值得一提的是,除了个人和常规团队使用,针对有高安全合规要求、或需要在内网环境协作的企业,Apifox 还提供了深度定制的私有化部署方案

获取专属报价与部署方案

icon 详细的私有化部署系统架构与安全白皮书
icon 针对您公司规模的专属报价单
icon 免费的 1v1 专属产品演示 (Demo) 机会
获取部署方案
* 提交后,我们的客户经理将在 1 个工作日内与您联系
林俊锋 企业微信
@Apifox 专属顾问
扫码备注: 私有化 + 公司名