测试最佳实践 (Dialogflow)

为 Actions on Google 平台开发 Action 通常需要 实现 Dialogflow 进行自然语言理解 (NLU) 和 Dialogflow 执行方式(可处理 Action 的逻辑)。 在代码库中包含测试有助于确保 Action 按预期执行 。

为 Action 实现单元测试、集成测试或端到端测试时, 应将 Dialogflow 代理和 fulfillment 视为单独的组件。

流程图从用户查询推进到 Actions on Google、Dialogflow
和 fulfillment webhook,最终返回给用户。

图 1. 流程图,说明测试时应考虑的系统

测试 Dialogflow 代理

Dialogflow 代理和 fulfillment 作为单独的组件进行测试。通过 以下小节介绍了如何概念化和测试 Dialogflow 为你的 Action 创建代理。

使用 Dialogflow 作为查询进入和意图输出系统

Dialogflow 代理负责获取用户的查询,并将其与 以及从查询中提取任何预定义的实体。您的代理 与您的执行方式进行交互,方法是传递一条包含匹配的 intent 及其参数以及 Actions on Google 元数据。

作为开发者,您可以控制 Dialogflow 代理的配置,例如 intent 和实体的结构。Actions on Google 元数据的来源 Actions on Google,可以假定包含用于测试的正确数据。

测试时,应专注于使代理能够正确提取意图 参数以及与意图匹配的查询。通过这种方法, 用于评估代理性能的可量化指标。您可以 通过准备和使用单个测试用例或 验证集。

Dialogflow 代理可以用文本查询作为输入和
意图以及提取的意图参数作为输出。

图 2. 将 Dialogflow 表示为查询输入和意图输出系统

单元测试

对于 Dialogflow 代理,您可以编写测试,其中每个用例都预计会有文本 查询作为输入,并生成 intent 元数据作为输出。此元数据 应(至少)包含匹配意图的名称和匹配列表 参数。

Dialogflow API 的 detectIntent 端点 将文本查询作为输入,并生成包含 已解析 intent 的名称和提取的参数。此输出结果非常有用 用于评估代理的意图匹配性能。有关 其他实用字段的参考文档,请参阅 QueryResult 参考文档

测试示例如下所示:

it('choose_fact', async function() {
  // The `dialogflow` variable is an abstraction around the API that creates
  // and sends payloads to Dialogflow.
  const resJson = await dialogflow.detectIntent(
    'Tell me about the history of Google');
  expect(resJson.queryResult).to.include.deep.keys('parameters');
  // Check that Dialogflow extracted required entities from the query.
  expect(resJson.queryResult.parameters).to.deep.equal({
    'category': 'history',
    // Put any other parameters you wish were extracted
  });
  expect(resJson.queryResult.intent.displayName).to.equal('choose_fact');
});

此代码段使用 MochaChai。查看完整说明 使用 Node.js 编写的 Dialogflow 单元测试 关于 Google 的信息

您的测试文件可以并行运行,因为 Dialogflow API 接受 sessionId 作为参数。因此,您可以使用单独的沙盒 每次对话时,只需使用一个 Dialogflow API 客户端即可。

由于您是在针对 Dialogflow API 发出请求,因此可能会产生 。请参阅配额和限制

集成测试

Dialogflow API 的 detectIntent 端点 触发第三方执行方式。因此,您可以编写 ,其中涵盖了 Dialogflow 代理与 Dialogflow 之间的集成 fulfillment。

为 Dialogflow 编写集成和单元测试的主要区别在于 在集成测试中,您可以断言来自网络钩子的响应 以及 Dialogflow 意图和实体提取。

如需查看以 Node.js 编写的集成测试的完整有效示例,请访问 Google 相关信息存储库。

测试 Dialogflow fulfillment 网络钩子

Dialogflow 代理和 Dialogflow fulfillment 作为单独的测试 组件。以下各小节介绍了如何理解和 测试执行方式。

作为 JSON 输入和 JSON 输出系统的 Fulfillment

您的 Dialogflow fulfillment 代码需要请求并在 JSON 格式。因此,您可以考虑以下方法来测试 fulfillment 代码: 以 JSON-in 和 JSON-out 系统的形式提供该请求包含来自 Dialogflow 和 Actions on Google,让它具备触发 特定的 intent 处理程序。

要测试 intent 处理程序的触发,请将 JSON 请求(输入)发送到 您的 Action。该请求会传递给你的执行方式,该执行方式可在 互联网。然后,fulfillment 会生成 JSON 响应(输出),该响应 进行验证。

执行方式可以用 JSON 请求输入和 webhook JSON 表示
响应输出。

图 3. 将 fulfillment 表示为 JSON-in 和 JSON-out 系统

单元测试

可以将 fulfillment webhook 代码视为一个接受 JSON 输入和 会生成 JSON 输出。Action 的测试过程随后可简化为 向您的执行方式提供请求并检查生成的输出 JSON。

这样,您就可以自由在本地托管执行方式并发送 HTTP 用于测试。如果您使用的是 Actions on Google Node.js 客户端库,也可以直接将 JSON 请求发送到客户端库 中间件层。

如果您使用 JSON 输入测试网络钩子代码并收到预期的 JSON 那么您就可以有把握地说, 受您控制的部分 才能正常运行。您可以假设 Dialogflow 和 Actions on Google 运行正常 因为它们会生成正确的 JSON 载荷。这种隔离 提供了一种简化的编程模型来编写测试。

以下是测试过程的概要:

  1. 使用 Actions 控制台中的模拟器获取 应用场景中的每个步骤请将这些内容保存为 JSON 文件。或者,您也可以 利用 网络钩子参考文档
  2. 编写测试以使用这些载荷调用 webhook。
  3. 对于每个测试,请确保响应 JSON 包含所需的商品。

此外,您还可以使用此模型在 持续集成设置,因为 fulfillment 端点可以在本地运行, Dialogflow API 内置了会话概念。

测试示例如下所示:

it('yes-history', function() {
  expect(jsonRes.payload).to.have.deep.keys('google');
  expect(jsonRes.payload.google.expectUserResponse).to.be.true;
  expect(jsonRes.payload.google.richResponse.items).to.have.lengthOf(3);
  expect(jsonRes.payload.google.richResponse.suggestions).to.have
    .deep.members([
      {'title': 'Sure'}, {'title': 'No thanks'},
    ]);
});

以上代码段使用 MochaChai。请参阅 在关于 Google 的事实中以 Node.js 编写的完整有效示例 存储库

设计可进行单元测试的执行方式

网络钩子代码通常包含应用所依赖的自定义业务逻辑 以满足其需求此外,webhook 代码还可以包含 处理程序。

为了改进执行方式代码的单元测试的粒度,最好 按照一定的业务逻辑 与 intent 处理例程分离。这意味着,拥有 intent 处理程序的 和业务逻辑分别位于不同的模块中 相互独立。

如需查看示例,请参阅 GitHub 上的 shiritori 示例操作。 在该示例中,functions/index.jsfunctions/shiritori/*.js 分别位于 包含 intent 处理程序和业务逻辑,以便进行更可靠的测试 套件。

集成测试

适用于编写涵盖 Dialogflow 与 fulfillment 网络钩子代码,请参阅 Dialogflow 的集成测试部分

负载测试

在将 Action 部署到生产环境之前,我们还建议对你的 webhook 执行方式来显示导致降级或 履单服务发生中断

下面列举了一些示例来说明您可能会在负载测试中发现的性能问题:

  • 计算资源和内存有限
  • 提供商的配额限制
  • 数据读写速度缓慢
  • 代码中的并发问题

负载测试场景取决于 您的 Action,但要测试的典型场景是负载突然增加(峰值) 和持续负载(过渡)

确定在哪些场景下调用 webhook 并执行 资源密集型操作典型的资源密集型操作包括 查询数据库、调用其他 API、执行计算和内存 密集型操作,例如渲染声音文件。

对于这些场景,您可以捕获 Actions on Google 服务器发送的请求 从 webhook 日志或 Stackdriver 日志发送到 webhook。您还可以 来自 Actions 控制台模拟器的捕获请求。

获得请求后,您可以使用负载测试工具来了解 webhook 在不同负载测试场景中做出响应。以下 小节提供了一些使用 ApacheBench

峰值测试

高峰测试要求您向 webhook 发送恒定数量的请求 然后负载突然增加例如,您可以设置 每秒 10 次查询 (QPS) 的负载达到 60 QPS 的峰值。

您可以运行以下 ApacheBench 命令来发送 60 个并发请求 添加到您的网络钩子:

ab -n 60 -c 60 -p ActionRequest.json -T 'application/json' https://example.com/webhookFunctionName

假设 ActionRequest.json 文件包含发送的已捕获请求载荷 添加到网络钩子。

浸泡测试

渗透测试要求您向 webhook 发送一定数量的请求 并观察响应。例如,您可以设置一项测试 持续数分钟的恒定负载(10-20 QPS) 增加。

您可以运行以下 ApacheBench 命令来发送 1200 个请求 每秒并发请求数:

ab -t 120 -n 1200 -p ActionRequest.json -T 'application/json' https://example.com/webhookFunctionName

假设 ActionRequest.json 文件包含发送的已捕获请求载荷 添加到网络钩子。

分析负载测试结果

运行负载测试后,分析 webhook 响应时间的结果。 网络钩子实现中问题的指示通常是趋势,例如 响应时间中位数随每次测试运行而增加,或在最坏情况下增加 您的 Action 无法接受的响应时间。

端到端测试

在提交你的 Action 以供审批之前进行端到端测试,方法是使用 Actions 控制台模拟器。您可以在这里找到 通过 Actions 模拟器中的 Actions 控制台模拟器进行测试 文档。执行这些测试有助于消除潜在的不确定性 Actions on Google 基础架构组件。