

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用适用于 AWS IoT Greengrass V2 的 AWS IoT Device Tester
<a name="device-tester-for-greengrass-ug"></a>

AWS IoT Device Tester (IDT) 是一个可下载的测试框架，可供您用于验证 IoT 设备。您可以使用 IDT for AWS IoT Greengrass 来运行 AWS IoT Greengrass 资格认证套件，并为您的设备创建和运行自定义测试套件。

IDT for AWS IoT Greengrass 在连接到要测试的设备的主机（Windows、macOS 或 Linux）上运行。它运行测试并聚合结果。它还提供命令行界面来管理测试过程。

## AWS IoT Greengrass 资格认证套件
<a name="gg-qual-suite"></a>

使用适用于 AWS IoT Greengrass V2 的 AWS IoT Device Tester 来验证 AWS IoT Greengrass Core 软件是否能在您的硬件上运行并与 AWS 云 通信。它还使用 AWS IoT Core 执行端到端测试。例如，其将验证您的设备能否部署组件并进行升级。

如果要将硬件添加到 AWS Partner 设备目录中，请运行 AWS IoT Greengrass 资格套件以生成可以提交到 AWS IoT 的测试报告。有关更多信息，请参阅 [AWS 设备资格认证计划](https://aws.amazon.com/partners/dqp/)。

![\[概述适用于 AWS IoT Greengrass V2 的 AWS IoT Device Tester 如何验证 AWS IoT Greengrass Core 软件是否能在您的硬件上运行并与 AWS 云 通信。\]](http://docs.aws.amazon.com/zh_cn/greengrass/v2/developerguide/images/devicetester_gg.png)


IDT for AWS IoT Greengrass V2 使用*测试套件*和*测试组*的概念来组织测试。<a name="idt-test-suites-groups"></a>
+ 测试套件是一组测试组，用于验证设备运行的是否为特定版本的 AWS IoT Greengrass。
+ 测试组是与特定功能相关的一组单独测试，例如组件部署。

 有关更多信息，请参阅 [使用 IDT 运行 AWS IoT Greengrass 资格套件](idt-greengrass-qualification.md)。

## 自定义测试套件
<a name="custom-test-suite"></a>

<a name="idt-byotc"></a>自 IDT v4.0.1 起，IDT for AWS IoT Greengrass V2 将标准化配置设置和结果格式与测试套件环境相结合，使您可以针对设备和设备软件开发自定义测试套件。您可以添加自定义测试来用于自己的内部验证，也可以将其提供给客户进行设备验证。

测试编写者如何配置自定义测试套件决定了运行自定义测试套件需要的设置配置。有关更多信息，请参阅 [使用 IDT 开发和运行自己的测试套件](idt-custom-tests.md)。

# 支持的 f AWS IoT Device Tester or AWS IoT Greengrass V2 版本
<a name="dev-test-versions"></a>

本主题列出了 AWS IoT Greengrass V2 版 IDT 支持的版本。作为最佳实践，我们建议您使用支持目标版本 AWS IoT Greengrass V2 的最新版本 IDT for V2。 AWS IoT Greengrass 的新版本 AWS IoT Greengrass 可能需要您下载适用于 AWS IoT Greengrass V2 的 IDT 的新版本。如果 IDT for AWS IoT Greengrass V2 与您正在使用的版本不兼容，则在开始测试运行时 AWS IoT Greengrass 会收到通知。

下载此软件即表示您同意 [AWS IoT Device Tester 许可协议](https://docs.aws.amazon.com/greengrass/v2/developerguide/idt-license.html)。

**注意**  
<a name="unzip-package-to-local-drive"></a>IDT 不支持由多个用户从共享位置（如 NFS 目录或 Windows 网络共享文件夹）运行。建议您将 IDT 包解压缩到本地驱动器，并在本地工作站上运行 IDT 二进制文件。

## 适用 AWS IoT Greengrass 于 V2 的最新 IDT 版本
<a name="idt-latest-version"></a>

您可以将此版本的 IDT for AWS IoT Greengrass V2 与此处列出的 AWS IoT Greengrass 版本一起使用。<a name="idt-latest-version.options"></a>

**IDT v4.9.4 适用于 AWS IoT Greengrass**    
支持的 AWS IoT Greengrass 版本：  
+ [Greengrass Nucleus](greengrass-nucleus-component.md) v2.12.0、v2.11.0、v2.10.0 和 v2.9.5  
IDT 软件下载：  
+ [带适用于 Linux 的测试套件 Q\$12.5.4 的 IDT v4.9.4 GGV2](https://docs.aws.amazon.com/greengrass/v2/developerguide/devicetester_greengrass_v2_4.9.4_testsuite_2.5.4_linux.zip)
+ [带有适用于 macOS 的测试套件 Q\$12.5.4 的 IDT v4.9.4 GGV2](https://docs.aws.amazon.com/greengrass/v2/developerguide/devicetester_greengrass_v2_4.9.4_testsuite_2.5.4_mac.zip)
+ [带适用于 Windows 的测试套件 Q\$12.5.4 的 IDT v4.9.4 GGV2](https://docs.aws.amazon.com/greengrass/v2/developerguide/devicetester_greengrass_v2_4.9.4_testsuite_2.5.4_win.zip)  
发行说明：  
+ 为运行 AWS IoT Greengrass 酷睿软件版本 2.12.0、2.11.0、2.10.0 和 2.9.5 的设备启用设备验证和资格认证。
+ 移除流管理器和机器学习测试组。  
附加注释：  
+ 如果您的设备使用 HSM，而您使用的是 Nucleus 2.10.x，请迁移至 Greengrass Nucleus 版本 2.11.0 或更高版本。  
测试套件版本：    
`GGV2Q_2.5.4`  
+ 发行时间：2024 年 5 月 3 日

## 较早的 IDT 版本适用于 AWS IoT Greengrass
<a name="idt-earlier-versions"></a>

还支持以下适用于 AWS IoT Greengrass V2 的 IDT 的早期版本。<a name="idt-earlier-version.options"></a>

**IDT v4.9.3 适用于 AWS IoT Greengrass**    
支持的 AWS IoT Greengrass 版本：  
+ [Greengrass Nucleus](greengrass-nucleus-component.md) v2.12.0、v2.11.0、v2.10.0 和 v2.9.5  
IDT 软件下载：  
+ [IDT v4.9.3 带适用于 Linux 的测试套件 Q\$12.5.3 GGV2](https://docs.aws.amazon.com/greengrass/v2/developerguide/devicetester_greengrass_v2_4.9.3_testsuite_2.5.3_linux.zip)
+ [带有适用于 macOS 的测试套件 Q\$12.5.3 的 IDT v4.9.3 GGV2](https://docs.aws.amazon.com/greengrass/v2/developerguide/devicetester_greengrass_v2_4.9.3_testsuite_2.5.3_mac.zip)
+ [IDT v4.9.3 带适用于 Windows 的测试套件 Q\$12.5.3 GGV2](https://docs.aws.amazon.com/greengrass/v2/developerguide/devicetester_greengrass_v2_4.9.3_testsuite_2.5.3_win.zip)  
发行说明：  
+ 修复了从 Windows 主机测试 Linux 设备（反之亦然）时组件测试中的一个问题。
+ 从 `localcomponent` 测试组中移除 `component` 测试用例。该测试用例不再需要进行资格认证。  
附加注释：  
+ 如果您的设备使用 HSM，而您使用的是 Nucleus 2.10.x，请迁移至 Greengrass Nucleus 版本 2.11.0 或更高版本。  
测试套件版本：    
`GGV2Q_2.5.3`  
+ 发行时间：2024 年 4 月 5 日

## 不支持的 for V2 AWS IoT Device Tester 版本 AWS IoT Greengrass
<a name="idt-unsupported-versions"></a>

本主题列出了不支持的 V2 版 IDT 版本。 AWS IoT Greengrass 不受支持的版本不会收到错误修复或更新。有关更多信息，请参阅 [适用于 AWS IoT Device Tester 的 AWS IoT Greengrass 的支持策略](idt-support-policy.md)。

**IDT v4.9.2 适用于 AWS IoT Greengrass**    
发行说明：  
+ 修复了由于 Java 8 被弃用而导致 Lambda 测试套件失败的问题。  
测试套件版本：    
`GGV2Q_2.5.2`  
+ 发行时间：2024 年 3 月 18 日

**IDT v4.9.1 适用于 AWS IoT Greengrass**    
发行说明：  
+ 允许您验证和鉴定运行 AWS IoT Greengrass Core 软件版本 2.12.0、2.11.0、2.10.0 和 2.9.5 的设备。
+ 次要错误修复。  
测试套件版本：    
`GGV2Q_2.5.1`  
+ 发行时间：2023 年 10 月 5 日

**IDT v4.7.0 适用于 AWS IoT Greengrass**    
支持的 AWS IoT Greengrass 版本：  
+ [Greengrass Nucleus](greengrass-nucleus-component.md) v2.11.0、v2.10.0 和 v2.9.5  
发行说明：  
+ 允许您验证和鉴定运行 AWS IoT Greengrass Core 软件版本 2.11.0、2.10.0 和 2.9.5 的设备。
+ 增加了对在 AWS Systems Manager Parameter Store 中存储 IDT 用户数据值的支持，并使用占位符语法将其提取到配置中。
+ 次要错误修复。  
测试套件版本：    
`GGV2Q_2.5.0`  
+ 发行时间：2022 年 12 月 13 日

**IDT v4.5.11 适用于 AWS IoT Greengrass**    
发行说明：  
+ 允许您验证和鉴定运行 AWS IoT Greengrass Core 软件版本 2.9.1、2.9.0、2.8.1、2.8.0、2.7.0 和 2.6.0 的设备。
+ 增加了对在核心设备上测试 PreInstalled Greengrass 的支持。
+ 次要错误修复。  
测试套件版本：    
`GGV2Q_2.4.1`  
+ 发行时间：2022 年 10 月 13 日

**IDT v4.5.8 适用于 AWS IoT Greengrass**    
发行说明：  
+ 允许您验证和鉴定运行 AWS IoT Greengrass Core 软件版本 2.7.0、2.6.0 和 2.5.6 的设备。
+ 使您能够在核心设备上使用 PreInstalled Greengrass 进行测试。
+ 次要错误修复。  
测试套件版本：    
`GGV2Q_2.4.0`  
+ 发行时间：2022 年 8 月 12 日

**IDT v4.5.3 适用于 AWS IoT Greengrass**    
发行说明：  
+ 允许您验证和鉴定运行 AWS IoT Greengrass Core 软件版本 2.7.0、2.6.0、2.5.6、2.5.5、2.5.4 和 2.5.3 的设备。
+ 更新 DockerApplicationManager 测试以使用基于 ECR 的 docker 镜像。
+ 次要错误修复。  
测试套件版本：    
`GGV2Q_2.3.1`  
+ 发行时间：2022 年 4 月 15 日

**IDT v4.5.1 适用于 AWS IoT Greengrass**    
发行说明：  
+ 允许您验证和鉴定运行 AWS IoT Greengrass Core 软件版本 2.5.3 的设备。
+ 增加了对验证和鉴定基于 Linux 的设备的支持，这些设备使用硬件安全模块（HSM）来存储 AWS IoT Greengrass Core 软件使用的私钥和证书。
+ 实现用于配置自定义测试套件的新 IDT 测试编排工具。有关更多信息，请参阅 [配置 IDT 测试编排工具](idt-test-orchestrator.md)。
+ 其他次要错误修复。  
测试套件版本：    
`GGV2Q_2.3.0`  
+ 发行时间：2022 年 1 月 11 日

**IDT v4.4.1 适用于 AWS IoT Greengrass**    
发行说明：  
+ 允许您验证和鉴定运行 AWS IoT Greengrass Core 软件版本 2.5.2 的设备。
+ 增加了对使用用户定义的 IAM 角色作为被测设备假设的与 AWS 资源交互的令牌交换角色的支持。

  您可以在 [`userdata.json` 文件](set-config.md#userdata-config)中指定 IAM 角色。如果您指定自定义角色，IDT 将在测试运行期间使用该角色而非创建默认的令牌交换角色。
+ 其他次要错误修复。  
测试套件版本：    
`GGV2Q_2.2.1`  
+ 发行时间：2021 年 12 月 12 日

**IDT v4.4.0 适用于 AWS IoT Greengrass**    
发行说明：  
+ 允许您验证和鉴定运行 AWS IoT Greengrass Core 软件版本 2.5.0 的设备。
+ 增加了对在 Windows 上运行 AWS IoT Greengrass 酷睿软件的设备进行验证和认证的支持。
+ 支持使用公钥验证进行 Secure Shell（SSH）设备连接。
+ 利用安全最佳实践改进 IDT 权限 IAM 策略。
+ 其他次要错误修复。  
测试套件版本：    
`GGV2Q_2.1.0`  
+ 发行时间：2021 年 11 月 19 日

**IDT v4.2.0 适用于 AWS IoT Greengrass**    
发行说明：  
+ 包括支持在运行 C AWS IoT Greengrass ore 软件 v2.2.0 及更高版本的设备上认证以下功能：
  + Docker – 验证设备是否可以从 Amazon Elastic Container Registry（Amazon ECR）中下载 Docker 容器映像。
  + [机器学习-验证设备是否可以使用[深度学习运行时或 Lite ML 框架执行机器学习](https://github.com/neo-ai/neo-ai-dlr) (ML) 推理。TensorFlow ](https://www.tensorflow.org/lite/guide/python)
  + 流管理器-验证设备是否可以下载、安装和运行流管理器。 AWS IoT Greengrass 
+ 允许您验证和鉴定运行 AWS IoT Greengrass Core 软件版本 2.4.0、2.3.0、2.2.0 和 2.1.0 的设备。
+ 将每个测试用例的测试日志分组到`<device-tester-extract-location>/results/<execution-id>/logs/<test-group-id>`目录内的单独*<test-case-id>*文件夹中。
+ 其他次要错误修复。  
测试套件版本：    
`GGV2Q_2.0.1`  
+ 发行时间：2021 年 8 月 31 日

**IDT v4.1.0 适用于 AWS IoT Greengrass**    
发行说明：  
+ 允许您验证和鉴定运行 AWS IoT Greengrass Core 软件版本 2.3.0、2.2.0、2.1.0 和 2.0.5 的设备。
+ 通过删除指定 `GreengrassNucleusVersion` 和 `GreengrassCLIVersion` 属性的要求来改进 `userdata.json` 配置。
+ 包括对 AWS IoT Greengrass 核心软件 v2.1.0 及更高版本的 Lambda 和 MQTT 功能认证的支持。现在，您可以使用适用于 AWS IoT Greengrass V2 的 IDT 来验证您的核心设备是否可以运行 Lambda 函数，以及该设备是否可以发布和订阅 MQTT 主题。 AWS IoT Core 
+ 改进日志记录功能。
+ 其他次要错误修复。  
测试套件版本：    
`GGV2Q_1.1.1`  
+ 发行时间：2021 年 6 月 18 日

**IDT v4.0.2 适用于 AWS IoT Greengrass**    
发行说明：  
+ 允许您验证和鉴定运行 AWS IoT Greengrass Core 软件版本 2.1.0 的设备。
+ 增加了对 AWS IoT Greengrass 核心软件 v2.1.0 及更高版本的 Lambda 和 MQTT 功能认证的支持。现在，您可以使用适用于 AWS IoT Greengrass V2 的 IDT 来验证您的核心设备是否可以运行 Lambda 函数，以及该设备是否可以发布和订阅 MQTT 主题。 AWS IoT Core 
+ 改进日志记录功能。
+ 其他次要错误修复。  
测试套件版本：    
`GGV2Q_1.1.1`  
+ 发行时间：2021 年 5 月 5 日

**IDT v4.0.1 适用于 AWS IoT Greengrass**    
发行说明：  
+ 允许您验证和鉴定运行 AWS IoT Greengrass 版本 2 软件的设备。
+ 使您可以使用 f AWS IoT Device Tester or 开发和运行自定义测试套件 AWS IoT Greengrass。有关更多信息，请参阅 [使用 IDT 开发和运行自己的测试套件](idt-custom-tests.md)。
+ 提供适用于 macOS 和 Windows 的代码签名 IDT 应用程序。在 macOS 上，您可能需要为 IDT 授予安全例外。有关更多信息，请参阅 [macOS 上的安全例外](idt-troubleshooting.md#security-exception-macos)。  
测试套件版本：    
`GGV2Q_1.0.0`  
+ 发行时间：2020 年 12 月 22 日
+ 除非将 `features` 数组中的相应 `value` 设置为 `yes`，否则测试套件仅运行资格认证所需测试。

# 下载 IDT for AWS IoT Greengrass V2
<a name="idt-programmatic-download"></a>

本主题介绍下载适用于 AWS IoT Greengrass V2 的 AWS IoT Device Tester 的选项。您可以使用以下软件下载链接之一，也可以按照说明以编程方式下载 IDT。

**Topics**
+ [

## 手动下载 IDT
](#idt-download-options)
+ [

## 以编程方式下载 IDT
](#idt-programmatic-download-process)

下载此软件即表示您同意 [AWS IoT Device Tester 许可协议](https://docs.aws.amazon.com/greengrass/v2/developerguide/idt-license.html)。

**注意**  
<a name="unzip-package-to-local-drive"></a>IDT 不支持由多个用户从共享位置（如 NFS 目录或 Windows 网络共享文件夹）运行。建议您将 IDT 包解压缩到本地驱动器，并在本地工作站上运行 IDT 二进制文件。

## 手动下载 IDT
<a name="idt-download-options"></a>

本主题列出了支持的 IDT for AWS IoT Greengrass V2 版本。作为最佳做法，我们建议您使用支持目标 AWS IoT Greengrass V2 版本的 IDT for AWS IoT Greengrass V2 最新版本。新版本的 AWS IoT Greengrass 可能要求您下载新版本的 IDT for AWS IoT Greengrass V2。如果 IDT for AWS IoT Greengrass V2 与您使用的 AWS IoT Greengrass 版本不兼容，则您在开始测试运行时会收到通知。

  <a name="idt-latest-version.options"></a>  
**适用于 AWS IoT Greengrass 的 IDT v4.9.4**    
支持的 AWS IoT Greengrass 版本：  
+ [Greengrass Nucleus](greengrass-nucleus-component.md) v2.12.0、v2.11.0、v2.10.0 和 v2.9.5  
IDT 软件下载：  
+ 适用于 [Linux](https://docs.aws.amazon.com/greengrass/v2/developerguide/devicetester_greengrass_v2_4.9.4_testsuite_2.5.4_linux.zip) 的带有测试套件 GGV2Q\$12.5.4 的 IDT v4.9.4
+ 适用于 [macOS](https://docs.aws.amazon.com/greengrass/v2/developerguide/devicetester_greengrass_v2_4.9.4_testsuite_2.5.4_mac.zip) 的带有测试套件 GGV2Q\$12.5.4 的 IDT v4.9.4
+ 适用于 [Windows](https://docs.aws.amazon.com/greengrass/v2/developerguide/devicetester_greengrass_v2_4.9.4_testsuite_2.5.4_win.zip) 的带有测试套件 GGV2Q\$12.5.4 的 IDT v4.9.4  
发行说明：  
+ 允许对运行 AWS IoT Greengrass Core 软件版本 2.12.0、2.11.0、2.10.0 和 2.9.5 的设备进行验证和资格认证。
+ 移除流管理器和机器学习测试组。  
附加注释：  
+ 如果您的设备使用 HSM，而您使用的是 Nucleus 2.10.x，请迁移至 Greengrass Nucleus 版本 2.11.0 或更高版本。  
测试套件版本：    
`GGV2Q_2.5.4`  
+ 发行时间：2024 年 5 月 3 日

## 以编程方式下载 IDT
<a name="idt-programmatic-download-process"></a>

IDT 提供了一个 API 操作，您可以使用该操作来检索 URL，也可以在其中以编程方式下载 IDT。您还可以使用此 API 操作来检查是否具有最新版本的 IDT。此 API 操作具有以下端点。

```
https://download.devicetester.iotdevicesecosystem.amazonaws.com/latestidt
```

要调用此 API 操作，您必须具有执行 **iot-device-tester:LatestIdt** 操作的权限。包括您的 AWS 签名，并使用 `iot-device-tester` 作为服务名称。

### API 请求
<a name="idt-programmatic-download-request"></a>

HostOS - 主机的操作系统。从以下选项中进行选择：  
+ `mac`
+ `linux`
+ `windows`

TestSuiteType – 测试套件的类型。选择以下选项：  
`GGV2` – IDT for AWS IoT Greengrass V2

ProductVersion  
（可选）Greengrass Nucleus 的版本。该服务返回适用于该 Greengrass Nucleus 版本的 IDT 的最新兼容版本。如果不指定此选项，则该服务将返回 IDT 的最新版本。

### API 响应
<a name="idt-programmatic-download-response"></a>

API 响应采用以下格式。`DownloadURL` 包括一个 zip 文件。

```
{
    "Success": True or False,
    "Message": Message,
    "LatestBk": {
        "Version": The version of the IDT binary,
        "TestSuiteVersion": The version of the test suite,
        "DownloadURL": The URL to download the IDT Bundle, valid for one hour
    }
 }
```

### 示例
<a name="idt-programmatic-download-examples"></a>

您可以参考以下示例以编程方式下载 IDT。这些示例使用您在 `AWS_ACCESS_KEY_ID` 和 `AWS_SECRET_ACCESS_KEY` 环境变量中存储的凭证。要遵循最佳安全实践，请勿在代码中存储您的凭证。

**Example 示例：使用 cURL 版本 7.75.0 或更高版本下载（Mac 和 Linux）**  
如果您的 cURL 版本为 7.75.0 或更高版本，则可以使用 `aws-sigv4` 标记对 API 请求进行签名。该示例使用 [jq](https://stedolan.github.io/jq/) 来解析响应中的下载 URL。  
`aws-sigv4` 标志要求 curl GET 请求的查询参数按照 **HostOs/ProductVersion/TestSuiteType** 或 **HostOs/TestSuiteType** 的顺序排列。如果参数顺序不符合要求，则会导致从 API Gateway 获得不匹配的规范字符串签名错误。  
如果包含可选参数 **ProductVersion**，则必须使用支持的产品版本，如[支持的适用于 AWS IoT Greengrass V2 的 AWS IoT Device Tester 版本](dev-test-versions.md)。
+ 将 *us-west-2* 替换为您的 AWS 区域。有关区域代码的列表，请参阅[区域端点](https://docs.aws.amazon.com/general/latest/gr/rande.html)。
+ 将 *linux* 替换为主机的操作系统。
+ 将 *2.5.3* 替换为 AWS IoT Greengrass Nucleus 版本。

```
url=$(curl --request GET "https://download.devicetester.iotdevicesecosystem.amazonaws.com/latestidt?HostOs=linux&ProductVersion=2.5.3&TestSuiteType=GGV2" \
--user $AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY \
--aws-sigv4 "aws:amz:us-west-2:iot-device-tester" \
| jq -r '.LatestBk["DownloadURL"]')

curl $url --output devicetester.zip
```

**Example 示例：使用早期版本的 cURL 下载（Mac 和 Linux）**  
您可以将以下 curl 命令与您签名和计算的 AWS 签名一起使用。有关如何签名和计算 AWS 签名的更多信息，请参阅[签署 AWS API 请求](https://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html)。  
+ 将 *linux* 替换为主机的操作系统。
+ 将 *Timestamp* 替换为日期和时间，例如 **20220210T004606Z**。
+ 将 *Data* 替换为日期，例如 **20220210**。
+ 将 *AWSRegion* 替换为您的 AWS 区域。有关区域代码的列表，请参阅[区域端点](https://docs.aws.amazon.com/general/latest/gr/rande.html)。
+ 将 *AWSSignature* 替换为您生成的 [AWS 签名](https://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html)。

```
curl --location --request GET 'https://download.devicetester.iotdevicesecosystem.amazonaws.com/latestidt?HostOs=linux&TestSuiteType=GGV2' \
--header 'X-Amz-Date: Timestamp \
--header 'Authorization: AWS4-HMAC-SHA256 Credential=$AWS_ACCESS_KEY_ID/Date/AWSRegion/iot-device-tester/aws4_request, SignedHeaders=host;x-amz-date, Signature=AWSSignature'
```

**Example 示例：使用 Python 脚本下载**  
此示例使用 Python [请求](https://pypi.org/project/requests/)库。此示例改编自 *AWS 一般参考*中[用于签署 AWS API 请求](https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html)的 Python 示例。    
  
+ 将 *us-west-2* 替换为您的区域。有关区域代码的列表，请参阅[区域端点](https://docs.aws.amazon.com/general/latest/gr/rande.html)。
+ 将 *linux* 替换为主机的操作系统。

```
# Copyright 2010-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# This file is licensed under the Apache License, Version 2.0 (the "License").
# You may not use this file except in compliance with the License. A copy of the
#License is located at
#
# http://aws.amazon.com/apache2.0/
#
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
# OF ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.

# See: http://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
# This version makes a GET request and passes the signature
# in the Authorization header.
import sys, os, base64, datetime, hashlib, hmac 
import requests # pip install requests
# ************* REQUEST VALUES *************
method = 'GET'
service = 'iot-device-tester'
host = 'download.devicetester.iotdevicesecosystem.amazonaws.com'
region = 'us-west-2'
endpoint = 'https://download.devicetester.iotdevicesecosystem.amazonaws.com/latestidt'
request_parameters = 'HostOs=linux&TestSuiteType=GGV2'
            
# Key derivation functions. See:
# http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html#signature-v4-examples-python
def sign(key, msg):
    return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()

def getSignatureKey(key, dateStamp, regionName, serviceName):
    kDate = sign(('AWS4' + key).encode('utf-8'), dateStamp)
    kRegion = sign(kDate, regionName)
    kService = sign(kRegion, serviceName)
    kSigning = sign(kService, 'aws4_request')
    return kSigning
    
# Read AWS access key from env. variables or configuration file. Best practice is NOT
# to embed credentials in code.
access_key = os.environ.get('AWS_ACCESS_KEY_ID')
secret_key = os.environ.get('AWS_SECRET_ACCESS_KEY')
if access_key is None or secret_key is None:
    print('No access key is available.')
    sys.exit()
    
# Create a date for headers and the credential string
t = datetime.datetime.utcnow()
amzdate = t.strftime('%Y%m%dT%H%M%SZ')
datestamp = t.strftime('%Y%m%d') # Date w/o time, used in credential scope

# ************* TASK 1: CREATE A CANONICAL REQUEST *************
# http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
# Step 1 is to define the verb (GET, POST, etc.)--already done.
# Step 2: Create canonical URI--the part of the URI from domain to query 
# string (use '/' if no path)
canonical_uri = '/latestidt' 
# Step 3: Create the canonical query string. In this example (a GET request),
# request parameters are in the query string. Query string values must
# be URL-encoded (space=%20). The parameters must be sorted by name.
# For this example, the query string is pre-formatted in the request_parameters variable.
canonical_querystring = request_parameters
# Step 4: Create the canonical headers and signed headers. Header names
# must be trimmed and lowercase, and sorted in code point order from
# low to high. Note that there is a trailing \n.
canonical_headers = 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n'
# Step 5: Create the list of signed headers. This lists the headers
# in the canonical_headers list, delimited with ";" and in alpha order.
# Note: The request can include any headers; canonical_headers and
# signed_headers lists those that you want to be included in the 
# hash of the request. "Host" and "x-amz-date" are always required.
signed_headers = 'host;x-amz-date'
# Step 6: Create payload hash (hash of the request body content). For GET
# requests, the payload is an empty string ("").
payload_hash = hashlib.sha256(('').encode('utf-8')).hexdigest()
# Step 7: Combine elements to create canonical request
canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash

# ************* TASK 2: CREATE THE STRING TO SIGN*************
# Match the algorithm to the hashing algorithm you use, either SHA-1 or
# SHA-256 (recommended)
algorithm = 'AWS4-HMAC-SHA256'
credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request'
string_to_sign = algorithm + '\n' +  amzdate + '\n' +  credential_scope + '\n' +  hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()
# ************* TASK 3: CALCULATE THE SIGNATURE *************
# Create the signing key using the function defined above.
signing_key = getSignatureKey(secret_key, datestamp, region, service)
# Sign the string_to_sign using the signing_key
signature = hmac.new(signing_key, (string_to_sign).encode('utf-8'), hashlib.sha256).hexdigest()

# ************* TASK 4: ADD SIGNING INFORMATION TO THE REQUEST *************
# The signing information can be either in a query string value or in 
# a header named Authorization. This code shows how to use a header.
# Create authorization header and add to request headers
authorization_header = algorithm + ' ' + 'Credential=' + access_key + '/' + credential_scope + ', ' +  'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature
# The request can include any headers, but MUST include "host", "x-amz-date", 
# and (for this scenario) "Authorization". "host" and "x-amz-date" must
# be included in the canonical_headers and signed_headers, as noted
# earlier. Order here is not significant.
# Python note: The 'host' header is added automatically by the Python 'requests' library.
headers = {'x-amz-date':amzdate, 'Authorization':authorization_header}

# ************* SEND THE REQUEST *************
request_url = endpoint + '?' + canonical_querystring
print('\nBEGIN REQUEST++++++++++++++++++++++++++++++++++++')
print('Request URL = ' + request_url)
response = requests.get(request_url, headers=headers)
print('\nRESPONSE++++++++++++++++++++++++++++++++++++')
print('Response code: %d\n' % response.status_code)
print(response.text)

download_url = response.json()["LatestBk"]["DownloadURL"]
r = requests.get(download_url)
open('devicetester.zip', 'wb').write(r.content)
```

# 使用 IDT 运行 AWS IoT Greengrass 资格套件
<a name="idt-greengrass-qualification"></a>

您可以使用 AWS IoT Device Tester AWS IoT Greengrass V2 来验证 C AWS IoT Greengrass ore 软件是否在您的硬件上运行并且可以与通信。 AWS 云它还使用执行 end-to-end测试 AWS IoT Core。例如，其将验证您的设备能否部署组件并进行升级。

除了测试设备外，IDT f AWS IoT Greengrass or V2 还会在中创建资源（例如， AWS IoT 事物、群组等）， AWS 账户 以简化认证流程。

<a name="idt-aws-credentials"></a>要创建这些资源，适用于 AWS IoT Greengrass V2 的 IDT 使用`config.json`文件中配置的 AWS 凭据代表您进行 API 调用。这些资源将在测试过程的不同时间进行预置。

当您使用 IDT f AWS IoT Greengrass or V2 运行 AWS IoT Greengrass 资格套件时，它会执行以下步骤：

1. 加载和验证您的设备和凭证配置。

1. 使用所需的本地资源和云资源执行选定测试。

1. 清除本地资源和云资源。

1. 生成测试报告，指明您的主板是否已通过资格认证所需的测试。

## 测试套件版本
<a name="idt-test-suite-versions"></a>

IDT for AWS IoT Greengrass V2 将测试组织到测试套件和测试组中。<a name="idt-test-suites-groups"></a>
+ 测试套件是一组测试组，用于验证设备运行的是否为特定版本的 AWS IoT Greengrass。
+ 测试组是与特定功能相关的一组单独测试，例如组件部署。

测试套件使用 `major.minor.patch` 格式（例如 `GGV2Q_1.0.0`）进行版本控制。当您下载 IDT 时，数据包中包含最新的 Greengrass 资格认证套件版本。

**重要**  
不受支持的测试套件版本进行的测试对于设备资格认证无效。IDT 不会为不受支持的版本打印资格认证报告。有关更多信息，请参阅 [适用于 AWS IoT Device Tester 的 AWS IoT Greengrass 的支持策略](idt-support-policy.md)。  
您可以运行列`list-supported-products`出当前版本的 IDT 支持的版本 AWS IoT Greengrass 和测试套件。

## 测试组描述
<a name="dt-test-groups"></a>

**核心资格必备测试组**  
这些测试组必须使您的 AWS IoT Greengrass V2 设备符合 AWS Partner 设备目录的资格。    
Core 依赖关系  
验证设备是否满足 AWS IoT Greengrass Core 软件的所有软硬件要求。该测试组包括以下测试用例：    
Java 版本  
检查被测设备上是否安装了所需的 Java 版本。 AWS IoT Greengrass 需要 Java 8 或更高版本。  
PreTest 验证  
检查设备是否满足运行测试的软件要求。  
+ 对于基于 Linux 的设备，此测试将检查设备是否可以运行以下 Linux 命令：

  `chmod`, `cp`, `echo`, `grep`, `kill`, `ln`, `mkinfo`, `ps`, `rm`, `sh`, `uname` 
+ 对于基于 Windows 的设备，此测试会检查设备是否安装了以下 Microsoft 软件：

  [Powershell](https://learn.microsoft.com/en-us/powershell/?view=powershell-7.1) [v5.1 或更高版本、[.NET](https://learn.microsoft.com/en-us/dotnet/) v4.6.1 或更高版本、V [isual C\$1\$1](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170) 2017 或更高版本、实用 PsExec](https://learn.microsoft.com/en-us/sysinternals/downloads/psexec)  
版本检查程序  
检查所 AWS IoT Greengrass 提供的版本是否与您正在使用的 AWS IoT 设备测试器版本兼容。  
组件  
验证设备是否可以部署组件并对其进行升级。该测试组包括以下测试：    
云组件  
验证云组件的设备功能。  
本地组件  
验证本地组件的设备功能。  
Lambda  
此测试不适用于基于 Windows 的设备。  
验证设备是否可以部署使用 Java 运行时的 Lambda 函数组件，以及 Lambda 函数是否可以 AWS IoT Core 使用 MQTT 主题作为工作消息的事件源。  
MQTT  
验证设备是否可以订阅和发布 AWS IoT Core MQTT 主题。

**可选测试组**  
这些测试组是可选的，仅用于符合条件的基于 Linux 的 Greengrass 核心设备。如果您选择符合可选测试的资格，则您的设备将在 AWS Partner 设备目录中列出其他功能。  
Docker 依赖关系  
<a name="description-docker"></a>验证设备是否满足使用 AWS提供的 Docker 应用程序管理器 () `aws.greengrass.DockerApplicationManager` 组件所需的所有技术依赖项。  
Docker 应用程序管理器资格认证  
<a name="description-docker-app-manager-qual"></a>验证<a name="description-docker-app-manager-qual-phrase"></a>设备是否可以从 Amazon ECR 下载 Docker 容器镜像。  
机器学习依赖关系  
只有 IDT v4.9.3 支持机器学习可选测试组。
<a name="description-ml"></a>验证设备是否满足使用 AWS提供的机器学习 (ML) 组件所需的所有技术依赖项。  
机器学习推理测试  
只有 IDT v4.9.3 支持机器学习可选测试组。
<a name="description-ml-inference"></a><a name="description-ml-inference-phrase"></a>验证设备是否可以使用[深度学习运行时](https://github.com/neo-ai/neo-ai-dlr)和 L [TensorFlow ite](https://www.tensorflow.org/lite/guide/python) ML 框架执行 ML 推理。  
流管理器依赖关系  
只有 IDT v4.9.3 支持流管理器可选测试组。
<a name="description-sm"></a>验证设备是否可以下载、安装和运行 [AWS IoT Greengrass 流管理器](manage-data-streams.md)。  
硬件安全性集成 (HSI)  
该测试仅在 IDT v4.9.3 及更高版本中适用于基于 Linux 的设备。 AWS IoT Greengrass 目前不支持 Windows 设备的硬件安全集成。
<a name="description-hsi"></a>验证设备是否可以使用存储在硬件安全模块 (HSM) 中的私钥和证书对与和 AWS IoT Greengrass 服务的连接进行身份验证。 AWS IoT 该测试还验证了提供的 [PKCS \$111 AWS提供者组件是否可以使用供应商提供](pkcs11-provider-component.md)的 PKCS \$111 库与 HSM 接口。有关更多信息，请参阅 [硬件安全性集成](hardware-security.md)。

# 运行 AWS IoT Greengrass 资格套件的先决条件
<a name="dev-tst-prereqs"></a>

本节介绍使用 AWS IoT Device Tester (IDT) 的先决条件。 AWS IoT Greengrass

## 下载 for 的最新版本 AWS IoT Device Tester AWS IoT Greengrass
<a name="install-dev-tst-gg"></a>

下载[最新版本的](idt-programmatic-download.md) IDT 并将该软件解压缩到文件系统上您拥有读/写权限的位置 (*<device-tester-extract-location>*)。

**注意**  
<a name="unzip-package-to-local-drive"></a>IDT 不支持由多个用户从共享位置（如 NFS 目录或 Windows 网络共享文件夹）运行。建议您将 IDT 包解压缩到本地驱动器，并在本地工作站上运行 IDT 二进制文件。  
Windows 的路径长度限制为 260 个字符。如果您使用的是 Windows，请将 IDT 提取到根目录（如 `C:\ ` 或 `D:\`）以使路径长度不超过 260 个字符的限制。

## 下载该 AWS IoT Greengrass 软件
<a name="config-gg"></a>

IDT fo AWS IoT Greengrass r V2 会测试您的设备是否与特定版本的兼容。 AWS IoT Greengrass运行以下命令将 AWS IoT Greengrass Core 软件下载到名为的文件中`aws.greengrass.nucleus.zip`。*version*替换为您的 IDT 版本[支持的 nucleus 组件版本](dev-test-versions.md)。

------
#### [ Linux or Unix ]

```
curl -s https://d2s8p88vqu9w66.cloudfront.net/releases/greengrass-version.zip > aws.greengrass.nucleus.zip
```

------
#### [ Windows Command Prompt (CMD) ]

```
curl -s https://d2s8p88vqu9w66.cloudfront.net/releases/greengrass-version.zip > aws.greengrass.nucleus.zip
```

------
#### [ PowerShell ]

```
iwr -Uri https://d2s8p88vqu9w66.cloudfront.net/releases/greengrass-version.zip -OutFile aws.greengrass.nucleus.zip
```

------

将下载的 `aws.greengrass.nucleus.zip` 文件放在 `<device-tester-extract-location>/products/` 文件夹中。

**注意**  
对于相同的操作系统和架构，请勿在此目录中放置多个文件。

## 创建和配置 AWS 账户
<a name="config-aws-account-for-idt"></a>

在 AWS IoT Greengrass V2 中使用 AWS IoT Device Tester 之前，必须执行以下步骤：

1. [设置一个 AWS 账户.](#create-aws-account-for-idt) 如果您已经有 AWS 账户，请跳至步骤 2。

1. [为 IDT 配置权限。](#configure-idt-permissions)

这些账户权限允许 IDT 代表您访问 AWS 服务和创建 AWS 资源，例如 AWS IoT 事物和 AWS IoT Greengrass 组件。

<a name="idt-aws-credentials"></a>要创建这些资源，适用于 AWS IoT Greengrass V2 的 IDT 使用`config.json`文件中配置的 AWS 凭据代表您进行 API 调用。这些资源将在测试过程的不同时间进行预置。

**注意**  
尽管大多数测试都符合 [AWS 免费套餐](https://aws.amazon.com/free)的要求，但您在注册 AWS 账户时必须提供信用卡。有关更多信息，请参阅[我的账户使用的是免费套餐，为什么还需要提供付款方式？](https://aws.amazon.com/premiumsupport/knowledge-center/free-tier-payment-method/)

### 第 1 步：设置 AWS 账户
<a name="create-aws-account-for-idt"></a>

在此步骤中，将创建并配置 AWS 账户。如果您已有 AWS 账户，请跳至 [步骤 2：为 IDT 配置权限](#configure-idt-permissions)。

如果您没有 AWS 账户，请完成以下步骤来创建一个。

**报名参加 AWS 账户**

1. 打开[https://portal.aws.amazon.com/billing/注册。](https://portal.aws.amazon.com/billing/signup)

1. 按照屏幕上的说明操作。

   在注册时，将接到电话或收到短信，要求使用电话键盘输入一个验证码。

   当您注册时 AWS 账户，就会创建*AWS 账户根用户*一个。根用户有权访问该账户中的所有 AWS 服务 和资源。作为最佳安全实践，请为用户分配管理访问权限，并且只使用根用户来执行[需要根用户访问权限的任务](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#root-user-tasks)。

要创建管理员用户，请选择以下选项之一。


****  

| 选择一种方法来管理您的管理员 | 目标 | 方式 | 您也可以 | 
| --- | --- | --- | --- | 
| 在 IAM Identity Center 中 （推荐） | 使用短期凭证访问 AWS。这符合安全最佳实操。有关最佳实践的信息，请参阅《IAM 用户指南》**中的 [IAM 中的安全最佳实践](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#bp-users-federation-idp)。 | 有关说明，请参阅《AWS IAM Identity Center 用户指南》中的[入门](https://docs.aws.amazon.com//singlesignon/latest/userguide/getting-started.html)。 | 通过在《AWS Command Line Interface 用户指南[》 AWS IAM Identity Center中配置 AWS CLI 要使用的来](https://docs.aws.amazon.com//cli/latest/userguide/cli-configure-sso.html)配置编程访问权限。 | 
| 在 IAM 中 （不推荐使用） | 使用长期凭证访问 AWS。 | 按照《IAM 用户指南》中的[创建用于紧急访问的 IAM 用户](https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-started-emergency-iam-user.html)中的说明进行操作。 | 按照《IAM 用户指南》中的[管理 IAM 用户的访问密钥](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_credentials_access-keys.html)，配置编程式访问。 | 

### 步骤 2：为 IDT 配置权限
<a name="configure-idt-permissions"></a>

在此步骤中，配置 IDT for AWS IoT Greengrass V2 用于运行测试和收集 IDT 使用情况数据的权限。您可以使用 [AWS 管理控制台](#configure-idt-permissions-console) 或 [AWS Command Line Interface （AWS CLI）](#configure-idt-permissions-cli)为 IDT 创建 IAM 策略和测试用户，然后将策略附加到用户。如果您已经为 IDT 创建了测试用户，请跳转至 [配置设备以运行 IDT 测试](device-config-setup.md)。

#### 为 IDT 配置权限（控制台）
<a name="configure-idt-permissions-console"></a>

1. 登录 [IAM 控制台](https://console.aws.amazon.com/iam)。

1. 创建客户托管策略，该策略授权创建具有特定权限的角色。

   1. 在导航窗格中，选择 **策略**，然后选择 **创建策略**。

   1. 如果您未使用 PreInstalled，请在 **JSON** 选项卡上将占位符内容替换为以下策略。如果您正在使用 PreInstalled，请继续执行以下步骤。

      ```
      <a name="customer-managed-policy-cli"></a>{
          "Version":"2012-10-17",		 	 	 
          "Statement":[
          {
            "Sid":"passRoleForResources",
            "Effect":"Allow",
            "Action":"iam:PassRole",
            "Resource":"arn:aws:iam::*:role/idt-*",
            "Condition":{
              "StringEquals":{
                "iam:PassedToService":[
                  "iot.amazonaws.com",
                  "lambda.amazonaws.com",
                  "greengrass.amazonaws.com"
                ]
              }
            }
          },
          {
            "Sid":"lambdaResources",
            "Effect":"Allow",
            "Action":[
              "lambda:CreateFunction",
              "lambda:PublishVersion",
              "lambda:DeleteFunction",
              "lambda:GetFunction"
            ],
            "Resource":[
              "arn:aws:lambda:*:*:function:idt-*"
            ]
          },
          {
            "Sid":"iotResources",
            "Effect":"Allow",
            "Action":[
              "iot:CreateThing",
              "iot:DeleteThing",
              "iot:DescribeThing",
              "iot:CreateThingGroup",
              "iot:DeleteThingGroup",
              "iot:DescribeThingGroup",
              "iot:AddThingToThingGroup",
              "iot:RemoveThingFromThingGroup",
              "iot:AttachThingPrincipal",
              "iot:DetachThingPrincipal",
              "iot:UpdateCertificate",
              "iot:DeleteCertificate",
              "iot:CreatePolicy",
              "iot:AttachPolicy",
              "iot:DetachPolicy",
              "iot:DeletePolicy",
              "iot:GetPolicy",
              "iot:Publish",
              "iot:TagResource",
              "iot:ListThingPrincipals",
              "iot:ListAttachedPolicies",
              "iot:ListTargetsForPolicy",
              "iot:ListThingGroupsForThing",
              "iot:ListThingsInThingGroup",
              "iot:CreateJob",
              "iot:DescribeJob",
              "iot:DescribeJobExecution",
              "iot:CancelJob"
            ],
            "Resource":[
              "arn:aws:iot:*:*:thing/idt-*",
              "arn:aws:iot:*:*:thinggroup/idt-*",
              "arn:aws:iot:*:*:policy/idt-*",
              "arn:aws:iot:*:*:cert/*",
              "arn:aws:iot:*:*:topic/idt-*",
              "arn:aws:iot:*:*:job/*"
            ]
          },
          {
            "Sid":"s3Resources",
            "Effect":"Allow",
            "Action":[
              "s3:GetObject",
              "s3:PutObject",
              "s3:DeleteObjectVersion",
              "s3:DeleteObject",
              "s3:CreateBucket",
              "s3:ListBucket",
              "s3:ListBucketVersions",
              "s3:DeleteBucket",
              "s3:PutObjectTagging",
              "s3:PutBucketTagging"
            ],
            "Resource":"arn:aws:s3::*:idt-*"
          },
          {
            "Sid":"roleAliasResources",
            "Effect":"Allow",
            "Action":[
              "iot:CreateRoleAlias",
              "iot:DescribeRoleAlias",
              "iot:DeleteRoleAlias",
              "iot:TagResource",
              "iam:GetRole"
            ],
            "Resource":[
              "arn:aws:iot:*:*:rolealias/idt-*",
              "arn:aws:iam::*:role/idt-*"
            ]
          },
          {
            "Sid":"idtExecuteAndCollectMetrics",
            "Effect":"Allow",
            "Action":[
              "iot-device-tester:SendMetrics",
              "iot-device-tester:SupportedVersion",
              "iot-device-tester:LatestIdt",
              "iot-device-tester:CheckVersion",
              "iot-device-tester:DownloadTestSuite"
            ],
            "Resource":"*"
          },
          {
            "Sid":"genericResources",
            "Effect":"Allow",
            "Action":[
              "greengrass:*",
              "iot:GetThingShadow",
              "iot:UpdateThingShadow",
              "iot:ListThings",
              "iot:DescribeEndpoint",
              "iot:CreateKeysAndCertificate"
            ],
            "Resource":"*"
          },
          {
            "Sid":"iamResourcesUpdate",
            "Effect":"Allow",
            "Action":[
              "iam:CreateRole",
              "iam:DeleteRole",
              "iam:CreatePolicy",
              "iam:DeletePolicy",
              "iam:AttachRolePolicy",
              "iam:DetachRolePolicy",
              "iam:TagRole",
              "iam:TagPolicy",
              "iam:GetPolicy",
              "iam:ListAttachedRolePolicies",
              "iam:ListEntitiesForPolicy"
            ],
            "Resource":[
              "arn:aws:iam::*:role/idt-*",
              "arn:aws:iam::*:policy/idt-*"
            ]
          }
        ]
      }
      ```

   1. 如果您使用的是 PreInstalled，请在 **JSON** 选项卡上将占位符内容替换为以下策略。请确保：
      + 将`iotResources`语句*thingGroup*中的*thingName*和替换为在被测设备 (DUT) 上安装 Greengrass 期间创建的事物名称和事物组，以添加权限。
      + 将语句*passRole*和`roleAliasResources`语句*roleAlias*中的和替换为`passRoleForResources`在 DUT 上安装 Greengrass 期间创建的角色。

      ```
      <a name="customer-managed-policy-cli"></a>{
          "Version":"2012-10-17",		 	 	 
          "Statement":[
          {
            "Sid":"passRoleForResources",
            "Effect":"Allow",
            "Action":"iam:PassRole",
            "Resource":"arn:aws:iam::*:role/passRole",
            "Condition":{
              "StringEquals":{
                "iam:PassedToService":[
                  "iot.amazonaws.com",
                  "lambda.amazonaws.com",
                  "greengrass.amazonaws.com"
                ]
              }
            }
          },
          {
            "Sid":"lambdaResources",
            "Effect":"Allow",
            "Action":[
              "lambda:CreateFunction",
              "lambda:PublishVersion",
              "lambda:DeleteFunction",
              "lambda:GetFunction"
            ],
            "Resource":[
              "arn:aws:lambda:*:*:function:idt-*"
            ]
          },
          {
            "Sid":"iotResources",
            "Effect":"Allow",
            "Action":[
              "iot:CreateThing",
              "iot:DeleteThing",
              "iot:DescribeThing",
              "iot:CreateThingGroup",
              "iot:DeleteThingGroup",
              "iot:DescribeThingGroup",
              "iot:AddThingToThingGroup",
              "iot:RemoveThingFromThingGroup",
              "iot:AttachThingPrincipal",
              "iot:DetachThingPrincipal",
              "iot:UpdateCertificate",
              "iot:DeleteCertificate",
              "iot:CreatePolicy",
              "iot:AttachPolicy",
              "iot:DetachPolicy",
              "iot:DeletePolicy",
              "iot:GetPolicy",
              "iot:Publish",
              "iot:TagResource",
              "iot:ListThingPrincipals",
              "iot:ListAttachedPolicies",
              "iot:ListTargetsForPolicy",
              "iot:ListThingGroupsForThing",
              "iot:ListThingsInThingGroup",
              "iot:CreateJob",
              "iot:DescribeJob",
              "iot:DescribeJobExecution",
              "iot:CancelJob"
            ],
            "Resource":[
              "arn:aws:iot:*:*:thing/thingName",
              "arn:aws:iot:*:*:thinggroup/thingGroup",
              "arn:aws:iot:*:*:policy/idt-*",
              "arn:aws:iot:*:*:cert/*",
              "arn:aws:iot:*:*:topic/idt-*",
              "arn:aws:iot:*:*:job/*"
            ]
          },
          {
            "Sid":"s3Resources",
            "Effect":"Allow",
            "Action":[
              "s3:GetObject",
              "s3:PutObject",
              "s3:DeleteObjectVersion",
              "s3:DeleteObject",
              "s3:CreateBucket",
              "s3:ListBucket",
              "s3:ListBucketVersions",
              "s3:DeleteBucket",
              "s3:PutObjectTagging",
              "s3:PutBucketTagging"
            ],
            "Resource":"arn:aws:s3::*:idt-*"
          },
          {
            "Sid":"roleAliasResources",
            "Effect":"Allow",
            "Action":[
              "iot:CreateRoleAlias",
              "iot:DescribeRoleAlias",
              "iot:DeleteRoleAlias",
              "iot:TagResource",
              "iam:GetRole"
            ],
            "Resource":[
              "arn:aws:iot:*:*:rolealias/roleAlias",
              "arn:aws:iam::*:role/idt-*"
            ]
          },
          {
            "Sid":"idtExecuteAndCollectMetrics",
            "Effect":"Allow",
            "Action":[
              "iot-device-tester:SendMetrics",
              "iot-device-tester:SupportedVersion",
              "iot-device-tester:LatestIdt",
              "iot-device-tester:CheckVersion",
              "iot-device-tester:DownloadTestSuite"
            ],
            "Resource":"*"
          },
          {
            "Sid":"genericResources",
            "Effect":"Allow",
            "Action":[
              "greengrass:*",
              "iot:GetThingShadow",
              "iot:UpdateThingShadow",
              "iot:ListThings",
              "iot:DescribeEndpoint",
              "iot:CreateKeysAndCertificate"
            ],
            "Resource":"*"
          },
          {
            "Sid":"iamResourcesUpdate",
            "Effect":"Allow",
            "Action":[
              "iam:CreateRole",
              "iam:DeleteRole",
              "iam:CreatePolicy",
              "iam:DeletePolicy",
              "iam:AttachRolePolicy",
              "iam:DetachRolePolicy",
              "iam:TagRole",
              "iam:TagPolicy",
              "iam:GetPolicy",
              "iam:ListAttachedRolePolicies",
              "iam:ListEntitiesForPolicy"
            ],
            "Resource":[
              "arn:aws:iam::*:role/idt-*",
              "arn:aws:iam::*:policy/idt-*"
            ]
          }
        ]
      }
      ```
**注意**  
如果您想使用[自定义 IAM 角色作为被测设备的令牌交换角色](set-config.md#custom-token-exchange-role-idt)，请务必更新策略中的 `roleAliasResources` 语句和 `passRoleForResources` 语句以允许自定义 IAM 角色资源。

   1. 选择**查看策略**。

   1. 对于 **Name (名称)**，请输入 **IDTGreengrassIAMPermissions**。在 **Summary (摘要)** 下，查看策略授予的权限。

   1. 选择**创建策略**。

1. 创建 IAM 用户并附加 IDT for AWS IoT Greengrass所需的权限。

   1. 创建 IAM 用户。按照 *IAM 用户指南*的[创建 IAM 用户（控制台）](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html#id_users_create_console)中的步骤 1 到 5 操作。

   1. 将权限附加到您的 IAM 用户：

      1. 在 **Set permissions (设置权限)** 页面上，选择 **Attach existing policies to user directly (直接附加现有策略到用户)**。

      1. 搜索您在上一步中创建的**IDTGreengrassIAMPermissions**策略。选中复选框。

   1. 选择**下一步：标签**。

   1. 选择 **Next: Review (下一步：审核)** 以查看您的选择摘要。

   1. 选择**创建用户**。

   1. 要查看用户的访问密钥（访问密钥 IDs 和私有访问密钥），请选择密码和访问密钥旁边的**显示**。要保存访问密钥，请选择**Download.csv (下载 .csv)**，然后将文件保存到安全位置。稍后您可以使用此信息配置 AWS 凭证文件。

1. <a name="aws-account-config-next-steps"></a>下一步：配置[物理设备](device-config-setup.md)。

#### 为 IDT 配置权限 (AWS CLI)
<a name="configure-idt-permissions-cli"></a>

1.  AWS CLI 如果尚未安装，请在您的计算机上进行安装和配置。按照《AWS Command Line Interface 用户指南》**中[安装 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) 的步骤来操作。
**注意**  
 AWS CLI 是一个开源工具，可用于通过命令行 shell 与 AWS 服务进行交互。

1. 创建用于授予管理 IDT 和 AWS IoT Greengrass 角色的权限的客户托管策略。

   1. 如果您未使用 PreInstalled，请打开文本编辑器并将以下策略内容保存到 JSON 文件中。如果您正在使用 PreInstalled，请继续执行以下步骤。

      ```
      <a name="customer-managed-policy-cli"></a>{
          "Version":"2012-10-17",		 	 	 
          "Statement":[
          {
            "Sid":"passRoleForResources",
            "Effect":"Allow",
            "Action":"iam:PassRole",
            "Resource":"arn:aws:iam::*:role/idt-*",
            "Condition":{
              "StringEquals":{
                "iam:PassedToService":[
                  "iot.amazonaws.com",
                  "lambda.amazonaws.com",
                  "greengrass.amazonaws.com"
                ]
              }
            }
          },
          {
            "Sid":"lambdaResources",
            "Effect":"Allow",
            "Action":[
              "lambda:CreateFunction",
              "lambda:PublishVersion",
              "lambda:DeleteFunction",
              "lambda:GetFunction"
            ],
            "Resource":[
              "arn:aws:lambda:*:*:function:idt-*"
            ]
          },
          {
            "Sid":"iotResources",
            "Effect":"Allow",
            "Action":[
              "iot:CreateThing",
              "iot:DeleteThing",
              "iot:DescribeThing",
              "iot:CreateThingGroup",
              "iot:DeleteThingGroup",
              "iot:DescribeThingGroup",
              "iot:AddThingToThingGroup",
              "iot:RemoveThingFromThingGroup",
              "iot:AttachThingPrincipal",
              "iot:DetachThingPrincipal",
              "iot:UpdateCertificate",
              "iot:DeleteCertificate",
              "iot:CreatePolicy",
              "iot:AttachPolicy",
              "iot:DetachPolicy",
              "iot:DeletePolicy",
              "iot:GetPolicy",
              "iot:Publish",
              "iot:TagResource",
              "iot:ListThingPrincipals",
              "iot:ListAttachedPolicies",
              "iot:ListTargetsForPolicy",
              "iot:ListThingGroupsForThing",
              "iot:ListThingsInThingGroup",
              "iot:CreateJob",
              "iot:DescribeJob",
              "iot:DescribeJobExecution",
              "iot:CancelJob"
            ],
            "Resource":[
              "arn:aws:iot:*:*:thing/idt-*",
              "arn:aws:iot:*:*:thinggroup/idt-*",
              "arn:aws:iot:*:*:policy/idt-*",
              "arn:aws:iot:*:*:cert/*",
              "arn:aws:iot:*:*:topic/idt-*",
              "arn:aws:iot:*:*:job/*"
            ]
          },
          {
            "Sid":"s3Resources",
            "Effect":"Allow",
            "Action":[
              "s3:GetObject",
              "s3:PutObject",
              "s3:DeleteObjectVersion",
              "s3:DeleteObject",
              "s3:CreateBucket",
              "s3:ListBucket",
              "s3:ListBucketVersions",
              "s3:DeleteBucket",
              "s3:PutObjectTagging",
              "s3:PutBucketTagging"
            ],
            "Resource":"arn:aws:s3::*:idt-*"
          },
          {
            "Sid":"roleAliasResources",
            "Effect":"Allow",
            "Action":[
              "iot:CreateRoleAlias",
              "iot:DescribeRoleAlias",
              "iot:DeleteRoleAlias",
              "iot:TagResource",
              "iam:GetRole"
            ],
            "Resource":[
              "arn:aws:iot:*:*:rolealias/idt-*",
              "arn:aws:iam::*:role/idt-*"
            ]
          },
          {
            "Sid":"idtExecuteAndCollectMetrics",
            "Effect":"Allow",
            "Action":[
              "iot-device-tester:SendMetrics",
              "iot-device-tester:SupportedVersion",
              "iot-device-tester:LatestIdt",
              "iot-device-tester:CheckVersion",
              "iot-device-tester:DownloadTestSuite"
            ],
            "Resource":"*"
          },
          {
            "Sid":"genericResources",
            "Effect":"Allow",
            "Action":[
              "greengrass:*",
              "iot:GetThingShadow",
              "iot:UpdateThingShadow",
              "iot:ListThings",
              "iot:DescribeEndpoint",
              "iot:CreateKeysAndCertificate"
            ],
            "Resource":"*"
          },
          {
            "Sid":"iamResourcesUpdate",
            "Effect":"Allow",
            "Action":[
              "iam:CreateRole",
              "iam:DeleteRole",
              "iam:CreatePolicy",
              "iam:DeletePolicy",
              "iam:AttachRolePolicy",
              "iam:DetachRolePolicy",
              "iam:TagRole",
              "iam:TagPolicy",
              "iam:GetPolicy",
              "iam:ListAttachedRolePolicies",
              "iam:ListEntitiesForPolicy"
            ],
            "Resource":[
              "arn:aws:iam::*:role/idt-*",
              "arn:aws:iam::*:policy/idt-*"
            ]
          }
        ]
      }
      ```

   1. 如果您正在使用 PreInstalled，请打开文本编辑器并将以下策略内容保存到 JSON 文件中。请确保：
      + *thingGroup*在被测设备 (DUT) 上安装 Greengrass 期间创建的`iotResources`语句中替换*thingName*和以添加权限。
      + 将语句*passRole*和`roleAliasResources`语句*roleAlias*中的和替换为`passRoleForResources`在 DUT 上安装 Greengrass 期间创建的角色。

      ```
      <a name="customer-managed-policy-cli"></a>{
          "Version":"2012-10-17",		 	 	 
          "Statement":[
          {
            "Sid":"passRoleForResources",
            "Effect":"Allow",
            "Action":"iam:PassRole",
            "Resource":"arn:aws:iam::*:role/passRole",
            "Condition":{
              "StringEquals":{
                "iam:PassedToService":[
                  "iot.amazonaws.com",
                  "lambda.amazonaws.com",
                  "greengrass.amazonaws.com"
                ]
              }
            }
          },
          {
            "Sid":"lambdaResources",
            "Effect":"Allow",
            "Action":[
              "lambda:CreateFunction",
              "lambda:PublishVersion",
              "lambda:DeleteFunction",
              "lambda:GetFunction"
            ],
            "Resource":[
              "arn:aws:lambda:*:*:function:idt-*"
            ]
          },
          {
            "Sid":"iotResources",
            "Effect":"Allow",
            "Action":[
              "iot:CreateThing",
              "iot:DeleteThing",
              "iot:DescribeThing",
              "iot:CreateThingGroup",
              "iot:DeleteThingGroup",
              "iot:DescribeThingGroup",
              "iot:AddThingToThingGroup",
              "iot:RemoveThingFromThingGroup",
              "iot:AttachThingPrincipal",
              "iot:DetachThingPrincipal",
              "iot:UpdateCertificate",
              "iot:DeleteCertificate",
              "iot:CreatePolicy",
              "iot:AttachPolicy",
              "iot:DetachPolicy",
              "iot:DeletePolicy",
              "iot:GetPolicy",
              "iot:Publish",
              "iot:TagResource",
              "iot:ListThingPrincipals",
              "iot:ListAttachedPolicies",
              "iot:ListTargetsForPolicy",
              "iot:ListThingGroupsForThing",
              "iot:ListThingsInThingGroup",
              "iot:CreateJob",
              "iot:DescribeJob",
              "iot:DescribeJobExecution",
              "iot:CancelJob"
            ],
            "Resource":[
              "arn:aws:iot:*:*:thing/thingName",
              "arn:aws:iot:*:*:thinggroup/thingGroup",
              "arn:aws:iot:*:*:policy/idt-*",
              "arn:aws:iot:*:*:cert/*",
              "arn:aws:iot:*:*:topic/idt-*",
              "arn:aws:iot:*:*:job/*"
            ]
          },
          {
            "Sid":"s3Resources",
            "Effect":"Allow",
            "Action":[
              "s3:GetObject",
              "s3:PutObject",
              "s3:DeleteObjectVersion",
              "s3:DeleteObject",
              "s3:CreateBucket",
              "s3:ListBucket",
              "s3:ListBucketVersions",
              "s3:DeleteBucket",
              "s3:PutObjectTagging",
              "s3:PutBucketTagging"
            ],
            "Resource":"arn:aws:s3::*:idt-*"
          },
          {
            "Sid":"roleAliasResources",
            "Effect":"Allow",
            "Action":[
              "iot:CreateRoleAlias",
              "iot:DescribeRoleAlias",
              "iot:DeleteRoleAlias",
              "iot:TagResource",
              "iam:GetRole"
            ],
            "Resource":[
              "arn:aws:iot:*:*:rolealias/roleAlias",
              "arn:aws:iam::*:role/idt-*"
            ]
          },
          {
            "Sid":"idtExecuteAndCollectMetrics",
            "Effect":"Allow",
            "Action":[
              "iot-device-tester:SendMetrics",
              "iot-device-tester:SupportedVersion",
              "iot-device-tester:LatestIdt",
              "iot-device-tester:CheckVersion",
              "iot-device-tester:DownloadTestSuite"
            ],
            "Resource":"*"
          },
          {
            "Sid":"genericResources",
            "Effect":"Allow",
            "Action":[
              "greengrass:*",
              "iot:GetThingShadow",
              "iot:UpdateThingShadow",
              "iot:ListThings",
              "iot:DescribeEndpoint",
              "iot:CreateKeysAndCertificate"
            ],
            "Resource":"*"
          },
          {
            "Sid":"iamResourcesUpdate",
            "Effect":"Allow",
            "Action":[
              "iam:CreateRole",
              "iam:DeleteRole",
              "iam:CreatePolicy",
              "iam:DeletePolicy",
              "iam:AttachRolePolicy",
              "iam:DetachRolePolicy",
              "iam:TagRole",
              "iam:TagPolicy",
              "iam:GetPolicy",
              "iam:ListAttachedRolePolicies",
              "iam:ListEntitiesForPolicy"
            ],
            "Resource":[
              "arn:aws:iam::*:role/idt-*",
              "arn:aws:iam::*:policy/idt-*"
            ]
          }
        ]
      }
      ```
**注意**  
如果您想使用[自定义 IAM 角色作为被测设备的令牌交换角色](set-config.md#custom-token-exchange-role-idt)，请务必更新策略中的 `roleAliasResources` 语句和 `passRoleForResources` 语句以允许自定义 IAM 角色资源。

   1. 运行以下命令，创建名为 `IDTGreengrassIAMPermissions` 的客户管理型策略。将 `policy.json` 替换为您在上一步中创建的 JSON 文件的完整路径。

      ```
      aws iam create-policy --policy-name IDTGreengrassIAMPermissions --policy-document file://policy.json
      ```

1. 创建 IAM 用户并附加 IDT for AWS IoT Greengrass所需的权限。

   1. 创建 IAM 用户。在此示例设置中，用户被命名为 `IDTGreengrassUser`。

      ```
      aws iam create-user --user-name IDTGreengrassUser
      ```

   1. 将您在步骤 2 中创建的 `IDTGreengrassIAMPermissions` 策略附加到您的 IAM 用户。*<account-id>*在命令中替换为您的 ID AWS 账户。

      ```
      aws iam attach-user-policy --user-name IDTGreengrassUser --policy-arn arn:aws:iam::<account-id>:policy/IDTGreengrassIAMPermissions
      ```

1. 为用户创建私密访问密钥。

   ```
   aws iam create-access-key --user-name IDTGreengrassUser
   ```

   将输出存储在安全位置。稍后您将使用此信息来配置您的 AWS 凭据文件。

1. <a name="aws-account-config-next-steps"></a>下一步：配置[物理设备](device-config-setup.md)。

### AWS IoT Device Tester 权限
<a name="gg-idt-managed-policy"></a>

以下策略描述了 AWS IoT Device Tester 权限。

AWS IoT Device Tester 版本检查和自动更新功能需要这些权限。
+ `iot-device-tester:SupportedVersion`

  授 AWS IoT Device Tester 予获取受支持产品、测试套件和 IDT 版本列表的权限。
+ `iot-device-tester:LatestIdt`

  授 AWS IoT Device Tester 予获取可供下载的最新 IDT 版本的权限。
+ `iot-device-tester:CheckVersion`

  授 AWS IoT Device Tester 予检查 IDT、测试套件和产品的版本兼容性的权限。
+ `iot-device-tester:DownloadTestSuite`

  授 AWS IoT Device Tester 予下载测试套件更新的权限。

AWS IoT Device Tester 还使用以下权限来报告可选指标：
+ `iot-device-tester:SendMetrics`

  授 AWS 予收集 AWS IoT Device Tester 内部使用情况指标的权限。如果省略此权限，则不会收集这些指标。

# 配置设备以运行 IDT 测试
<a name="device-config-setup"></a>

要让 IDT 运行设备资格认证测试，您必须将主机配置为访问您的设备，并在您的设备上配置用户权限。

## 在主机上安装 Java
<a name="install-java-for-idt"></a>

从 IDT v4.2.0 开始，可选的资格测试 AWS IoT Greengrass 要求运行 Java。

您可以使用 Java 版本 8 或更高版本。我们建议您使用 [Amazon Corretto](https://aws.amazon.com/corretto/) 或 [OpenJDK](https://openjdk.java.net/) 长期支持版本。需要版本 8 或更高版本。

## 配置主机以访问被测设备
<a name="configure-host"></a>

IDT 在主机上运行，并且必须能够使用 SSH 连接到您的设备。有两个选项允许 IDT 获得对被测设备的 SSH 访问权限：

1. 按照此处的说明创建一个 SSH 密钥对并授权您的密钥，以便登录被测设备而无需指定密码。

1. 在 `device.json` 文件中为每个设备提供用户名和密码。有关更多信息，请参阅 [配置 device.json](set-config.md#device-config)。

您可以使用任何 SSL 实现创建 SSH 密钥。以下说明向你展示了如何使用 [SSH-KEYGEN](https://www.ssh.com/ssh/keygen/) 或 [Pu TTYgen](https://www.ssh.com/ssh/putty/windows/puttygen)（适用于 Windows）。如果您使用的是另一个 SSL 实现，请参阅该实现的文档。

IDT 使用 SSH 密钥对被测设备进行身份验证。

**使用 SSH-KEYGEN 创建 SSH 密钥**

1. 创建 SSH 密钥。

   您可以使用 Open SSH **ssh-keygen** 命令创建 SSH 密钥对。如果您的主机上已有一个 SSH 密钥对，则最佳做法是专门为 IDT 创建一个 SSH 密钥对。这样，完成测试后，如果没有输入密码，主机将无法再连接到设备。它还使您能够仅向需要访问远程设备的人员授予访问权限。
**注意**  
Windows 没有安装 SSH 客户端。有关在 Windows 上安装 SSH 客户端的信息，请参阅[下载 SSH 客户端软件](https://www.ssh.com/ssh/#sec-Download-client-software)。

   **ssh-keygen** 命令会提示您输入要存储密钥对的名称和路径。默认情况下，密钥对文件的名称为 `id_rsa`（私有密钥）和 `id_rsa.pub`（公有密钥）。在 macOS 和 Linux 上，这些文件的默认位置为 `~/.ssh/`。在 Windows 上，默认位置为 `C:\Users\<user-name>\.ssh`。

   根据提示，输入密钥短语来保护您的 SSH 密钥。有关更多信息，请参阅[生成新的 SSH 密钥](https://www.ssh.com/ssh/keygen/)。

1. 向被测设备添加经过授权的 SSH 密钥。

   IDT 必须使用您的 SSH 私有密钥登录被测设备。要授权 SSH 私有密钥以登录被测设备，请在主机上使用 **ssh-copy-id** 命令。此命令会将您的公有密钥添加到被测设备上的 `~/.ssh/authorized_keys` 文件中。例如：

   **\$1 ssh-copy-id *<remote-ssh-user>*@*<remote-device-ip>***

   哪里*remote-ssh-user*是用于登录被测设备的用户名，以及*remote-device-ip*用于运行测试的被测设备的 IP 地址。例如：

   **ssh-copy-id pi@192.168.1.5**

   系统提示时，输入在 **ssh-copy-id** 命令中指定的用户名所对应的密码。

   **ssh-copy-id** 公有密钥的名称为 `id_rsa.pub` 并且存储在默认位置（macOS 和 Linux 上的位置为 `~/.ssh/`，Windows 上的位置为 `C:\Users\<user-name>\.ssh`）。如果公有密钥采用其他名称或存储在其他位置，则必须使用 **-i** 选项与 **ssh-copy-id** 指定 SSH 公有密钥的完全限定路径（例如，**ssh-copy-id -i \$1/my/path/myKey.pub**）。有关创建 SSH 密钥和复制公有密钥的更多信息，请参阅 [SSH-COPY-ID](https://www.ssh.com/ssh/copy-id)。

**使用 Pu 创建 SSH 密钥TTYgen （仅限 Windows）**

1. 确保您在被测设备上安装了 OpenSSH 服务器和客户端。有关更多信息，请参阅 [OpenSSH](https://www.openssh.com/)。

1. 在被测设备TTYgen上安装 [Pu](https://www.puttygen.com/)。

1. 打开 Pu TTYgen。

1. 选择 **Generate (生成)**，然后在框中移动鼠标光标以生成私有密钥。

1. 从 **Conversions (转换)** 菜单中，选择 **Export OpenSSH key (导出 OpenSSH 密钥)**，然后使用 `.pem` 文件扩展名保存私有密钥 。

1. 将公有密钥添加到被测设备上的 `/home/<user>/.ssh/authorized_keys` 文件中。

   1. 从 Pu TTYgen 窗口复制公钥文本。

   1. 使用 PuTTY 在被测设备上创建会话。

      1. 从命令提示符或 Windows Powershell 窗口中，运行以下命令：

          **C:/*<path-to-putty>*/putty.exe -ssh *<user>*@*<dut-ip-address>* ** 

      1. 在系统提示时，输入您的设备密码。

      1. 使用 vi 或其他文本编辑器将公有密钥附加到被测设备上的 `/home/<user>/.ssh/authorized_keys` 文件中。

1. 使用您的用户名、IP 地址以及您刚刚为每个被测设备保存在主机上的私钥文件的路径更新 `device.json` 文件。有关更多信息，请参阅 [配置 device.json](set-config.md#device-config)。确保提供私有密钥的完整路径和文件名，并使用正斜杠（“/”）。例如，对于 Windows 路径 `C:\DT\privatekey.pem`，请在 `device.json` 文件中使用 `C:/DT/privatekey.pem`。

## 为 Windows 设备配置用户凭证
<a name="configure-windows-user-for-idt"></a>

要获得基于 Windows 的设备的资格，您必须在被测设备上的LocalSystem 帐户中为以下用户配置用户凭据：
+ 默认 Greengrass 用户（`ggc_user`）。
+ 您用来连接到被测设备的用户。您可以在 [`device.json` 文件](set-config.md#device-config)中配置此用户。

您必须在被测设备上的 LocalSystem 账户中创建每个用户，然后将该用户的用户名和密码存储在LocalSystem 账户的 Credential Manager 实例中。<a name="set-up-windows-device-environment-procedure"></a>

**在 Windows 设备上配置用户**

1. 以管理员身份打开 Windows 命令提示符 (`cmd.exe`)。

1. 在 Windows 设备上的 LocalSystem 帐户中创建用户。为您要创建的每个用户运行以下命令：对于默认 Greengrass 用户，请替换为。*user-name* `ggc_user`*password*替换为安全密码。

   ```
   net user /add user-name password
   ```

1. 从微软下载该[PsExec实用程序](https://docs.microsoft.com/en-us/sysinternals/downloads/psexec)并将其安装到设备上。

1. 使用该 PsExec 实用程序将默认用户的用户名和密码存储在 LocalSystem 账户的凭据管理器实例中。

   为要在 Credential Manager 中配置的每个用户运行以下命令。对于默认 Greengrass 用户，请替换为。*user-name* `ggc_user`*password*替换为您之前设置的用户密码。

   ```
   psexec -s cmd /c cmdkey /generic:user-name /user:user-name /pass:password
   ```

   如果系统打开 **PsExec License Agreement**，请选择 **Accept** 以同意许可并运行命令。
**注意**  
在 Windows 设备上，该 LocalSystem 帐户运行 Greengrass 核心，您必须使用 PsExec 该实用程序在帐户中存储用户信息。 LocalSystem使用凭据管理器应用程序将此信息存储在当前登录用户的 Windows 帐户中，而不是 LocalSystem帐户中。

## 在您的设备上配置用户权限
<a name="root-access"></a>

IDT 将对被测设备中的各种目录和文件执行操作。其中一些操作需要升级权限（使用 **sudo**）。要自动执行这些操作， AWS IoT Greengrass V2 版 IDT 必须能够在不被提示输入密码的情况下使用 sudo 运行命令。

请在被测设备上执行以下步骤，以允许在不提示输入密码的情况下进行 sudo 访问。

**注意**  
`username` 是指 IDT 用来访问被测设备的 SSH 用户。

**将用户添加到 sudo 组**

1. 在被测设备上，运行 `sudo usermod -aG sudo <username>`。

1. 注销，然后重新登录，以使变更生效。

1. 要验证您的用户名是否已成功添加，请运行 **sudo echo test**。如果系统未提示您输入密码，则说明已正确配置您的用户。

1. 打开 `/etc/sudoers` 文件，并将以下行添加到文件末尾：

   `<ssh-username> ALL=(ALL) NOPASSWD: ALL`

## 配置自定义令牌交换角色
<a name="configure-custom-tes-role-for-idt"></a>

您可以选择使用自定义 IAM 角色作为被测设备假设的与 AWS 资源交互的令牌交换角色。有关创建 IAM 角色的信息，请参阅《IAM 用户指南》**中的[创建 IAM 角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create.html)。

您必须满足以下要求才能允许 IDT 使用您的自定义 IAM 角色。强烈建议您仅向该角色添加最低要求的策略操作。
+ 必须更新 [userdata.json](set-config.md#custom-token-exchange-role-idt) 配置文件才能将 `GreengrassV2TokenExchangeRole` 参数设置为 `true`。
+ 必须使用以下最低信任策略配置自定义 IAM 角色：

------
#### [ JSON ]

****  

  ```
  {
     "Version":"2012-10-17",		 	 	 
     "Statement":[
        {
           "Effect":"Allow",
           "Principal":{
              "Service":[
                 "credentials.iot.amazonaws.com",
                 "lambda.amazonaws.com", 
                 "sagemaker.amazonaws.com" 
              ]
           },
           "Action":"sts:AssumeRole"
        }
     ]
  }
  ```

------
+ 必须使用以下最低权限策略配置自定义 IAM 角色：

------
#### [ JSON ]

****  

  ```
  {
     "Version":"2012-10-17",		 	 	 
     "Statement":[
        {
           "Effect":"Allow",
           "Action":[
              "iot:DescribeCertificate",
              "logs:CreateLogGroup",
              "logs:CreateLogStream",
              "logs:PutLogEvents",
              "logs:DescribeLogStreams",
              "iot:Connect",
              "iot:Publish",
              "iot:Subscribe",
              "iot:Receive",
              "iot:ListThingPrincipals", 
              "iot:GetThingShadow",
              "iot:UpdateThingShadow",
              "s3:GetBucketLocation",
              "s3:GetObject",
              "s3:PutObject",
              "s3:AbortMultipartUpload",
              "s3:ListMultipartUploadParts"
           ],
           "Resource":"*"
        }
     ]
  }
  ```

------
+ 自定义 IAM 角色的名称必须与您在测试用户的 IAM 权限中指定的 IAM 角色资源相匹配。默认情况下，[测试用户策略](dev-tst-prereqs.md#configure-idt-permissions)允许访问角色名称中带有 `idt-` 前缀的 IAM 角色。如果您的 IAM 角色名称不使用此前缀，请将 `arn:aws:iam::*:role/custom-iam-role-name` 资源添加到测试用户策略的 `roleAliasResources` 语句和 `passRoleForResources` 语句中，如以下示例所示：

    
**Example `passRoleForResources` statement**  

  ```
  {
     "Sid":"passRoleForResources",
     "Effect":"Allow",
     "Action":"iam:PassRole",
     "Resource":"arn:aws:iam::*:role/custom-iam-role-name",
     "Condition":{
        "StringEquals":{
           "iam:PassedToService":[
              "iot.amazonaws.com",
              "lambda.amazonaws.com",
              "greengrass.amazonaws.com"
           ]
        }
     }
  }
  ```  
**Example `roleAliasResources` statement**  

  ```
  {
     "Sid":"roleAliasResources",
     "Effect":"Allow",
     "Action":[
        "iot:CreateRoleAlias",
        "iot:DescribeRoleAlias",
        "iot:DeleteRoleAlias",
        "iot:TagResource",
        "iam:GetRole"
     ],
     "Resource":[
        "arn:aws:iot:*:*:rolealias/idt-*",
        "arn:aws:iam::*:role/custom-iam-role-name"
     ]
  }
  ```

## 配置设备以测试可选功能
<a name="optional-feature-config"></a>

本节介绍运行可选 Docker 和机器学习（ML）功能的 IDT 测试的设备要求。只有 IDT v4.9.3 支持 ML 功能。只有当您想测试这些功能时，才必须确保您的设备符合这些要求。否则，请继续查看 [配置 IDT 设置以运行 AWS IoT Greengrass 资格套件](set-config.md)。

**Topics**
+ [

### Docker 资格认证要求
](#idt-config-docker-components)
+ [

### ML 资格认证要求
](#idt-config-ml-components)
+ [

### HSM 资格认证要求
](#idt-config-hsm-components)

### Docker 资格认证要求
<a name="idt-config-docker-components"></a>

IDT f AWS IoT Greengrass or V2 提供 Docker 资格测试，以验证您的设备是否可以使用 AWS提供的 [Docker 应用程序管理器组件下载您可以使用自定义 Dock](docker-application-manager-component.md) er 容器组件运行的 Docker 容器镜像。有关创建自定义 Docker 文档的更多信息，请参阅 [运行 Docker 容器](run-docker-container.md)。

要运行 Docker 资格认证测试，您的被测设备必须满足以下要求才能部署 Docker 应用程序管理器组件。
+ <a name="docker-engine-requirement"></a>Greengrass 核心设备上安装的 [Docker Engine](https://docs.docker.com/engine/) 1.9.1 或更高版本。版本 20.10 是经验证可与 AWS IoT Greengrass 核心软件配合使用的最新版本。在部署运行 Docker 容器的组件之前，必须直接在核心设备上安装 Docker。
+ <a name="docker-daemon-requirement"></a>在部署此组件之前，Docker 进程守护程序已启动并在核心设备上运行。
+ <a name="docker-user-permissions-requirement"></a>运行 Docker 容器组件的系统用户必须具有根或管理员权限，或者您必须将 Docker 配置为以非根用户或非管理员用户身份运行。
  + 在 Linux 设备上，您可向 `docker` 组中添加一个用户以调用 `docker` 命令，无需 `sudo`。
  + 在 Windows 设备上，您可将用户添加到 `docker-users` 组中以调用 `docker` 命令，无需管理员权限。

------
#### [ Linux or Unix ]

  要添加 `ggc_user` 或您用于运行 Docker 容器组件的非根用户至 `docker` 组中，请运行以下命令：

  ```
  sudo usermod -aG docker ggc_user
  ```

  有关更多信息，请参阅[以非根用户身份管理 Docker](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user)。

------
#### [ Windows Command Prompt (CMD) ]

  要添加 `ggc_user` 或您用于运行 Docker 容器组件的非根用户至 `docker-users` 组中，请以管理员身份运行以下命令：

  ```
  net localgroup docker-users ggc_user /add
  ```

------
#### [ Windows PowerShell ]

  要添加 `ggc_user` 或您用于运行 Docker 容器组件的非根用户至 `docker-users` 组中，请以管理员身份运行以下命令：

  ```
  Add-LocalGroupMember -Group docker-users -Member ggc_user
  ```

------

### ML 资格认证要求
<a name="idt-config-ml-components"></a>

**注意**  
只有 IDT v4.9.3 支持机器学习功能。

[IDT f AWS IoT Greengrass or V2 提供机器学习资格测试，以验证您的设备是否可以使用 AWS提供的[机器学习组件，使用深度学习](machine-learning-components.md)[运行时或 TensorFlow Lite ML 框架在本地执行机器学习](https://github.com/neo-ai/neo-ai-dlr)推理。](https://www.tensorflow.org/lite/guide/python)有关在 Greengrass 设备上运行 ML 推理的更多信息，请参阅 [执行机器学习推理](perform-machine-learning-inference.md)。

要运行 ML 资格认证测试，您的被测设备必须满足以下要求才能部署机器学习组件。<a name="ml-component-requirements"></a>
+ 在运行 Amazon Linux 2 或 Ubuntu 18.04 的 Greengrass 核心设备上，[GNU C 库](https://www.gnu.org/software/libc/)（glibc）版本 2.27 或更高版本已安装在设备上。
+ 在 Armv7l 设备（例如 Raspberry Pi）上，OpenCV-Python 的依赖关系已安装在设备上。运行以下命令以安装依赖关系。

  ```
  sudo apt-get install libopenjp2-7 libilmbase23 libopenexr-dev libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libgtk-3-0 libwebp-dev
  ```
+ 运行 Raspberry Pi OS Bullseye 的 Raspberry Pi 设备必须满足以下要求：
  + NumPy 设备上安装了 1.22.4 或更高版本。Raspberry Pi OS Bullseye 包含的早期版本 NumPy，因此你可以运行以下命令在设备 NumPy 上进行升级。

    ```
    pip3 install --upgrade numpy
    ```
  + 旧摄像机堆栈已在设备上启用。Raspberry Pi OS Bullseye 包含一个新摄像机堆栈，该堆栈默认处于启用状态且不兼容，因此您必须启用旧摄像机堆栈。<a name="raspberry-pi-bullseye-enable-legacy-camera-stack"></a>

**启用旧摄像机堆栈**

    1. 运行以下命令以打开 Raspberry Pi 配置工具。

       ```
       sudo raspi-config
       ```

    1. 选择**接口选项**。

    1. 选择**旧摄像机**以启用旧摄像机堆栈。

    1. 重启 Raspberry Pi。

### HSM 资格认证要求
<a name="idt-config-hsm-components"></a>

AWS IoT Greengrass 提供 [PKCS \$111 提供程序组件](pkcs11-provider-component.md)，用于与设备上的 PKCS 硬件安全模块 (HSM) 集成。HSM 设置取决于您的设备和您选择的 HSM 模块。只要提供了 [IDT 配置设置](set-config.md)中记录的预期 HSM 配置，IDT 就会获得运行此可选功能资格认证测试所需的信息。

# 配置 IDT 设置以运行 AWS IoT Greengrass 资格套件
<a name="set-config"></a>

在运行测试之前，您必须在主机上配置 AWS 凭据和设备的设置。

## 在 config.json 中配置 AWS 凭据
<a name="cfg-aws-gg"></a>

您必须在 `<device_tester_extract_location>/configs/config.json` 文件中配置 IAM 用户凭证。使用中创建的 AWS IoT Greengrass V2 版 IDT 用户的凭证。[创建和配置 AWS 账户](dev-tst-prereqs.md#config-aws-account-for-idt)您可以采用以下两种方法之一来指定凭证：
+ 在凭证文件中
+ 作为环境变量

### 使用 AWS 凭证文件配置凭证
<a name="config-cred-file"></a>

IDT 使用与 AWS CLI相同的凭证文件。有关更多信息，请参阅[配置和凭证文件](https://docs.aws.amazon.com/cli/latest/userguide/cli-config-files.html)。

凭证文件的位置因您使用的操作系统而异：
+ macOS、Linux：`~/.aws/credentials`
+ Windows：`C:\Users\UserName\.aws\credentials`

按以下格式将您的 AWS 凭证添加到`credentials`文件中：

```
[default]
aws_access_key_id = <your_access_key_id>
aws_secret_access_key = <your_secret_access_key>
```

要将 IDT f AWS IoT Greengrass or V2 配置为使用`credentials`文件中的 AWS 凭据，请按如下方式编辑您的`config.json`文件：

```
{
  "awsRegion": "region",
  "auth": {
    "method": "file",
    "credentials": {
      "profile": "default"
    }
  }
}
```

**注意**  
如果您不使用`default` AWS 配置文件，请务必更改文件中的配置`config.json`文件名称。有关更多信息，请参阅[命名配置文件](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html)。

### 使用环境变量配置 AWS 凭证
<a name="config-env-vars"></a>

环境变量是由操作系统维护且由系统命令使用的变量。如果您关闭 SSH 会话，则不会保存它们。适用于 AWS IoT Greengrass V2 的 IDT 可以使用`AWS_ACCESS_KEY_ID`和`AWS_SECRET_ACCESS_KEY`环境变量来存储您的 AWS 证书。

要在 Linux、macOS 或 Unix 上设置这些变量，请使用 **export**：

```
export AWS_ACCESS_KEY_ID=<your_access_key_id>
export AWS_SECRET_ACCESS_KEY=<your_secret_access_key>
```

要在 Windows 上设置这些变量，请使用 **set**：

```
set AWS_ACCESS_KEY_ID=<your_access_key_id>
set AWS_SECRET_ACCESS_KEY=<your_secret_access_key>
```

要配置 IDT 以使用环境变量，请编辑 `config.json` 文件中的 `auth` 部分。示例如下：

```
{
  "awsRegion": "region",
  "auth": {
    "method": "environment"
  }
}
```

## 配置 device.json
<a name="device-config"></a>

**注意**  
IDT v4.9.3 支持测试 `ml`、`docker` 和 `streamManagement` 功能。IDT v4.9.4 及更高版本支持测试 `docker`。如果您不希望测试这些功能，请将相应的值设置为 `no`。

除了 AWS 凭证外，IDT fo AWS IoT Greengrass r V2 还需要有关运行测试的设备的信息。示例信息包括 IP 地址、登录信息、操作系统和 CPU 架构。

您必须使用位于 ` <device_tester_extract_location>/configs/device.json` 中的 `device.json` 模板提供此信息：

------
#### [ IDT v4.9.3 ]

```
[
  {
    "id": "<pool-id>",
    "sku": "<sku>",
    "features": [
      {
        "name": "arch",
        "value": "x86_64 | armv6l | armv7l | aarch64"
      },
      {
        "name": "ml",
        "value": "dlr | tensorflowlite | dlr,tensorflowlite | no"
      },
      {
        "name": "docker",
        "value": "yes | no"
      },
      {
        "name": "streamManagement",
        "value": "yes | no"
      }, 
      {
        "name": "hsi", 
        "value": "hsm | no" 
      }
    ],
    "devices": [
      {
        "id": "<device-id>",
        "operatingSystem": "Linux | Windows",
        "connectivity": {
          "protocol": "ssh",
          "ip": "<ip-address>",
          "port": 22,
          "publicKeyPath": "<public-key-path>",
          "auth": {
            "method": "pki | password",
            "credentials": {
              "user": "<user-name>",
              "privKeyPath": "/path/to/private/key",
              "password": "<password>"
            }
          }
        }
      }
    ]
  }
]
```

**注意**  
只有当 `method` 设置为 `pki` 时才指定 `privKeyPath`。  
只有当 `method` 设置为 `password` 时才指定 `password`。

包含值的所有属性均为必填字段，如下所述：

`id`  
一个用户定义的字母数字 ID，用于唯一地标识称作*设备池*的设备集合。属于池的设备必须具有相同的硬件。运行一组测试时，池中的设备将用于对工作负载进行并行化处理。多个设备用于运行不同测试。

`sku`  
唯一标识所测试设备的字母数字值。该 SKU 用于跟踪符合条件的主板。  
如果您想在设备目录中列出您的 AWS Partner 设备，则在此处指定的 SKU 必须与您在发布过程中使用的 SKU 相匹配。

`features`  
包含设备支持的功能的数组。所有功能都是必需的。    
`arch`  
支持测试运行验证的操作系统架构。有效值为：  
+ `x86_64`
+ `armv6l`
+ `armv7l`
+ `aarch64`  
`ml`  
<a name="description-ml"></a>验证设备是否满足使用 AWS提供的机器学习 (ML) 组件所需的所有技术依赖项。  
启用此功能还可以验证<a name="description-ml-inference-phrase"></a>设备是否可以使用[深度学习运行时和 [TensorFlow Lite](https://www.tensorflow.org/lite/guide/python) ML 框架执行机器学习](https://github.com/neo-ai/neo-ai-dlr)推理。  
有效值是 `dlr` 和 `tensorflowlite` 或 `no` 的任意组合。  
`docker`  
<a name="description-docker"></a>验证设备是否满足使用 AWS提供的 Docker 应用程序管理器 () `aws.greengrass.DockerApplicationManager` 组件所需的所有技术依赖项。  
启用此功能还会验证<a name="description-docker-app-manager-qual-phrase"></a>设备是否可以从 Amazon ECR 下载 Docker 容器镜像。  
有效值是 `yes` 或 `no` 的任意组合。  
`streamManagement`  
<a name="description-sm"></a>验证设备是否可以下载、安装和运行 [AWS IoT Greengrass 流管理器](manage-data-streams.md)。  
有效值是 `yes` 或 `no` 的任意组合。  
`hsi`  
<a name="description-hsi"></a>验证设备是否可以使用存储在硬件安全模块 (HSM) 中的私钥和证书对与和 AWS IoT Greengrass 服务的连接进行身份验证。 AWS IoT 该测试还验证了提供的 [PKCS \$111 AWS提供者组件是否可以使用供应商提供](pkcs11-provider-component.md)的 PKCS \$111 库与 HSM 接口。有关更多信息，请参阅 [硬件安全性集成](hardware-security.md)。  
有效值为 `hsm` 或 `no`。
测试 `hsi` 仅在 IDT v4.9.3 及更高版本中可用。

`devices.id`  
用户定义的测试的设备的唯一标识符。

`devices.operatingSystem`  
设备操作系统。支持的值为 `Linux` 和 `Windows`。

`connectivity.protocol`  
用于与此设备通信的通信协议。目前，物理设备唯一支持的值是 `ssh`。

`connectivity.ip`  
测试的设备 IP 地址。  
<a name="connectivity-protocol-ssh-only"></a>此属性仅在 `connectivity.protocol` 设置为 `ssh` 时适用。

`connectivity.port`  
可选。用于 SSH 连接的端口号。  
默认值为 22。  
此属性仅在 `connectivity.protocol` 设置为 `ssh` 时适用。

`connectivity.publicKeyPath`  
可选。用于验证待测设备连接的公有密钥的完整路径。  
如果指定 `publicKeyPath`，IDT 会在与待测设备建立 SSH 连接时验证设备的公有密钥。如果未指定此值，IDT 将创建 SSH 连接，但不验证设备的公有密钥。  
我们强烈建议您指定公有密钥的路径，并使用安全的方法来获取此公有密钥。对于基于标准命令行的 SSH 客户端，`known_hosts` 文件中提供了公有密钥。如果您指定单独的公有密钥文件，则该文件必须使用与 `known_hosts` 文件相同的格式，即 ` ip-address key-type public-key`。如果有多个条目具有相同 IP 地址，则 IDT 所用密钥类型的条目必须位于文件中的其它条目之前。

`connectivity.auth`  
连接的身份验证信息。  
<a name="connectivity-protocol-ssh-only"></a>此属性仅在 `connectivity.protocol` 设置为 `ssh` 时适用。    
`connectivity.auth.method`  
用于通过给定的连接协议访问设备的身份验证方法。  
支持的值为：  
+ `pki`
+ `password`  
`connectivity.auth.credentials`  
用于身份验证的凭证。    
`connectivity.auth.credentials.password`  
该密码用于登录到正在测试的设备。  
此值仅在 `connectivity.auth.method` 设置为 `password` 时适用。  
`connectivity.auth.credentials.privKeyPath`  
用于登录所测试设备的私有密钥的完整路径。  
此值仅在 `connectivity.auth.method` 设置为 `pki` 时适用。  
`connectivity.auth.credentials.user`  
用于登录所测试设备的用户名。

------
#### [ IDT v4.9.4 ]

```
[
  {
    "id": "<pool-id>",
    "sku": "<sku>",
    "features": [
      {
        "name": "arch",
        "value": "x86_64 | armv6l | armv7l | aarch64"
      },
      {
        "name": "docker",
        "value": "yes | no"
      }, 
      {
        "name": "hsi", 
        "value": "hsm | no" 
      }
    ],
    "devices": [
      {
        "id": "<device-id>",
        "operatingSystem": "Linux | Windows",
        "connectivity": {
          "protocol": "ssh",
          "ip": "<ip-address>",
          "port": 22,
          "publicKeyPath": "<public-key-path>",
          "auth": {
            "method": "pki | password",
            "credentials": {
              "user": "<user-name>",
              "privKeyPath": "/path/to/private/key",
              "password": "<password>"
            }
          }
        }
      }
    ]
  }
]
```

**注意**  
只有当 `method` 设置为 `pki` 时才指定 `privKeyPath`。  
只有当 `method` 设置为 `password` 时才指定 `password`。

包含值的所有属性均为必填字段，如下所述：

`id`  
一个用户定义的字母数字 ID，用于唯一地标识称作*设备池*的设备集合。属于池的设备必须具有相同的硬件。运行一组测试时，池中的设备将用于对工作负载进行并行化处理。多个设备用于运行不同测试。

`sku`  
唯一标识所测试设备的字母数字值。该 SKU 用于跟踪符合条件的主板。  
如果您想在设备目录中列出您的 AWS Partner 设备，则在此处指定的 SKU 必须与您在发布过程中使用的 SKU 相匹配。

`features`  
包含设备支持的功能的数组。所有功能都是必需的。    
`arch`  
支持测试运行验证的操作系统架构。有效值为：  
+ `x86_64`
+ `armv6l`
+ `armv7l`
+ `aarch64`  
`docker`  
<a name="description-docker"></a>验证设备是否满足使用 AWS提供的 Docker 应用程序管理器 () `aws.greengrass.DockerApplicationManager` 组件所需的所有技术依赖项。  
启用此功能还会验证<a name="description-docker-app-manager-qual-phrase"></a>设备是否可以从 Amazon ECR 下载 Docker 容器镜像。  
有效值是 `yes` 或 `no` 的任意组合。  
`hsi`  
<a name="description-hsi"></a>验证设备是否可以使用存储在硬件安全模块 (HSM) 中的私钥和证书对与和 AWS IoT Greengrass 服务的连接进行身份验证。 AWS IoT 该测试还验证了提供的 [PKCS \$111 AWS提供者组件是否可以使用供应商提供](pkcs11-provider-component.md)的 PKCS \$111 库与 HSM 接口。有关更多信息，请参阅 [硬件安全性集成](hardware-security.md)。  
有效值为 `hsm` 或 `no`。
测试 `hsi` 仅在 IDT v4.9.3 及更高版本中可用。

`devices.id`  
用户定义的测试的设备的唯一标识符。

`devices.operatingSystem`  
设备操作系统。支持的值为 `Linux` 和 `Windows`。

`connectivity.protocol`  
用于与此设备通信的通信协议。目前，物理设备唯一支持的值是 `ssh`。

`connectivity.ip`  
测试的设备 IP 地址。  
<a name="connectivity-protocol-ssh-only"></a>此属性仅在 `connectivity.protocol` 设置为 `ssh` 时适用。

`connectivity.port`  
可选。用于 SSH 连接的端口号。  
默认值为 22。  
此属性仅在 `connectivity.protocol` 设置为 `ssh` 时适用。

`connectivity.publicKeyPath`  
可选。用于验证待测设备连接的公有密钥的完整路径。  
如果指定 `publicKeyPath`，IDT 会在与待测设备建立 SSH 连接时验证设备的公有密钥。如果未指定此值，IDT 将创建 SSH 连接，但不验证设备的公有密钥。  
我们强烈建议您指定公有密钥的路径，并使用安全的方法来获取此公有密钥。对于基于标准命令行的 SSH 客户端，`known_hosts` 文件中提供了公有密钥。如果您指定单独的公有密钥文件，则该文件必须使用与 `known_hosts` 文件相同的格式，即 ` ip-address key-type public-key`。如果有多个条目具有相同 IP 地址，则 IDT 所用密钥类型的条目必须位于文件中的其它条目之前。

`connectivity.auth`  
连接的身份验证信息。  
<a name="connectivity-protocol-ssh-only"></a>此属性仅在 `connectivity.protocol` 设置为 `ssh` 时适用。    
`connectivity.auth.method`  
用于通过给定的连接协议访问设备的身份验证方法。  
支持的值为：  
+ `pki`
+ `password`  
`connectivity.auth.credentials`  
用于身份验证的凭证。    
`connectivity.auth.credentials.password`  
该密码用于登录到正在测试的设备。  
此值仅在 `connectivity.auth.method` 设置为 `password` 时适用。  
`connectivity.auth.credentials.privKeyPath`  
用于登录所测试设备的私有密钥的完整路径。  
此值仅在 `connectivity.auth.method` 设置为 `pki` 时适用。  
`connectivity.auth.credentials.user`  
用于登录所测试设备的用户名。

------

## 配置 userdata.json
<a name="userdata-config"></a>

IDT fo AWS IoT Greengrass r V2 还需要有关测试工件和 AWS IoT Greengrass 软件位置的更多信息。

您必须使用位于 ` <device_tester_extract_location>/configs/userdata.json` 中的 `userdata.json` 模板提供此信息：

```
{
    "TempResourcesDirOnDevice": "/path/to/temp/folder",
    "InstallationDirRootOnDevice": "/path/to/installation/folder",
    "GreengrassNucleusZip": "/path/to/aws.greengrass.nucleus.zip",
    "PreInstalled": "yes/no",
    "GreengrassV2TokenExchangeRole": "custom-iam-role-name",
	"hsm": {
        "greengrassPkcsPluginJar": "/path/to/aws.greengrass.crypto.Pkcs11Provider-latest.jar",
        "pkcs11ProviderLibrary": "/path/to/pkcs11-vendor-library",
        "slotId": "slot-id",
        "slotLabel": "slot-label",
        "slotUserPin": "slot-pin",
        "keyLabel": "key-label",
        "preloadedCertificateArn": "certificate-arn"
        "rootCA": "path/to/root-ca"
    }
}
```

包含值的所有属性均为必填字段，如下所述：

`TempResourcesDirOnDevice`  
被测试设备上用于存储测试构件的临时文件夹的完整路径。确保不需要 sudo 权限即可写入此目录。  
IDT 会在完成测试运行后删除该文件夹的内容。

`InstallationDirRootOnDevice`  
设备上要安装 AWS IoT Greengrass的文件夹的完整路径。对于 PreInstalled Greengrass 来说，这是 Greengrass 安装目录的路径。  
您必须为该文件夹设置必要的文件权限。对安装路径中的每个文件夹运行以下命令。  

```
sudo chmod 755 folder-name
```

`GreengrassNucleusZip`  
主机上 Greengrass Nucleus ZIP (`greengrass-nucleus-latest.zip`) 文件的完整路径。使用 PreInstalled Greengrass 进行测试时不需要此字段。  
有关适用于 IDT 的 Greengrass nucleus 支持版本的信息，请参阅。 AWS IoT Greengrass[适用 AWS IoT Greengrass 于 V2 的最新 IDT 版本](dev-test-versions.md#idt-latest-version)[要下载最新的 Greengrass 软件，请参阅下载该软件。 AWS IoT Greengrass](https://docs.aws.amazon.com/greengrass/v2/developerguide/dev-tst-prereqs.html#config-gg)

`PreInstalled`  
此功能仅适用于 Linux 设备上的 IDT v4.5.8 及更高版本。  
（可选）当值为时*yes*，IDT 将假设中`InstallationDirRootOnDevice`提到的路径是安装 Greengrass 的目录。  
有关如何在设备上安装 Greengrass 的更多信息，请参阅 [安装具有自动资源配置功能的 AWS IoT Greengrass Core 软件](quick-installation.md)。如果[使用手动配置进行安装](https://docs.aws.amazon.com/greengrass/v2/developerguide/manual-installation.html)，请在手动创建 AWS IoT 事物时包含 “将事物添加到新的或现有[AWS IoT 的事物](https://docs.aws.amazon.com/greengrass/v2/developerguide/manual-installation.html#create-iot-thing)组” 步骤。IDT 假设事物和事物组是在安装设置期间创建的。确保这些值反映在 `effectiveConfig.yaml` 文件中。IDT 检查 `<InstallationDirRootOnDevice>/config/effectiveConfig.yaml` 下的文件 `effectiveConfig.yaml`。  
要使用 HSM 运行测试，请确保在 `effectiveConfig.yaml` 中更新了 `aws.greengrass.crypto.Pkcs11Provider` 字段。

  `GreengrassV2TokenExchangeRole`  
（可选）您要用作令牌交换角色的自定义 IAM 角色，被测试设备会担任该角色以与 AWS 资源交互。  
IDT 将在测试运行期间使用此自定义 IAM 角色，而非创建默认的令牌交换角色。如果您使用自定义角色，则可以更新[测试用户的 IAM 权限](dev-tst-prereqs.md#configure-idt-permissions)，以排除允许该用户创建和删除 IAM 角色和策略的 `iamResourcesUpdate` 语句。
有关创建自定义 IAM 角色作为令牌交换角色的更多信息，请参阅[配置自定义令牌交换角色](device-config-setup.md#configure-custom-tes-role-for-idt)。

`hsm`  
此功能适用于 IDT v4.5.1 及更高版本。  
（可选）用于通过 AWS IoT Greengrass 硬件安全模块（HSM）进行测试的配置信息。否则，应忽略 `hsm` 属性。有关更多信息，请参阅 [硬件安全性集成](hardware-security.md)。  
<a name="connectivity-protocol-ssh-only"></a>此属性仅在 `connectivity.protocol` 设置为 `ssh` 时适用。  
如果硬件安全模块在 IDT 与其他系统间共享，则 HSM 配置可能被视为敏感数据。在这种情况下，您可以通过将这些配置值存储在 Paramet AWS er Stor SecureString e 参数中并配置 IDT 使其在测试执行期间获取它们，从而避免以明文形式保护这些配置值。有关更多信息，请参阅 [从 AWS 参数存储中获取配置](#fetch-config)。  
`hsm.greengrassPkcsPluginJar`  
您下载到 IDT 主机的 [PKCS\$111 提供程序组件](pkcs11-provider-component.md)的完整路径。 AWS IoT Greengrass 将此组件作为 JAR 文件提供，您可以下载该文件以在安装过程中将其指定为预置插件。您可以通过以下 URL 下载该组件 JAR 文件的最新版本：[https://d2s8p88vqu9w66.cloudfront。 net/releases/Pkcs11Provider/aws.greengrass.crypto.pkcs11Provider](https://d2s8p88vqu9w66.cloudfront.net/releases/Pkcs11Provider/aws.greengrass.crypto.Pkcs11Provider-latest.jar)-latest.jar。  
`hsm.pkcs11ProviderLibrary`  
硬件安全模块（HSM）供应商提供的 PKCS\$111 库的完整路径，用于与 HSM 交互。  
`hsm.slotId`  
用于识别要加载密钥和证书的 HSM 槽的槽 ID。  
`hsm.slotLabel`  
用于识别要加载密钥和证书的 HSM 槽的槽标签。  
`hsm.slotUserPin`  
IDT 用来向 HSM 验证 AWS IoT Greengrass 核心软件的用户 PIN。  
作为安全最佳实践，请勿在生产设备上使用同一用户 PIN。  
`hsm.keyLabel`  
用于标识硬件模块中的键的标签。密钥和证书必须使用相同密钥标签。  
`hsm.preloadedCertificateArn`  
 AWS IoT 云中上传的设备证书的 Amazon 资源名称（ARN）。  
您之前必须使用 HSM 中的密钥生成此证书，将其导入您的 HSM，然后将其上传到云端。 AWS IoT 有关生成和导入证书的信息，请参阅您的 HSM 文档。  
您必须将证书上传到您在 [config.json](#cfg-aws-gg) 中提供的同一个账户和区域。有关将证书上传到的更多信息 AWS IoT，请参阅*《AWS IoT 开发人员指南》*中的[手动注册客户端证书](https://docs.aws.amazon.com/iot/latest/developerguide/manual-cert-registration.html)。  
`hsm.rootCAPath`  
（可选）IDT 主机上指向签署证书的根证书颁发机构（CA）的完整路径。如果您在 HSM 中创建的证书并非由 Amazon 根 CA 签名，则这是必需的。

## 从 AWS 参数存储中获取配置
<a name="fetch-config"></a>

AWS IoT 设备测试器 (IDT) 包含一项可选功能，用于从 S [AWS ystems Manager 参数存储](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html)区获取配置值。 AWS Parameter Store 允许对配置进行安全和加密的存储。配置后，IDT 可以从 Paramet AWS er Store 获取参数，而不是将参数以纯文本形式存储在文件中。`userdata.json`这对于任何应加密存储的敏感数据都很有用，例如密码、PIN 和其他密钥。

1. 要使用此功能，您必须更新创建 [IDT 用户](https://docs.aws.amazon.com/greengrass/v2/developerguide/dev-tst-prereqs.html)时使用的权限，以允许对 IDT 配置为使用的参数进行 GetParameter 操作。以下是可以添加到 IDT 用户的权限语句示例。有关更多信息，请参阅[《AWS Systems Manager 用户指南》](https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-paramstore-access.html)。

   ```
   {
          "Sid":"parameterStoreResources",
          "Effect": "Allow",
           "Action": [
               "ssm:GetParameter"
           ],
           "Resource": "arn:aws:ssm:*:*:parameter/IDT*"
   }
   ```

   配置以上权限是为了允许使用通配符 `*` 获取名称以 `IDT` 开头的所有参数。您应该根据自己的需要进行自定义，以便 IDT 可以根据您正在使用的参数的命名来获取任何已配置的参数。

1. 你需要将配置值存储在 P AWS aramater Store 中。这可以通过 AWS 控制台或 AWS CLI 完成。 AWS Parameter Store 允许您选择加密或未加密的存储。要存储机密、密码和 PIN 等敏感值，应使用加密选项，该选项的参数类型为 SecureString。要使用 AWS CLI 上传参数，可以使用以下命令：

   ```
   aws ssm put-parameter --name IDT-example-name --value IDT-example-value --type SecureString
   ```

   您可以使用以下命令验证是否已存储参数。（可选）使用该`--with-decryption`标志获取解密后的参数。SecureString 

   ```
   aws ssm get-parameter --name IDT-example-name
   ```

   使用 AWS CLI 将上传当前 CLI 用户 AWS 所在区域中的参数，IDT 将从中`config.json`配置的区域获取参数。要通过 AWS CLI 查看您所在的区域，请使用以下命令：

   ```
   aws configure get region
   ```

1. 在 AWS 云端拥有配置值后，您可以更新 IDT 配置中的任何值以从 AWS 云端获取。为此，您可以在表单`{{AWS.Parameter.parameter_name}}`的 IDT 配置中使用占位符从 Parameter Store 中按该名称获取 AWS 参数。

   例如，假设您要在 HSM 配置中使用步骤 2 中的 `IDT-example-name` 参数作为 HSM keyLabel。为此，可以按以下方式更新 `userdata.json`：

   ```
   "hsm": {
           "keyLabel": "{{AWS.Parameter.IDT-example-name}}",
           [...]
       }
   ```

   IDT 将在运行时获取步骤 2 中设置为 `IDT-example-value` 的此参数的值。此配置与设置类似，`"keyLabel": "IDT-example-value"`但相反，该值以加密形式存储在 AWS 云中。

# 运行 AWS IoT Greengrass 资格套件
<a name="run-tests"></a>

[设置所需的配置](set-config.md)后，就可以开始测试了。完整测试套件的运行时取决于您的硬件。作为参考，在 Raspberry Pi 3B 上完成完整的测试套件大约需要 30 分钟。

使用以下 `run-suite` 命令运行一系列测试。

```
devicetester_[linux | mac | win]_x86-64 run-suite  \\
    --suite-id suite-id  \\
    --group-id group-id  \\
    --pool-id your-device-pool \\
    --test-id test-id  \\
    --update-idt y|n  \\
    --userdata userdata.json
```

所有选项均为可选。例如，如果您只有一个设备池（即 `device.json` 文件中定义的一组相同设备），则可以忽略 `pool-id`。或者，如果您要在 `tests` 文件夹中运行最新的测试套件版本，则可以忽略 `suite-id`。

**注意**  
如果在线提供了更新的测试套件版本，IDT 会提示您。有关更多信息，请参阅 [测试套件版本](idt-greengrass-qualification.md#idt-test-suite-versions)。

## 用于运行资格认证套件的示例命令
<a name="idt-run-suite-examples"></a>

以下命令行示例介绍如何针对某个设备池运行资格认证测试。有关 `run-suite` 和其他 IDT 命令的更多信息，请参阅 [AWS IoT Greengrass V2 命令的 IDT](#bk-cli)。

使用以下命令在指定的测试套件中运行所有测试组。`list-suites` 命令可列出 `tests` 文件夹中的测试套件。

```
devicetester_[linux | mac | win]_x86-64 run-suite \
    --suite-id GGV2Q_1.0.0 \
    --pool-id <pool-id> \
    --userdata userdata.json
```

使用以下命令运行测试套件中的特定测试组。`list-groups` 命令可列出测试套件中的测试组。

```
devicetester_[linux | mac | win]_x86-64 run-suite \
    --suite-id GGV2Q_1.0.0 \
    --group-id <group-id> \
    --pool-id <pool-id> \
    --userdata userdata.json
```

使用以下命令运行测试组中的特定测试案例。

```
devicetester_[linux | mac | win]_x86-64 run-suite \
    --group-id <group-id> \
    --test-id <test-id> \
    --userdata userdata.json
```

使用以下命令运行测试组中的多个测试案例。

```
devicetester_[linux | mac | win]_x86-64 run-suite \
    --group-id <group-id> \
    --test-id <test-id1>,<test-id2>
    --userdata userdata.json
```

使用以下命令列出测试组中的所有测试案例。

```
devicetester_[linux | mac | win]_x86-64 list-test-cases --group-id <group-id>
```

建议您运行完整的资格认证测试套件，该套件会按正确的顺序运行测试组依赖关系。如果您选择运行特定测试组，建议您先运行依赖关系检查程序测试组，以确保在运行相关测试组之前已安装所有 Greengrass 依赖关系。例如：
+ 在运行核心资格测试组之前运行 `coredependencies`。

## AWS IoT Greengrass V2 命令的 IDT
<a name="bk-cli"></a>

IDT 命令位于 `<device-tester-extract-location>/bin` 目录中。要运行测试套件，请按以下格式提供命令：

`help`  <a name="idt-command-help"></a>
列出有关指定命令的信息。

`list-groups`  <a name="idt-command-list-groups"></a>
列出给定测试套件中的组。

`list-suites`  <a name="idt-command-list-suites"></a>
列出可用的测试套件。

`list-supported-products`  
列出当前 IDT AWS IoT Greengrass 版本支持的产品（在本例中为版本）和测试套件版本。

`list-test-cases`  
列出给定测试组中的测试用例。支持以下选项：  
+ `group-id`. 要搜索的测试组。此选项是必需的，必须指定单个组。

`run-suite`  
对某个设备池运行一组测试。以下是一些受支持的选项：  
+ `suite-id`. 要运行的测试套件版本。如果未指定，IDT 将使用 `tests` 文件夹中的最新版本。
+ `group-id`. 要以逗号分隔的列表形式运行的测试组。如果未指定，IDT 将运行测试套件中的所有相应测试组，具体取决于 `device.json` 中已配置的设置。IDT 不会根据您配置的设置运行设备不支持的任何测试组，即使这些测试组是在 `group-id` 列表中指定的。
+ `test-id`. 要以逗号分隔的列表形式运行的测试用例。指定后，`group-id` 必须指定单个组。
+ `pool-id`. 要测试的设备池。如果您在 `device.json` 文件中定义了多个设备池，则必须指定一个池。
+ `stop-on-first-failure`。将 IDT 配置为在第一次失败时停止运行。当您想要调试指定的测试组时，请将此选项与 `group-id` 配合使用。在运行完整测试套件以生成资格认证报告时，请勿使用此选项。
+ `update-idt`。为更新 IDT 的提示设置响应。如果 IDT 检测到有更新的版本，则 `Y` 响应将停止执行测试。`N` 响应会继续执行测试。
+ `userdata`。包含有关测试构件路径的信息的 `userdata.json` 文件的完整路径。此选项是 `run-suite` 命令所必需的。该`userdata.json`文件必须位于 /devic *devicetester\$1extract\$1location* etester\$1ggv2\$1 /c *[win\$1mac\$1linux]* onfigs/ 目录中。
有关 `run-suite` 选项的更多信息，请使用 `help` 选项：  

```
devicetester_[linux | mac | win]_x86-64 run-suite -h
```

# 了解结果和日志
<a name="results-logs"></a>

本节介绍如何查看和解释 IDT 结果报告和日志。

要对错误进行故障排查，请参阅[V2 版 IDT 故障排除 AWS IoT Greengrass](idt-troubleshooting.md)。

## 查看结果
<a name="view-results"></a>

在运行时，IDT 会将错误写入控制台、日志文件和测试报告中。IDT 在完成资格测试套件后，会生成两个测试报告。这些报告位于 `<device-tester-extract-location>/results/<execution-id>/` 下。两个报告都捕获资格认证测试套件运行的结果。

`awsiotdevicetester_report.xml` 是您提交给 AWS 的资格测试报告，用于在 AWS Partner 设备目录中列出您的设备。该报告包含以下元素：
+ IDT 版本。
+ 所测试的 AWS IoT Greengrass 版本。
+ `device.json` 文件中指定的 SKU 和设备池名称。
+ `device.json` 文件中指定的设备池的功能。
+ 测试结果的摘要汇总。
+ 按照基于设备功能（例如，本地资源访问、影子、MQTT）测试的库细分的测试结果。

`GGV2Q_Result.xml` 报告采用 [JUnit XML 格式](https://llg.cubic.org/docs/junit/)。您可以将它集成到持续集成和开发平台，例如 [Jenkins](https://jenkins.io/)、[Bamboo](https://www.atlassian.com/software/bamboo) 等。该报告包含以下元素：
+ 测试结果的摘要汇总。
+ 按照已测试的 AWS IoT Greengrass 功能细分的测试结果。

## 解析 AWS IoT Device Tester 结果
<a name="interpreting-results-gg"></a>

`awsiotdevicetester_report.xml` 或 `awsiotdevicetester_report.xml` 中的报告部分列出了运行的测试以及结果。

第一个 XML 标签 `<testsuites>` 包含测试运行情况的摘要。例如：

```
<testsuites name="GGQ results" time="2299" tests="28" failures="0" errors="0" disabled="0">
````<testsuites>` 标签中使用的属性

`name`  
测试套件的名称。

`time`  
运行资格认证套件所用的时间（以秒为单位）。

`tests`  
已运行的测试数。

`failures`  
已运行但未通过的测试数。

`errors`  
IDT 无法运行的测试数。

`disabled`  
忽略此属性。不会使用。

`awsiotdevicetester_report.xml` 文件包含一个 `<awsproduct>` 标签，其中包含有关正测试的产品以及在运行测试套件后验证的产品功能的信息。`<awsproduct>` 标签中使用的属性

`name`  
所测试的产品的名称。

`version`  
所测试的产品的版本。

`features`  
验证的功能。标记为 `required` 的功能需要提交您的主板信息以供资格审核。以下代码段演示了此信息在 `awsiotdevicetester_report.xml` 文件中的显示方式。  

```
<name="aws-iot-greengrass-v2-core" value="supported" type="required"></feature>
```

如果没有针对所需功能的测试失败或错误，则设备满足运行 AWS IoT Greengrass 的技术要求并可以与 AWS IoT 服务互操作。如果您想要在 AWS Partner 设备目录中列出您的设备，则可以使用此报告作为资格证明。

如果出现测试失败或错误，则可以通过检查 `<testsuites>` XML 标签来确定失败的测试。`<testsuite>` 标签内的 `<testsuites>` XML 标签显示了测试组的测试结果摘要。例如：

```
<testsuite name="combination" package="" tests="1" failures="0" time="161" disabled="0" errors="0" skipped="0">
```

其格式与 `<testsuites>` 标签类似，但包含一个未使用并可忽略的 `skipped` 属性。在每个 `<testsuite>` XML 标签内部，对于一个测试组，所运行的每个测试都有 `<testcase>` 标签。例如：

```
<testcase classname="Security Combination (IPD + DCM) Test Context" name="Security Combination IP Change Tests sec4_test_1: Should rotate server cert when IPD disabled and following changes are made:Add CIS conn info and Add another CIS conn info" attempts="1"></testcase>>
````<testcase>` 标签中使用的属性

`name`  
测试的名称。

`attempts`  
IDT 运行测试用例的次数。

当测试失败或出现错误时，将会在 `<failure>` 标签中添加包含用于故障排除的信息的 `<error>` 或 `<testcase>` 标签。例如：

```
<testcase classname="mcu.Full_MQTT" name="AFQP_MQTT_Connect_HappyCase" attempts="1">
	<failure type="Failure">Reason for the test failure</failure>
	<error>Reason for the test execution error</error>
</testcase>
```

## 查看日志
<a name="view-logs-gg"></a>

IDT 从测试运行生成的日志位于 `<devicetester-extract-location>/results/<execution-id>/logs` 中。它会生成两组日志：

`test_manager.log`  
从 AWS IoT Device Tester 的 Test Manager 组件生成的日志（例如，与配置、测试序列和报告生成相关的日志）。

`<test-case-id>.log (for example, lambdaDeploymentTest.log)`  
测试组内测试用例的日志，包括来自所测试设备的日志。从 IDT v4.2.0 开始，IDT 会将每个测试用例的测试日志归类到 `<devicetester-extract-location>/results/<execution-id>/logs/<test-group-id>/` 目录下的单独 *<test-case-id>* 文件夹中。

# 使用 IDT 开发和运行自己的测试套件
<a name="idt-custom-tests"></a>

<a name="idt-byotc"></a>从 IDT v4.0.1 开始，IDT for AWS IoT Greengrass V2 将标准化配置设置和结果格式与测试套件环境相结合，使您能够为设备和设备软件开发自定义测试套件。您可以添加自定义测试来用于自己的内部验证，也可以将其提供给客户进行设备验证。

使用 IDT 开发和运行自定义测试套件，如下所示：

**开发自定义测试套件**  
+ 使用自定义测试逻辑为要测试的 Greengrass 设备创建测试套件。
+ 向 IDT 提供您的自定义测试套件以供测试运行者使用。包括有关测试套件的特定设置配置的信息。

**运行自定义测试套件**  
+ 设置要测试的设备。
+ 根据要使用的测试套件的要求实现设置配置。
+ 使用 IDT 运行您的自定义测试套件。
+ 查看 IDT 运行的测试的测试结果和执行日志。

## 下载 for 的最新版本 AWS IoT Device Tester AWS IoT Greengrass
<a name="install-dev-tst-gg"></a>

下载[最新版本的](idt-programmatic-download.md) IDT，并将软件解压缩到文件系统上您拥有读/写权限的位置 (*<device-tester-extract-location>*)。

**注意**  
<a name="unzip-package-to-local-drive"></a>IDT 不支持由多个用户从共享位置（如 NFS 目录或 Windows 网络共享文件夹）运行。建议您将 IDT 包解压缩到本地驱动器，并在本地工作站上运行 IDT 二进制文件。  
Windows 的路径长度限制为 260 个字符。如果您使用的是 Windows，请将 IDT 提取到根目录（如 `C:\ ` 或 `D:\`）以使路径长度不超过 260 个字符的限制。

## 测试套件创建工作流程
<a name="custom-test-workflow"></a>

测试套件由三种类型的文件组成：
+ 为 IDT 提供有关如何运行测试套件的信息的配置文件。
+ 测试 IDT 用来运行测试用例的可执行文件。
+ 运行测试所需的其他文件。

完成以下基本步骤来创建自定义 IDT 测试：

1. 为测试套件[创建配置文件](idt-json-config.md)。

1. [创建包含测试套件测试逻辑的测试用例可执行文件](create-test-executables.md)。

1. 验证并记录[测试运行器运行测试套件所需的配置信息](set-custom-idt-config.md)。

1. 验证 IDT 能否按预期运行您的测试套件并生成[测试结果](run-debug-custom-tests.md)。

要快速构建示例自定义套件并运行它，请按照 [教程：构建和运行示例 IDT 测试套件](build-sample-suite.md) 中的说明进行操作。

要开始使用 Python 创建自定义测试套件，请参阅[教程：开发一个简单的 IDT 测试套件](create-custom-tests.md)。

# 教程：构建和运行示例 IDT 测试套件
<a name="build-sample-suite"></a>

 AWS IoT Device Tester 下载内容包括示例测试套件的源代码。您可以完成本教程来构建和运行示例测试套件，以了解如何使用 IDT AWS IoT Greengrass 来运行自定义测试套件。

 在本教程中，您将完成以下步骤：

1. [构建示例测试套件](#build-sample)

1. [使用 IDT 运行示例测试套件](#run-sample)

## 先决条件
<a name="prereqs-tutorial-sample"></a><a name="prereqs-list"></a>

要完成本教程，您需要：
+ 

**主机要求**
  + 最新版本的 AWS IoT Device Tester
  + [Python](https://www.python.org/downloads/) 3.7 或更高版本

    要检查您计算机安装的 Python 版本，请运行以下命令：

    ```
    python3 --version
    ```

    在 Windows 上，如果运行此命令时返回错误，则可改用 `python --version`。如果返回的版本号为 3.7 或更高版本，则可通过在 Powershell 终端中运行以下命令将 `python3` 设置为 `python` 命令的别名。

    ```
    Set-Alias -Name "python3" -Value "python"
    ```

    如果没有返回版本信息，或者版本号小于 3.7，则按照[下载 Python](https://wiki.python.org/moin/BeginnersGuide/Download) 中的说明安装 Python 3.7\$1。有关更多信息，请参阅 [Python 文档](https://docs.python.org)。
  + [urllib3](https://urllib3.readthedocs.io/en/latest/)

    要验证 `urllib3` 是否已正确安装，请运行以下命令：

    ```
    python3 -c 'import urllib3'
    ```

    如果未安装 `urllib3`，请运行以下命令进行安装：

    ```
    python3 -m pip install urllib3
    ```
+ 

**设备要求**
  + 一种运行 Linux 操作系统的设备，其网络连接到与您主机相同的网络。

    我们建议您使用搭载 Raspberry Pi 操作系统的 [Raspberry Pi](https://www.raspberrypi.org/)。请确保您设置 Raspberry Pi 上的 [SSH](https://www.raspberrypi.org/documentation/remote-access/ssh/) 才能远程连接到它。

## 配置 IDT 的设备信息
<a name="configure-idt-sample"></a>

配置您的设备信息，以便 IDT 运行测试。您必须使用以下信息，更新位于 `<device-tester-extract-location>/configs` 文件夹中的 `device.json` 模板。

```
[
  {
    "id": "pool",
    "sku": "N/A",
    "devices": [
      {
        "id": "<device-id>",
        "connectivity": {
          "protocol": "ssh",
          "ip": "<ip-address>",
          "port": "<port>",
          "auth": {
            "method": "pki | password",
            "credentials": {
              "user": "<user-name>",
              "privKeyPath": "/path/to/private/key",
              "password": "<password>"
            }
          }
        }
      }
    ]
  }
]
```

在 `devices` 对象中，提供以下信息：

`id`  
专属于您设备的用户定义唯一标识符。

`connectivity.ip`  
您设备的 IP 地址。

`connectivity.port`  
可选。用于通过 SSH 连接到您的设备的端口号。

`connectivity.auth`  
连接的身份验证信息。  
此属性仅在 `connectivity.protocol` 设置为 `ssh` 时适用。    
`connectivity.auth.method`  
用于通过给定的连接协议访问设备的身份验证方法。  
支持的值为：  
+ `pki`
+ `password`  
`connectivity.auth.credentials`  
用于身份验证的凭证。    
`connectivity.auth.credentials.user`  
用于登录您的设备的用户名。  
`connectivity.auth.credentials.privKeyPath`  
用于登录您设备的私有密钥的完整路径。  
此值仅在 `connectivity.auth.method` 设置为 `pki` 时适用。  
`devices.connectivity.auth.credentials.password`  
该密码用于登录到您的设备。  
此值仅在 `connectivity.auth.method` 设置为 `password` 时适用。

**注意**  
只有当 `method` 设置为 `pki` 时才指定 `privKeyPath`。  
只有当 `method` 设置为 `password` 时才指定 `password`。

## 构建示例测试套件
<a name="build-sample"></a>

`<device-tester-extract-location>/samples/python` 文件夹包含示例配置文件、源代码和 IDT 客户端软件开发工具包，您可以使用提供的构建脚本将其组合成一个测试套件。以下目录树显示了这些示例文件的位置：

```
<device-tester-extract-location>
├── ...
├── tests
├── samples
│   ├── ...
│   └── python
│       ├── configuration
│       ├── src
│       └── build-scripts
│           ├── build.sh
│           └── build.ps1
└── sdks
    ├── ...
    └── python
        └── idt_client
```

要构建测试套件，请在主机上运行以下命令：

------
#### [ Windows ]

```
cd <device-tester-extract-location>/samples/python/build-scripts
./build.ps1
```

------
#### [ Linux, macOS, or UNIX ]

```
cd <device-tester-extract-location>/samples/python/build-scripts
./build.sh
```

------

这将在该 `<device-tester-extract-location>/tests` 文件夹下的 `IDTSampleSuitePython_1.0.0` 文件夹中创建示例测试套件。检查 `IDTSampleSuitePython_1.0.0` 文件夹中的文件，以了解示例测试套件的结构，并查看测试用例可执行文件和测试配置 JSON 文件的各种示例。

**注意**  
示例测试套件包含 python 源代码。请勿在测试套件代码中包含敏感信息。

下一步：使用 IDT [运行您创建的示例测试套件](#run-sample)。

## 使用 IDT 运行示例测试套件
<a name="run-sample"></a>

要运行示例测试套件，请在主机上运行以下命令：

```
cd <device-tester-extract-location>/bin
./devicetester_[linux | mac | win_x86-64] run-suite --suite-id IDTSampleSuitePython
```

IDT 会运行示例测试套件，并将结果流式传输到控制台。测试运行完毕后，您会看到以下信息：

```
========== Test Summary ==========
Execution Time:         5s
Tests Completed:        4
Tests Passed:           4
Tests Failed:           0
Tests Skipped:          0
----------------------------------
Test Groups:
    sample_group:       PASSED
----------------------------------
Path to IoT Device Tester Report: /path/to/devicetester/results/87e673c6-1226-11eb-9269-8c8590419f30/awsiotdevicetester_report.xml
Path to Test Execution Logs: /path/to/devicetester/results/87e673c6-1226-11eb-9269-8c8590419f30/logs
Path to Aggregated JUnit Report: /path/to/devicetester/results/87e673c6-1226-11eb-9269-8c8590419f30/IDTSampleSuitePython_Report.xml
```

## 问题排查
<a name="tutorial-troubleshooting-custom"></a>

使用以下信息，以帮助解决在完成本教程时遇到的任何问题。

**测试用例未成功运行**  
如果测试运行失败，IDT 会将错误日志流式传输到控制台，以帮助您对测试运行进行故障排除。请确保满足本教程的所有[先决条件](#prereqs-tutorial-sample)。

**无法连接到被测设备**

请验证以下内容：
+ 您的 `device.json` 文件包含正确的 IP 地址、端口和身份验证信息。
+ 您可以通过 SSH 从主机连接到您的设备。

# 教程：开发一个简单的 IDT 测试套件
<a name="create-custom-tests"></a>

测试套件结合了以下内容：
+ 包含测试逻辑的测试可执行文件
+ 描述测试套件的配置文件

本教程向您展示如何使用 IDT AWS IoT Greengrass 来开发包含单个测试用例的 Python 测试套件。在本教程中，您将完成以下步骤：

1. [创建测试套件目录](#test-suite-dir)

1. [创建配置文件](#test-suite-json)

1. [创建测试用例可执行文件](#test-suite-exe)

1. [运行测试套件](#run-test-suite)

## 先决条件
<a name="prereqs-tutorial-custom"></a><a name="prereqs-list"></a>

要完成本教程，您需要：
+ 

**主机要求**
  + 最新版本的 AWS IoT Device Tester
  + [Python](https://www.python.org/downloads/) 3.7 或更高版本

    要检查您计算机安装的 Python 版本，请运行以下命令：

    ```
    python3 --version
    ```

    在 Windows 上，如果运行此命令时返回错误，则可改用 `python --version`。如果返回的版本号为 3.7 或更高版本，则可通过在 Powershell 终端中运行以下命令将 `python3` 设置为 `python` 命令的别名。

    ```
    Set-Alias -Name "python3" -Value "python"
    ```

    如果没有返回版本信息，或者版本号小于 3.7，则按照[下载 Python](https://wiki.python.org/moin/BeginnersGuide/Download) 中的说明安装 Python 3.7\$1。有关更多信息，请参阅 [Python 文档](https://docs.python.org)。
  + [urllib3](https://urllib3.readthedocs.io/en/latest/)

    要验证 `urllib3` 是否已正确安装，请运行以下命令：

    ```
    python3 -c 'import urllib3'
    ```

    如果未安装 `urllib3`，请运行以下命令进行安装：

    ```
    python3 -m pip install urllib3
    ```
+ 

**设备要求**
  + 一种运行 Linux 操作系统的设备，其网络连接到与您主机相同的网络。

    我们建议您使用搭载 Raspberry Pi 操作系统的 [Raspberry Pi](https://www.raspberrypi.org/)。请确保您设置 Raspberry Pi 上的 [SSH](https://www.raspberrypi.org/documentation/remote-access/ssh/) 才能远程连接到它。

## 创建测试套件目录
<a name="test-suite-dir"></a>

IDT 在逻辑上将测试用例分成每个测试套件中的测试组。每个测试用例都必须位于测试组中。在本教程中，创建一个名为 `MyTestSuite_1.0.0` 的文件夹，并在此文件夹中创建以下目录树：

```
MyTestSuite_1.0.0
└── suite
    └── myTestGroup
        └── myTestCase
```

## 创建配置文件
<a name="test-suite-json"></a>

您的测试套件必须包含以下必需的[配置文件](idt-json-config.md)：<a name="required-json"></a>必需配置文件

`suite.json`  
包含有关测试套件的信息。请参阅[配置 suite.json](idt-json-config.md#suite-json)。

`group.json`  
包含有关测试组的信息。您必须为测试套件中的每个测试组创建一个 `group.json` 文件。请参阅[配置 group.json](idt-json-config.md#group-json)。

`test.json`  
包含有关测试用例的信息。您必须为测试套件中的每个测试用例创建一个 `test.json` 文件。请参阅[配置 test.json](idt-json-config.md#test-json)。

1. 在 `MyTestSuite_1.0.0/suite` 文件夹中，创建以下文件夹结构的 `suite.json`：

   ```
   {
       "id": "MyTestSuite_1.0.0",
       "title": "My Test Suite",
       "details": "This is my test suite.",
       "userDataRequired": false
   }
   ```

1. 在 `MyTestSuite_1.0.0/myTestGroup` 文件夹中，创建以下文件夹结构的 `group.json`：

   ```
   {
       "id": "MyTestGroup",
       "title": "My Test Group",
       "details": "This is my test group.",
       "optional": false
   }
   ```

1. 在 `MyTestSuite_1.0.0/myTestGroup/myTestCase` 文件夹中，创建以下文件夹结构的 `test.json`：

   ```
   {
       "id": "MyTestCase",
       "title": "My Test Case",
       "details": "This is my test case.",
       "execution": {
           "timeout": 300000,
           "linux": {
               "cmd": "python3",
               "args": [
                   "myTestCase.py"
               ]
           },
           "mac": {
               "cmd": "python3",
               "args": [
                   "myTestCase.py"
               ]
           },
           "win": {
               "cmd": "python3",
               "args": [
                   "myTestCase.py"
               ]
           }
       }
   }
   ```

您的 `MyTestSuite_1.0.0` 文件夹应类似于以下内容：

```
MyTestSuite_1.0.0
└── suite
    ├── suite.json
    └── myTestGroup
        ├── group.json
        └── myTestCase
            └── test.json
```

## 获取 IDT 客户端 SDK
<a name="add-idt-sdk"></a>

您可以使用 [IDT 客户端 SDK](create-test-executables.md#idt-client-sdk) 让 IDT 与被测设备进行交互并报告测试结果。在本教程中，您将使用 Python 版本的软件开发工具包。

从 `<device-tester-extract-location>/sdks/python/` 文件夹，将 `idt_client` 文件夹复制到您的 `MyTestSuite_1.0.0/suite/myTestGroup/myTestCase` 文件夹。

要验证 SDK 是否复制，可以运行以下命令。

```
cd MyTestSuite_1.0.0/suite/myTestGroup/myTestCase
python3 -c 'import idt_client'
```

## 创建测试用例可执行文件
<a name="test-suite-exe"></a>

测试用例可执行文件包含要运行的测试逻辑。一个测试套件可以包含多个测试用例可执行文件。在本教程中，您将只创建一个测试用例可执行文件。

1. 创建测试套件文件。

   在 `MyTestSuite_1.0.0/suite/myTestGroup/myTestCase` 文件夹中，创建使用以下内容的 `myTestCase.py` 文件：

   ```
   from idt_client import *
   
   def main():
       # Use the client SDK to communicate with IDT
       client = Client()
   
   if __name__ == "__main__":
       main()
   ```

1. 使用客户端 SDK 函数将以下测试逻辑添加到您的 `myTestCase.py` 文件中：

   1. 在被测设备上运行 SSH 命令。

      ```
      from idt_client import *
      
      def main():
          # Use the client SDK to communicate with IDT
          client = Client()
          
          # Create an execute on device request
          exec_req = ExecuteOnDeviceRequest(ExecuteOnDeviceCommand("echo 'hello world'"))
          
          # Run the command
          exec_resp = client.execute_on_device(exec_req)
          
          # Print the standard output
          print(exec_resp.stdout)
      
      if __name__ == "__main__":
          main()
      ```

   1. 将测试结果发送给 IDT。

      ```
      from idt_client import *
      
      def main():
          # Use the client SDK to communicate with IDT
          client = Client()
          
          # Create an execute on device request
          exec_req = ExecuteOnDeviceRequest(ExecuteOnDeviceCommand("echo 'hello world'"))
          
          # Run the command
          exec_resp = client.execute_on_device(exec_req)
          
          # Print the standard output
          print(exec_resp.stdout)
      
          # Create a send result request
          sr_req = SendResultRequest(TestResult(passed=True))
           
          # Send the result
          client.send_result(sr_req)
             
      if __name__ == "__main__":
          main()
      ```

## 配置 IDT 的设备信息
<a name="configure-idt-sample"></a>

配置您的设备信息，以便 IDT 运行测试。您必须使用以下信息，更新位于 `<device-tester-extract-location>/configs` 文件夹中的 `device.json` 模板。

```
[
  {
    "id": "pool",
    "sku": "N/A",
    "devices": [
      {
        "id": "<device-id>",
        "connectivity": {
          "protocol": "ssh",
          "ip": "<ip-address>",
          "port": "<port>",
          "auth": {
            "method": "pki | password",
            "credentials": {
              "user": "<user-name>",
              "privKeyPath": "/path/to/private/key",
              "password": "<password>"
            }
          }
        }
      }
    ]
  }
]
```

在 `devices` 对象中，提供以下信息：

`id`  
专属于您设备的用户定义唯一标识符。

`connectivity.ip`  
您设备的 IP 地址。

`connectivity.port`  
可选。用于通过 SSH 连接到您的设备的端口号。

`connectivity.auth`  
连接的身份验证信息。  
此属性仅在 `connectivity.protocol` 设置为 `ssh` 时适用。    
`connectivity.auth.method`  
用于通过给定的连接协议访问设备的身份验证方法。  
支持的值为：  
+ `pki`
+ `password`  
`connectivity.auth.credentials`  
用于身份验证的凭证。    
`connectivity.auth.credentials.user`  
用于登录您的设备的用户名。  
`connectivity.auth.credentials.privKeyPath`  
用于登录您设备的私有密钥的完整路径。  
此值仅在 `connectivity.auth.method` 设置为 `pki` 时适用。  
`devices.connectivity.auth.credentials.password`  
该密码用于登录到您的设备。  
此值仅在 `connectivity.auth.method` 设置为 `password` 时适用。

**注意**  
只有当 `method` 设置为 `pki` 时才指定 `privKeyPath`。  
只有当 `method` 设置为 `password` 时才指定 `password`。

## 运行测试套件
<a name="run-test-suite"></a>

创建测试套件后，您需要确保其按预期运行。要使用现有设备池运行测试套件，请完成以下步骤。

1. 将您的 `MyTestSuite_1.0.0` 文件夹复制到 `<device-tester-extract-location>/tests`。

1. 运行以下 命令：

   ```
   cd <device-tester-extract-location>/bin
   ./devicetester_[linux | mac | win_x86-64] run-suite --suite-id MyTestSuite
   ```

IDT 会运行您的测试套件，并将结果流式传输到控制台。测试运行完毕后，您会看到以下信息：

```
time="2020-10-19T09:24:47-07:00" level=info msg=Using pool: pool
time="2020-10-19T09:24:47-07:00" level=info msg=Using test suite "MyTestSuite_1.0.0" for execution
time="2020-10-19T09:24:47-07:00" level=info msg=b'hello world\n' suiteId=MyTestSuite groupId=myTestGroup testCaseId=myTestCase deviceId=my-device executionId=9a52f362-1227-11eb-86c9-8c8590419f30
time="2020-10-19T09:24:47-07:00" level=info msg=All tests finished. executionId=9a52f362-1227-11eb-86c9-8c8590419f30
time="2020-10-19T09:24:48-07:00" level=info msg=

========== Test Summary ==========
Execution Time:         1s
Tests Completed:        1
Tests Passed:           1
Tests Failed:           0
Tests Skipped:          0
----------------------------------
Test Groups:
    myTestGroup:        PASSED
----------------------------------
Path to IoT Device Tester Report: /path/to/devicetester/results/9a52f362-1227-11eb-86c9-8c8590419f30/awsiotdevicetester_report.xml
Path to Test Execution Logs: /path/to/devicetester/results/9a52f362-1227-11eb-86c9-8c8590419f30/logs
Path to Aggregated JUnit Report: /path/to/devicetester/results/9a52f362-1227-11eb-86c9-8c8590419f30/MyTestSuite_Report.xml
```

## 问题排查
<a name="tutorial-troubleshooting"></a>

使用以下信息，以帮助解决在完成本教程时遇到的任何问题。

**测试用例未成功运行**

如果测试运行失败，IDT 会将错误日志流式传输到控制台，以帮助您对测试运行进行故障排除。检查错误日志之前，请验证以下内容：
+ 如[本步骤](#add-idt-sdk)所述，IDT 客户端 SDK 位于正确的文件夹中。
+ 您已满足本教程的所有[先决条件](#prereqs-tutorial-custom)。

**无法连接到被测设备**

请验证以下内容：
+ 您的 `device.json` 文件包含正确的 IP 地址、端口和身份验证信息。
+ 您可以通过 SSH 从主机连接到您的设备。

# 创建 IDT 测试套件配置文件
<a name="idt-json-config"></a>

本节介绍创建配置文件时使用的格式，您在编写自定义测试套件时包含了这些文件。<a name="required-json"></a>必需配置文件

`suite.json`  
包含有关测试套件的信息。请参阅[配置 suite.json](#suite-json)。

`group.json`  
包含有关测试组的信息。您必须为测试套件中的每个测试组创建一个 `group.json` 文件。请参阅[配置 group.json](#group-json)。

`test.json`  
包含有关测试用例的信息。您必须为测试套件中的每个测试用例创建一个 `test.json` 文件。请参阅[配置 test.json](#test-json)。可选配置文件

`test_orchestrator.yaml` 或者`state_machine.json`  
定义 IDT 运行测试套件时运行测试的方式。请参阅[配置 test\$1orchestrator.yaml](#test-orchestrator-config)。  
从 IDT v4.5.1 开始，您可以使用 `test_orchestrator.yaml` 文件来定义测试工作流程。在以前版本的 IDT 中，请使用 `state_machine.json` 文件。有关状态机的信息，请参阅[配置 IDT 状态机](idt-state-machine.md)。

`userdata_schema.json`  
定义测试运行器可以在其设置配置中包含的[`userdata.json`文件](set-custom-idt-config.md#userdata-config-custom)架构。`userdata.json` 文件用于存储运行测试所需但 `device.json` 文件中不存在的任何其他配置信息。请参阅[配置 userdata\$1schema.json](#userdata-schema-json)。

配置文件放置在您的 `<custom-test-suite-folder>` 中，如下所示。

```
<custom-test-suite-folder>
└── suite
    ├── suite.json
    ├── test_orchestrator.yaml
    ├── userdata_schema.json
    ├── <test-group-folder>
        ├── group.json
        ├── <test-case-folder>
            └── test.json
```

## 配置 suite.json
<a name="suite-json"></a>

`suite.json` 文件设置环境变量并确定运行测试套件是否需要用户数据。使用以下模板来配置您的 `<custom-test-suite-folder>/suite/suite.json` 文件：

```
{
    "id": "<suite-name>_<suite-version>",
    "title": "<suite-title>",
    "details": "<suite-details>",
    "userDataRequired": true | false,
    "environmentVariables": [
        {
            "key": "<name>",
            "value": "<value>",
        },
        ...
        {
            "key": "<name>",
            "value": "<value>",
        }
    ]
}
```

包含值的所有字段都为必填字段，如下所述：

`id`  
测试套件的唯一用户定义 ID。`id` 的值必须与 `suite.json` 文件所在的测试套件文件夹的名称相匹配。套件名称和套件版本还必须满足以下要求：  
+ `<suite-name>` 不可以包含下划线。
+ `<suite-version>` 表示为 `x.x.x`，其中 `x` 为数字。
ID 显示在 IDT 生成的测试报告中。

`title`  
此测试套件正在测试的产品或功能的用户定义名称。该名称显示在 IDT CLI 中供测试运行器使用。

`details`  
测试套件用途的简短描述。

`userDataRequired`  
定义测试运行器是否需要在 `userdata.json` 文件中包含自定义信息。如果将此值设置为 `true`，还必须将[`userdata_schema.json` 文件](#userdata-schema-json)包含在测试套件文件夹中。

`environmentVariables`  
可选。一组要为此测试套件设置的环境变量。    
`environmentVariables.key`  
环境变量的名称。  
`environmentVariables.value`  
环境变量的值。

## 配置 group.json
<a name="group-json"></a>

`group.json` 文件定义测试组是必需的还是可选的。使用以下模板来配置您的 `<custom-test-suite-folder>/suite/<test-group>/group.json` 文件：

```
{
    "id": "<group-id>",
    "title": "<group-title>",
    "details": "<group-details>",
    "optional": true | false,
}
```

包含值的所有字段都为必填字段，如下所述：

`id`  
测试组的唯一用户定义 ID。`id` 的值必须与 `group.json` 文件所在的测试组文件夹的名称相匹配，并且不得包含下划线（`_`）。ID 用于 IDT 生成的测试报告中。

`title`  
测试组的描述性名称。该名称显示在 IDT CLI 中供测试运行器使用。

`details`  
测试组用途的简短描述。

`optional`  
可选。设置为 `true` 以便在 IDT 完成运行所需测试后，将此测试组显示为可选组。默认值为 `false`。

## 配置 test.json
<a name="test-json"></a>

`test.json` 文件确定测试用例的可执行文件和测试用例使用的环境变量。有关创建测试用例可执行文件的更多信息，请参阅 [创建 IDT 测试用例可执行文件](create-test-executables.md)。

使用以下模板来配置您的 `<custom-test-suite-folder>/suite/<test-group>/<test-case>/test.json` 文件：

```
{
    "id": "<test-id>",
    "title": "<test-title>",
    "details": "<test-details>",
    "requireDUT": true | false,
    "requiredResources": [
        {
            "name": "<resource-name>",
            "features": [
                {
                    "name": "<feature-name>",
                    "version": "<feature-version>",
                    "jobSlots": <job-slots>
                }
            ]
        }
    ],
    "execution": {
        "timeout": <timeout>,
        "mac": {
            "cmd": "/path/to/executable",
            "args": [
                "<argument>"
            ],
        },
        "linux": {
            "cmd": "/path/to/executable",
            "args": [
                "<argument>"
            ],
        },
        "win": {
            "cmd": "/path/to/executable",
            "args": [
                "<argument>"
            ]
        }
    },
    "environmentVariables": [
        {
            "key": "<name>",
            "value": "<value>",
        }
    ]
}
```

包含值的所有字段都为必填字段，如下所述：

`id`  
测试用例的唯一用户定义 ID。`id` 的值必须与 `test.json` 文件所在的测试用例文件夹的名称相匹配，并且不得包含下划线（`_`）。ID 用于 IDT 生成的测试报告中。

`title`  
测试用例的描述性名称。该名称显示在 IDT CLI 中供测试运行器使用。

`details`  
测试用例用途的简短描述。

`requireDUT`  
可选。如果需要设备才能运行此测试，则设置为 `true`，否则设置为 `false`。默认值为 `true`。测试运行器将在其 `device.json` 文件中配置将用来运行测试的设备。

`requiredResources`  
可选。一个阵列，提供有关运行此测试所需资源设备的信息。    
`requiredResources.name`  
运行此测试时为资源设备提供的唯一名称。  
`requiredResources.features`  
一系列用户定义的资源设备功能。    
`requiredResources.features.name`  
功能的名称。您要使用此设备的设备功能。此名称与 `resource.json` 文件中测试运行器提供的功能名称相匹配。  
`requiredResources.features.version`  
可选。功能的版本。此值与 `resource.json` 文件中测试运行器提供的功能版本相匹配。如果未提供版本，则不检查该功能。如果功能不需要版本号，请将此字段留为空白。  
`requiredResources.features.jobSlots`  
可选。此功能可以支持的同时测试的数量。默认值为 `1`。如果您希望 IDT 使用不同的设备来实现各项功能，我们建议您将此值设置为 `1`。

`execution.timeout`  
IDT 等待测试完成运行的时间长度（以毫秒为单位）。有关设置该值的更多信息，请参阅 [创建 IDT 测试用例可执行文件](create-test-executables.md)。

`execution.os`  
要运行的测试用例可执行文件基于运行 IDT 的主机操作系统。支持的值有`linux`、`mac`和`win`。    
`execution.os.cmd`  
要在指定操作系统上运行的测试用例可执行文件的路径。此位置必须位于系统路径中。  
`execution.os.args`  
可选。为运行测试用例可执行文件而提供的参数。

`environmentVariables`  
可选。一组要为此测试用例设置的环境变量。    
`environmentVariables.key`  
环境变量的名称。  
`environmentVariables.value`  
环境变量的值。
如果在 `test.json` 文件和 `suite.json` 文件中指定相同的环境变量，则 `test.json` 文件中的值优先。

## 配置 test\$1orchestrator.yaml
<a name="test-orchestrator-config"></a>

测试编排工具是一种控制测试套件执行流程的构造。它决定测试套件的起始状态，根据用户定义的规则管理状态转换，并继续在这些状态之间进行转换，直到达到结束状态。

如果您的测试套件不包含用户定义的测试编排工具，IDT 将为您生成一个测试编排工具。

默认测试编排工具执行以下功能：
+ 使测试运行器能够选择和运行特定的测试组，而不是整个测试套件。
+ 如果未选择特定的测试组，则按随机顺序运行测试套件中的每个测试组。
+ 生成报告并打印控制台摘要，其中显示每个测试组和测试用例的测试结果。

有关 IDT 测试编排工具工作原理的更多信息，请参阅[配置 IDT 测试编排工具](idt-test-orchestrator.md)。

## 配置 userdata\$1schema.json
<a name="userdata-schema-json"></a>

`userdata_schema.json` 文件确定了测试运行器提供用户数据的架构。如果您的测试套件需要 `device.json` 文件中不存在的信息，则需要用户数据。例如，您的测试可能需要 Wi-Fi 网络凭证、特定的开放端口或用户必须提供的证书。此信息可提供给 IDT，作为用户在其 `<device-tester-extract-location>/config` 文件夹中创建的输入参数，称为 `userdata`，其值是一个 `userdata.json` 文件。`userdata.json` 文件的格式取决于您在测试套件中包含的 `userdata_schema.json` 文件。

要指示测试运行器必须提供 `userdata.json` 文件：

1. 在 `suite.json` 文件中设置 `userDataRequired` 为 `true`。

1. 在您的 `<custom-test-suite-folder>` 中，创建一个 `userdata_schema.json` 文件。

1. 编辑 `userdata_schema.json` 文件以创建有效的 [IETF 草稿 v4 JSON 架构](https://json-schema.org/specification-links.html#draft-4)。

当 IDT 运行您的测试套件时，它会自动读取架构并使用它来验证测试运行器提供的 `userdata.json` 文件。如果有效，则 `userdata.json` 文件的内容在 [IDT 上下文](idt-context.md)和[测试编排工具上下文](idt-state-machine.md#state-machine-context)中均可用。

# 配置 IDT 测试编排工具
<a name="idt-test-orchestrator"></a>

从 IDT v4.5.1 开始，IDT 包括一个新的*测试编排工具*组件。测试编排工具是一个 IDT 组件，用于控制测试套件的执行流程，并在 IDT 完成运行所有测试后生成测试报告。测试编排工具根据用户定义的规则确定测试选择和测试的运行顺序。

如果您的测试套件不包含用户定义的测试编排工具，IDT 将为您生成一个测试编排工具。

默认测试编排工具执行以下功能：
+ 使测试运行器能够选择和运行特定的测试组，而不是整个测试套件。
+ 如果未选择特定的测试组，则按随机顺序运行测试套件中的每个测试组。
+ 生成报告并打印控制台摘要，其中显示每个测试组和测试用例的测试结果。

测试编排工具取代 IDT 测试编排工具。我们强烈建议您使用测试编排工具来开发测试套件，而不是使用 IDT 测试编排工具。测试编排工具提供了以下改进功能：
+ IDT 状态机使用命令式格式，而该工具使用声明式格式。这允许您指定要运行哪些测试以及何时运行它们。
+ 管理特定的组处理、报告生成、错误处理和结果跟踪，让您无需手动管理这些操作。
+ 使用 YAML 格式，该格式默认支持注释。
+ 定义相同的工作流程所需的磁盘空间比测试编排工具少 80%。
+ 添加测试前验证，以验证您的工作流程定义不包含错误的测试 ID 或循环依赖关系。

## 测试编排工具格式
<a name="idt-test-orchestrator-format"></a>

您可以使用以下模板来配置自己的`<custom-test-suite-folder>/suite/test_orchestrator.yaml`文件：

```
Aliases:
  string: context-expression

ConditionalTests:
  - Condition: context-expression
    Tests:
      - test-descriptor

Order:
  - - group-descriptor
    - group-descriptor

Features:
  - Name: feature-name
    Value: support-description
    Condition: context-expression
    Tests:
        - test-descriptor
    OneOfTests:
        - test-descriptor
    IsRequired: boolean
```

包含值的所有字段都为必填字段，如下所述：

`Aliases`  
可选。映射到上下文表达式的用户定义字符串。别名允许您生成友好的名称，以便识别测试编排工具配置中的上下文表达式。如果您要创建复杂的上下文表达式或在多个位置使用的表达式，则此功能特别有用。  
您可以使用上下文表达式来存储上下文查询，从而允许您访问其他 IDT 配置中的数据。有关更多信息，请参阅 [在上下文中访问数据](idt-context.md#accessing-context-data)。  

**Example 示例**  

```
Aliases:
    FizzChosen: "'{{$pool.features[?(@.name == 'Fizz')].value[0]}}' == 'yes'"    
    BuzzChosen: "'{{$pool.features[?(@.name == 'Buzz')].value[0]}}' == 'yes'"    
    FizzBuzzChosen: "'{{$aliases.FizzChosen}}' && '{{$aliases.BuzzChosen}}'"
```

`ConditionalTests`  
可选。条件列表以及满足每个条件时运行的相应测试用例。每个条件可以有多个测试用例；但是，您只能将给定测试用例分配给一个条件。  
默认情况下，IDT 会运行任何未分配给此列表中的条件的测试用例。如果您未指定此部分，IDT 将运行测试套件中的所有测试组。  
`ConditionalTests` 列表中的每个项目都包含以下参数：    
`Condition`  
计算结果为布尔值的上下文字符串。如果计算值为 true，IDT 将运行 `Tests` 参数中指定的测试用例。  
`Tests`  
测试描述符列表。  
每个测试描述符使用测试组 ID 和一个或多个测试用例 ID 来标识要从特定测试组运行的单个测试。测试描述符使用以下格式：  

```
GroupId: group-id
CaseIds: [test-id, test-id] # optional
```

**Example 示例**  
以下示例使用可定义为 `Aliases` 的通用上下文表达式。  

```
ConditionalTests:
    - Condition: "{{$aliases.Condition1}}"
      Tests:
          - GroupId: A
          - GroupId: B
    - Condition: "{{$aliases.Condition2}}"
      Tests:
          - GroupId: D
    - Condition: "{{$aliases.Condition1}} || {{$aliases.Condition2}}"
      Tests:
          - GroupId: C
```

IDT 根据定义的条件选择测试组，如下所示：
+ 如果 `Condition1` 为 true，IDT 将在测试组 A、B 和 C 中运行测试。
+ 如果 `Condition2` 为 true，IDT 将在测试组 C 和 D 中运行测试。

`Order`  
可选。运行测试的顺序。您可以在测试组级别指定测试顺序。如果未指定此部分，IDT 将按随机顺序运行所有适用的测试组。`Order` 的值是组描述符列表的列表。未在 `Order` 中列出的任何测试组都可以与列出的任何其他测试组并行运行。  

每个组描述符列表都包含一个或多个组描述符，并标识每个描述符中指定的组的运行顺序。您可以使用以下格式定义单个组描述符：
+ `group-id` – 现有测试组的组 ID。
+ `[group-id, group-id]` – 可按相对于彼此的任意顺序运行的测试组列表。
+ `"*"` – 通配符。这等同于所有尚未在当前组描述符列表中指定的测试组的列表。

`Order` 的值必须满足以下要求：
+ 您的测试套件中必需存在在组描述符中指定的测试组 ID。
+ 每个组描述符列表必须包含至少一个测试组。
+ 每个组描述符列表必须包含唯一的组 ID。不能在单个组描述符中使用重复的测试组 ID。
+ 一个组描述符列表最多可以有一个通配符组描述符。通配符组描述符必须是列表中的第一项或最后一项。

**Example 示例**  
对于包含测试组 A、B、C、D 和 E 的测试套件，以下示例列表显示了指定 IDT 应先运行测试组 A，然后运行测试组 B，然后按任意顺序运行测试组 C、D 和 E 的不同方法。  
+ 

  ```
  Order:
      - - A
        - B
        - [C, D, E]
  ```
+ 

  ```
  Order:
      - - A
        - B
        - "*"
  ```
+ 

  ```
  Order:
      - - A
        - B
      
      - - B
        - C
      
      - - B
        - D
      
      - - B
        - E
  ```

`Features`  
可选。您希望将 IDT 添加到 `awsiotdevicetester_report.xml` 文件中的产品功能列表。如果未指定此部分，则 IDT 不会将任何产品功能添加到报告中。  
产品功能是关于设备可能符合的特定标准的用户定义信息。例如，MQTT 产品功能可以指定设备正确发布 MQTT 消息。在 `awsiotdevicetester_report.xml` 中，根据指定的测试是否通过，将产品功能设置为 `supported`、`not-supported` 或自定义的用户定义值。  
`Features` 列表中的每个项目都包含以下参数：    
`Name`  
特征的名称。  
`Value`  
可选。要在报告中使用的自定义值，而不是 `supported`。如果未指定此值，则根据测试结果，IDT 将特征值设置为 `supported` 或 `not-supported`。如果您使用不同的条件测试相同的功能，则可以在 `Features` 列表中为该特征的各个实例使用自定义值，而 IDT 会将支持条件的特征值串联起来。有关更多信息，请参阅   
`Condition`  
计算结果为布尔值的上下文字符串。如果计算值为 true，IDT 将在运行完测试套件后将该功能添加到测试报告中。如果计算值为 false，则不会将测试包含在报告中。  
`Tests`  
可选。测试描述符列表。必须通过在此列表中指定的所有测试才能支持该功能。  
此列表中的每个测试描述符使用测试组 ID 和一个或多个测试用例 ID 来标识要从特定测试组运行的单个测试。测试描述符使用以下格式：  

```
GroupId: group-id
CaseIds: [test-id, test-id] # optional
```
必须为 `Features` 列表中的每个特征指定 `Tests` 或 `OneOfTests`。  
`OneOfTests`  
可选。测试描述符列表。必须通过在此列表中指定的至少一个测试才能支持该功能。  
此列表中的每个测试描述符使用测试组 ID 和一个或多个测试用例 ID 来标识要从特定测试组运行的单个测试。测试描述符使用以下格式：  

```
GroupId: group-id
CaseIds: [test-id, test-id] # optional
```
必须为 `Features` 列表中的每个特征指定 `Tests` 或 `OneOfTests`。  
`IsRequired`  
用于定义测试报告中是否需要该功能的布尔值。默认值为 `false`。

**Example**  

## 测试编排工具上下文
<a name="idt-test-orchestrator-context"></a>

测试编排工具上下文是一个只读 JSON 文档，其中包含在执行期间可供测试编排工具使用的数据。测试编排工具上下文只能从测试编排工具访问，其中包含决定测试流程的信息。例如，您可以使用 `userdata.json` 文件中测试运行器配置的信息来确定是否需要运行特定的测试。

测试编排工具上下文使用以下格式：

```
{
    "pool": {
        <device-json-pool-element>
    },
    "userData": {
        <userdata-json-content>
    },
    "config": {
        <config-json-content>
    }
}
```

`pool`  
有关为测试运行选择的设备池的信息。对于选定的设备池，此信息将从 `device.json` 文件中定义的相应顶级设备池阵列元素中检索。

`userData`  
`userdata.json` 文件中的信息

`config`  
`config.json` 文件中的信息

您可以使用 JSONPath 表示法查询上下文。状态定义中 jsonPath 查询的语法是 `{{query}}`。从测试编排工具上下文访问数据时，请确保每个值的计算结果都为字符串、数字或布尔值。

有关使用 JSONPath 表示法从上下文中访问数据的更多信息，请参阅 [使用 IDT 上下文](idt-context.md)。

# 配置 IDT 状态机
<a name="idt-state-machine"></a>

**重要**  
从 IDT v4.5.1 开始，此状态机已弃用。我们强烈建议您使用新的测试编排工具。有关更多信息，请参阅 [配置 IDT 测试编排工具](idt-test-orchestrator.md)。

状态机是一种控制测试套件执行流程的构造。它决定测试套件的起始状态，根据用户定义的规则管理状态转换，并继续在这些状态之间进行转换，直到达到结束状态。

如果您的测试套件不包含用户定义的状态机，IDT 将为您生成状态机。默认状态机执行以下功能：
+ 使测试运行器能够选择和运行特定的测试组，而不是整个测试套件。
+ 如果未选择特定的测试组，则按随机顺序运行测试套件中的每个测试组。
+ 生成报告并打印控制台摘要，其中显示每个测试组和测试用例的测试结果。

IDT 测试套件的状态机必须满足以下条件：
+ 每个状态都对应于 IDT 要采取的操作，例如运行测试组或产品报告文件。
+ 过渡到状态会执行与该状态关联的操作。
+ 每个状态都定义了下一个状态的过渡规则。
+ 结束状态必须为 `Succeed` 或 `Fail`。

## 状态机格式
<a name="state-machine-format"></a>

您可以使用以下模板来配置自己的`<custom-test-suite-folder>/suite/state_machine.json`文件：

```
{
  "Comment": "<description>",
  "StartAt": "<state-name>",
  "States": {
    "<state-name>": {
      "Type": "<state-type>",
      // Additional state configuration
    }
    
    // Required states
    "Succeed": {
      "Type": "Succeed"
    },
    "Fail": {
      "Type": "Fail"
    }
  }
}
```

包含值的所有字段都为必填字段，如下所述：

`Comment`  
状态机的描述。

`StartAt`  
IDT 开始运行测试套件的状态名称。`StartAt` 的值必须设置为 `States` 对象中列出的其中一个状态。

`States`  
将用户定义的状态名称映射到有效的 IDT 状态的对象。每个州。 *state-name*对象包含映射到. 的有效状态的定义*state-name*。  
`States` 对象必须包含 `Succeed` 和 `Fail` 状态。有关有效状态的信息，请参阅[有效状态和状态定义](#valid-states)。

## 有效状态和状态定义
<a name="valid-states"></a>

本节介绍可在 IDT 状态机中使用的所有有效状态的状态定义。以下某些状态支持测试用例级别的配置。但是，除非绝对必要，否则我们建议您在测试组级别而不是测试用例级别配置状态转换规则。

**Topics**
+ [

### RunTask
](#state-runtask)
+ [

### Choice
](#state-choice)
+ [

### Parallel
](#state-parallel)
+ [

### AddProductFeatures
](#state-addproductfeatures)
+ [

### 报告
](#state-report)
+ [

### LogMessage
](#state-logmessage)
+ [

### SelectGroup
](#state-selectgroup)
+ [

### Fail
](#state-fail)
+ [

### Succeed
](#state-succeed)

### RunTask
<a name="state-runtask"></a>

`RunTask` 状态运行测试套件中定义的测试组中的测试用例。

```
{
    "Type": "RunTask",
    "Next": "<state-name>",
    "TestGroup": "<group-id>",
    "TestCases": [
        "<test-id>"
    ],
    "ResultVar": "<result-name>"
}
```

包含值的所有字段都为必填字段，如下所述：

`Next`  
在当前状态下执行操作后要过渡到的状态的名称。

`TestGroup`  
可选。要运行的测试组的 ID。如果未指定此值，则 IDT 将运行测试运行器选择的测试组。

`TestCases`  
可选。 IDs 来自中指定组的测试用例数组`TestGroup`。IDT 根据 `TestGroup` 和 `TestCases` 的值确定测试执行行为，如下所示：  
+ 同时指定 `TestGroup` 和 `TestCases` 时，IDT 会运行测试组中的指定测试用例。
+ 如果 `TestCases` 已指定但 `TestGroup` 未指定，IDT 将运行指定的测试用例。
+ 如果 `TestGroup` 已指定但 `TestCases` 未指定，则 IDT 将运行指定测试组中的所有测试用例。
+ 如果未指定 `TestGroup` 或 `TestCases`，IDT 将运行测试运行器从 IDT CLI 中选择的测试组中的所有测试用例。要为测试运行器启用组选择，必须在 `state_machine.json` 文件中同时包含 `RunTask` 和 `Choice` 状态。有关其工作原理的示例，请参阅[状态机示例：运行用户选择的测试组](#allow-specific-groups)。

  有关为测试运行器启用 IDT CLI 命令的更多信息，请参阅 [启用 IDT CLI 命令](create-test-executables.md#idt-cli-coop)。

`ResultVar`  
要与测试运行结果一起设置的上下文变量的名称。如果您没有为指定值，请不要指定此值 `TestGroup`。基于以下内容，IDT 将您在 `ResultVar` 中定义的变量的值设置为 `true` 或 `false`：  
+ 如果变量名称的形式为 `text_text_passed`，则该值设置为第一个测试组中的所有测试均已通过或跳过。
+ 在所有其他情况下，该值设置为所有测试组中的所有测试已通过或跳过。

通常，您将使用`RunTask`状态来指定测试组 ID，而不指定单个测试用例 IDs，这样 IDT 将运行指定测试组中的所有测试用例。在此状态下运行的所有测试用例均按随机顺序并行运行。但是，如果所有测试用例都需要一台设备运行，并且只有一台设备可用，则测试用例将按顺序运行。

**错误处理**

如果任何指定的测试组或测试用例 IDs 无效，则此状态会发出`RunTaskError`执行错误。如果状态遇到执行错误，则它还会将状态机上下文中的 `hasExecutionError` 变量设置为 `true`。

### Choice
<a name="state-choice"></a>

`Choice` 状态允许您根据用户定义的条件动态设置要过渡到的下一个状态。

```
{
    "Type": "Choice",
    "Default": "<state-name>", 
    "FallthroughOnError": true | false,
    "Choices": [
        {
            "Expression": "<expression>",
            "Next": "<state-name>"
        }
    ]
}
```

包含值的所有字段都为必填字段，如下所述：

`Default`  
如果 `Choices` 中定义的表达式都无法评估到 `true`，则设置要过渡到的默认状态。

`FallthroughOnError`  
可选。指定状态在评估表达式时遇到错误时的行为。如果要在评估结果出错时跳过表达式，则设置为 `true`。如果没有匹配的表达式，则状态机将过渡到 `Default` 状态。如果 `FallthroughOnError` 的值未指定，将默认为 `false`。

`Choices`  
一组表达式和状态，用于确定在当前状态下执行操作后要过渡到哪个状态。    
`Choices.Expression`  
计算结果为布尔值的表达式字符串。如果表达式的评估结果为 `true`，则状态机将过渡到 `Choices.Next` 中定义的状态。表达式字符串从状态机上下文中检索值，然后对它们执行操作以得出布尔值。有关访问状态机上下文的信息，请参见 [状态机上下文](#state-machine-context)。  
`Choices.Next`  
如果 `Choices.Expression` 中定义的表达式的评估结果为 `true`，则设置要过渡到的状态的名称。

**错误处理**

在以下情况下，`Choice` 状态可能需要错误处理：
+ 选择表达式中的某些变量在状态机上下文中不存在。
+ 表达式的结果不是布尔值。
+ JSON 查询的结果不是字符串、数字或布尔值。

在这种状态下，不能使用 `Catch` 数据块来处理错误。如果要在状态机遇到错误时停止执行它，则必须将 `FallthroughOnError` 设置为 `false`。但是，建议您将 `FallthroughOnError` 设置为 `true`，并根据您的用例，执行以下操作之一：
+ 如果您正在访问的变量预计在某些情况下不存在，则使用的值 `Default` 和其他 `Choices` 数据块来指定下一个状态。
+ 如果您正在访问的变量应始终存在，则将 `Default` 状态设置为 `Fail`。

### Parallel
<a name="state-parallel"></a>

`Parallel` 状态允许您并行地定义和运行新的状态机。

```
{
    "Type": "Parallel",
    "Next": "<state-name>",
    "Branches": [
        <state-machine-definition>
    ]
}
```

包含值的所有字段都为必填字段，如下所述：

`Next`  
在当前状态下执行操作后要过渡到的状态的名称。

`Branches`  
要运行的状态机定义阵列。每个状态机定义都必须包含自己的`StartAt`、`Succeed` 和 `Fail` 状态。此阵列中的状态机定义不能引用其自身定义之外的状态。  
由于每个分支状态机共享相同的状态机上下文，因此在一个分支中设置变量然后从另一个分支读取这些变量可能会导致意外行为。

只有在 `Parallel` 运行所有分支状态机之后，该状态才会移动到下一个状态。每种需要设备的状态都将等到设备可用后才运行。如果有多个设备可用，则此状态会并行运行来自多个组的测试用例。如果没有足够的设备可用，则测试用例将按顺序运行。由于测试用例在并行运行时按随机顺序运行，因此可能会使用不同的设备来运行来自同一个测试组的测试。

**错误处理**

确保分支状态机和父状态机都过渡到 `Fail` 状态以处理执行错误。

由于分支状态机不会将执行错误传输到父状态机，因此您不能使用 `Catch` 数据块来处理分支状态机中的执行错误。相反，在共享状态机上下文中使用 `hasExecutionErrors` 值。有关如何执行此操作的示例，请参阅 [状态机示例：并行运行两个测试组](#run-in-parallel)。

### AddProductFeatures
<a name="state-addproductfeatures"></a>

`AddProductFeatures` 状态允许您将产品功能添加到 IDT 生成的 `awsiotdevicetester_report.xml` 文件中。

产品功能是关于设备可能符合的特定标准的用户定义信息。例如，`MQTT` 产品功能可以指定设备正确发布 MQTT 消息。在报告中，根据指定的测试是否通过，将产品功能设置为 `supported`、`not-supported` 或自定义值。



**注意**  
`AddProductFeatures` 状态本身不生成报告。此状态必须过渡到[`Report`状态](#state-report)才能生成报告。

```
{
    "Type": "Parallel",
    "Next": "<state-name>",
    "Features": [
        {
            "Feature": "<feature-name>", 
            "Groups": [
                "<group-id>"
            ],
            "OneOfGroups": [
                "<group-id>"
            ],
            "TestCases": [
                "<test-id>"
            ],
            "IsRequired": true | false,
            "ExecutionMethods": [
                "<execution-method>"
            ]
        }
    ]
}
```

包含值的所有字段都为必填字段，如下所述：

`Next`  
在当前状态下执行操作后要过渡到的状态的名称。

`Features`  
要在 `awsiotdevicetester_report.xml` 文件中显示的一系列产品功能。    
`Feature`  
功能的名称  
`FeatureValue`  
可选。要在报告中使用的自定义值，而不是 `supported`。如果未指定此值，则根据测试结果，将特征值设置为 `supported` 或 `not-supported`。  
如果您使用 `FeatureValue` 自定义值，则可以在不同的条件下测试相同的功能，IDT 会将支持条件的特征值串联起来。例如，以下摘录显示具有两个独立 `MyFeature` 特征值的要素：  

```
...
{
    "Feature": "MyFeature",
    "FeatureValue": "first-feature-supported",
    "Groups": ["first-feature-group"]
},
{
    "Feature": "MyFeature",
    "FeatureValue": "second-feature-supported",
    "Groups": ["second-feature-group"]
},
...
```
如果两个测试组都通过，则特征值将设置为 `first-feature-supported, second-feature-supported`。  
`Groups`  
可选。一组测试组 IDs。每个指定测试组中的所有测试都必须通过才能支持该功能。  
`OneOfGroups`  
可选。一组测试组 IDs。至少一个指定测试组中的所有测试都必须通过才能支持该功能。  
`TestCases`  
可选。一系列测试用例 IDs。如果您指定此值，则适用以下条件：  
+ 必须通过所有指定的测试用例才能支持该功能。
+ `Groups` 必须仅包含一个测试组 ID。
+ `OneOfGroups` 不得指定。  
`IsRequired`  
可选。设置为 `false` 可在报告中将此功能标记为可选功能。默认值为 `true`。  
`ExecutionMethods`  
可选。与 `device.json` 文件中指定的 `protocol` 值相匹配的执行方法阵列。如果指定了此值，则测试运行器必须指定与该阵列中的一个 `protocol` 值相匹配的值，才能将该功能包含在报告中。如果未指定此值，则该要素将始终包含在报告中。

要使用 `AddProductFeatures` 状态，必须将 `RunTask` 状态 `ResultVar` 中的值设置为以下值之一：
+ 如果您指定了单个测试用例 IDs，则将设置`ResultVar`为`group-id_test-id_passed`。
+ 如果您未指定单个测试用例 IDs，则将设置`ResultVar`为`group-id_passed`。

`AddProductFeatures` 状态通过以下方式检查测试结果：
+ 如果您未指定任何测试用例 IDs，则每个测试组的结果将根据状态机上下文中的`group-id_passed`变量值确定。
+ 如果您确实指定了测试用例 IDs，则每个测试的结果都是根据状态机上下文中`group-id_test-id_passed`变量的值确定的。

**错误处理**

如果在此状态下提供的群组 ID 不是有效的组 ID，则此状态会导致 `AddProductFeaturesError` 执行错误。如果状态遇到执行错误，则它还会将状态机上下文中的 `hasExecutionErrors` 变量设置为 `true`。

### 报告
<a name="state-report"></a>

`Report` 状态会生成 `suite-name_Report.xml` 和 `awsiotdevicetester_report.xml` 文件。此状态还会将报告流式传输到控制台。

```
{
    "Type": "Report",
    "Next": "<state-name>"
}
```

包含值的所有字段都为必填字段，如下所述：

`Next`  
在当前状态下执行操作后要过渡到的状态的名称。

您应始终过渡到测试执行流程即将结束时的 `Report` 状态，以便测试运行器可以查看测试结果。通常，此状态之后的下一个状态是 `Succeed`。

**错误处理**

如果此状态在生成报告时遇到问题，则会发出 `ReportError` 执行错误。

### LogMessage
<a name="state-logmessage"></a>

`LogMessage` 状态生成 `test_manager.log` 文件并将日志消息流式传输到控制台。

```
{
    "Type": "LogMessage",
    "Next": "<state-name>"
    "Level": "info | warn | error"
    "Message": "<message>"
}
```

包含值的所有字段都为必填字段，如下所述：

`Next`  
在当前状态下执行操作后要过渡到的状态的名称。

`Level`  
创建日志消息的错误级别。如果您指定的级别无效，则此状态会生成一条错误消息并将其丢弃。

`Message`  
要记入日志的消息。

### SelectGroup
<a name="state-selectgroup"></a>

`SelectGroup` 状态会更新状态机上下文以指示选择了哪些组。任何后续 `Choice` 状态都使用此状态设置的值。

```
{
    "Type": "SelectGroup",
    "Next": "<state-name>"
    "TestGroups": [
        <group-id>"
    ]
}
```

包含值的所有字段都为必填字段，如下所述：

`Next`  
在当前状态下执行操作后要过渡到的状态的名称。

`TestGroups`  
一组将被标记为选中的测试组。对于此阵列中的每个测试组 ID，`group-id_selected` 变量在上下文中都设置为 `true`。请确保提供有效的测试组， IDs 因为 IDT 不会验证指定的组是否存在。

### Fail
<a name="state-fail"></a>

`Fail` 状态表示状态机未正确执行。这是状态机的结束状态，每个状态机定义都必须包含此状态。

```
{
    "Type": "Fail"
}
```

### Succeed
<a name="state-succeed"></a>

`Succeed` 状态表示状态机已正确执行。这是状态机的结束状态，每个状态机定义都必须包含此状态。

```
{
    "Type": "Succeed"
}
```

## 状态机上下文
<a name="state-machine-context"></a>

状态机上下文是一个只读 JSON 文档，其中包含在执行期间可供状态机使用的数据。状态机上下文只能从状态机访问，并且包含决定测试流程的信息。例如，您可以使用 `userdata.json` 文件中测试运行器配置的信息来确定是否需要运行特定的测试。

状态机上下文使用以下格式：

```
{
    "pool": {
        <device-json-pool-element>
    },
    "userData": {
        <userdata-json-content>
    },
    "config": {
        <config-json-content>
    },
    "suiteFailed": true | false,
    "specificTestGroups": [
        "<group-id>"
    ],
    "specificTestCases": [
        "<test-id>"
    ],
    "hasExecutionErrors": true
}
```

`pool`  
有关为测试运行选择的设备池的信息。对于选定的设备池，此信息将从 `device.json` 文件中定义的相应顶级设备池阵列元素中检索。

`userData`  
`userdata.json` 文件中的信息

`config`  
信息会锁定 `config.json` 文件。

`suiteFailed`  
该值在状态机启动时设置为 `false`。如果测试组在某种 `RunTask` 状态下失败，则在状态机执行的剩余时间内，该值将设置为 `true`。

`specificTestGroups`  
如果测试运行者选择特定的测试组而不是整个测试套件来运行，则会创建此密钥并包含特定测试组的列表 IDs。

`specificTestCases`  
如果测试运行器选择要运行的特定测试用例而不是整个测试套件，则会创建此密钥并包含特定测试用例的列表 IDs。

`hasExecutionErrors`  
状态机启动时不退出。如果任何状态遇到执行错误，则会在状态机执行的剩余时间内创建此变量并将其设置为 `true`。

您可以使用 JSONPath 符号查询上下文。状态定义中 JSONPath 查询的语法是`{{$.query}}`。在某些状态下，您可以将 JSONPath 查询用作占位符字符串。IDT 将占位符字符串替换为来自上下文的已评估 JSONPath 查询的值。您可以对占位符使用以下值：
+ `RunTask`状态的 `TestCases` 值。
+ `Expression` 值 `Choice` 状态。

当您访问状态机上下文中的数据时，请确保满足以下条件：
+ JSON 路径必须以 `$.` 开头
+ 每个值的计算结果必须为字符串、数字或布尔值。

有关使用 JSONPath 符号从上下文访问数据的更多信息，请参阅[使用 IDT 上下文](idt-context.md)。

## 执行错误
<a name="execution-errors"></a>

执行错误是状态机在执行状态时遇到的状态机定义中的错误。IDT 在 `test_manager.log` 文件中记录有关每个错误的信息，并将日志消息流式传输到控制台。

您可以使用以下方法来处理执行错误：
+ 在状态定义中添加一个[`Catch` 数据块](#catch)。
+ 在状态机上下文中检查 [`hasExecutionErrors`值](#context)。

### 捕获
<a name="catch"></a>

要使用 `Catch`，请将以下内容添加到您的状态定义中：

```
"Catch": [
    {    
        "ErrorEquals": [
            "<error-type>"
        ]
        "Next": "<state-name>" 
    }
]
```

包含值的所有字段都为必填字段，如下所述：

`Catch.ErrorEquals`  
要捕获的错误类型的数组。如果执行错误与其中一个指定值匹配，则状态机将转换为 `Catch.Next` 中指定的状态。有关其产生的错误类型的信息，请参阅每个状态定义。

`Catch.Next`  
当前状态遇到与 `Catch.ErrorEquals` 中指定值之一相匹配的执行错误时，设置要过渡到的下一个状态。

捕获数据块按顺序处理，直到匹配。如果没有错误与捕获数据块中列出的错误相匹配，则状态机将继续执行。由于执行错误是由状态定义不正确造成的，因此我们建议您在状态遇到执行错误时过渡到失败状态。

### hasExecutionError
<a name="context"></a>

当某些状态遇到执行错误时，除了发出错误外，它们还会在状态机上下文中将 `hasExecutionError` 值设置为 `true`。您可以使用此值来检测何时发生错误，然后使用 `Choice` 状态将状态机过渡到 `Fail` 状态。

该方式具有以下特征。
+ 状态机不以分配给 `hasExecutionError` 的任何值启动，并且在特定状态设置该值之前，该值不可用。这意味着必须将访问此值的 `Choice` 状态的 `FallthroughOnError` 明确设置为 `false`，以防止在没有发生执行错误时状态机停止。
+ 一旦将其设置为 `true`，`hasExecutionError` 就永远不会设置为 false 或将其从上下文中删除。这意味着该值仅在首次设置为 `true` 时才有用，并且对于所有后续状态，它不会提供有意义的值。
+ `hasExecutionError` 值与处于 `Parallel` 状态的所有分支状态机共享，这可能会导致意想不到的结果，具体取决于访问该值的顺序。

由于这些特性，如果您可以改用捕获数据块，我们不建议您使用此方法。

## 示例状态机
<a name="state-machine-examples"></a>

本部分提供了一些状态机配置示例。

**Topics**
+ [

### 状态机示例：运行单个测试组
](#single-test-group)
+ [

### 状态机示例：运行用户选择的测试组
](#allow-specific-groups)
+ [

### 状态机示例：使用产品功能运行单个测试组
](#run-with-product-features)
+ [

### 状态机示例：并行运行两个测试组
](#run-in-parallel)

### 状态机示例：运行单个测试组
<a name="single-test-group"></a>

该状态机：
+ 运行带有 id `GroupA` 的测试组，该组必须以 `group.json` 文件形式存在于套件中。
+ 检查是否存在执行错误，如果发现任何错误，则过渡到 `Fail`。
+ 生成报告，如果没有错误，则过渡到 `Succeed`，否则过渡到 `Fail`。

```
{
    "Comment": "Runs a single group and then generates a report.",
    "StartAt": "RunGroupA",
    "States": {
        "RunGroupA": {
            "Type": "RunTask",
            "Next": "Report",
            "TestGroup": "GroupA",
            "Catch": [
                {
                    "ErrorEquals": [
                        "RunTaskError"
                    ],
                    "Next": "Fail"
                }
            ]
        },
        "Report": {
            "Type": "Report",
            "Next": "Succeed",
            "Catch": [
                {
                    "ErrorEquals": [
                        "ReportError"
                    ],
                    "Next": "Fail"
                }
            ]
        },
        "Succeed": {
            "Type": "Succeed"
        },
        "Fail": {
            "Type": "Fail"
        }
    }
}
```

### 状态机示例：运行用户选择的测试组
<a name="allow-specific-groups"></a>

该状态机：
+ 检查测试运行器是否选择了特定的测试组。状态机不检查特定的测试用例，因为如果不选择测试组，测试运行器就无法选择测试用例。
+ 如果选择了测试组：
  + 在选定的测试组中运行测试用例。为此，状态机不会明确指定处于 `RunTask` 状态中的任何测试组或测试用例。
  + 运行所有测试后生成报告并退出。
+ 如果未选择测试组：
  + 在测试组 `GroupA` 中运行测试。
  + 生成报告并退出。

```
{
    "Comment": "Runs specific groups if the test runner chose to do that, otherwise runs GroupA.",
    "StartAt": "SpecificGroupsCheck",
    "States": {
        "SpecificGroupsCheck": {
            "Type": "Choice",
            "Default": "RunGroupA",
            "FallthroughOnError": true,
            "Choices": [
                {
                    "Expression": "{{$.specificTestGroups[0]}} != ''",
                    "Next": "RunSpecificGroups"
                }
            ]
        },
        "RunSpecificGroups": {
            "Type": "RunTask",
            "Next": "Report",
            "Catch": [
                {
                    "ErrorEquals": [
                        "RunTaskError"
                    ],
                    "Next": "Fail"
                }
            ]
        },
        "RunGroupA": {
            "Type": "RunTask",
            "Next": "Report",
            "TestGroup": "GroupA",
            "Catch": [
                {
                    "ErrorEquals": [
                        "RunTaskError"
                    ],
                    "Next": "Fail"
                }
            ]
        },
        "Report": {
            "Type": "Report",
            "Next": "Succeed",
            "Catch": [
                {
                    "ErrorEquals": [
                        "ReportError"
                    ],
                    "Next": "Fail"
                }
            ]
        },
        "Succeed": {
            "Type": "Succeed"
        },
        "Fail": {
            "Type": "Fail"
        }
    }
}
```

### 状态机示例：使用产品功能运行单个测试组
<a name="run-with-product-features"></a>

该状态机：
+ 运行测试组 `GroupA`。
+ 检查是否存在执行错误，如果发现任何错误，则过渡到 `Fail`。
+ 将 `FeatureThatDependsOnGroupA` 功能添加到 `awsiotdevicetester_report.xml` 文件中：
  + 如果 `GroupA` 通过，则该功能将设置为 `supported`。
  + 报告中未将该功能标记为可选。
+ 生成报告，如果没有错误，则过渡到 `Succeed`，否则过渡到 `Fail`

```
{
    "Comment": "Runs GroupA and adds product features based on GroupA",
    "StartAt": "RunGroupA",
    "States": {
        "RunGroupA": {
            "Type": "RunTask",
            "Next": "AddProductFeatures",
            "TestGroup": "GroupA",
            "ResultVar": "GroupA_passed",
            "Catch": [
                {
                    "ErrorEquals": [
                        "RunTaskError"
                    ],
                    "Next": "Fail"
                }
            ]
        },
        "AddProductFeatures": {
            "Type": "AddProductFeatures",
            "Next": "Report",
            "Features": [
                {
                    "Feature": "FeatureThatDependsOnGroupA",
                    "Groups": [
                        "GroupA"
                    ],
                    "IsRequired": true
                }
            ]
        },
        "Report": {
            "Type": "Report",
            "Next": "Succeed",
            "Catch": [
                {
                    "ErrorEquals": [
                        "ReportError"
                    ],
                    "Next": "Fail"
                }
            ]
        },
        "Succeed": {
            "Type": "Succeed"
        },
        "Fail": {
            "Type": "Fail"
        }
    }
}
```

### 状态机示例：并行运行两个测试组
<a name="run-in-parallel"></a>

该状态机：
+ 并行运行 `GroupA` 和 `GroupB` 测试组。通过分支状态机中的 `RunTask` 状态存储在上下文中的 `ResultVar` 变量可供 `AddProductFeatures` 状态使用。
+ 检查是否存在执行错误，如果发现任何错误，则过渡到 `Fail`。此状态机不使用 `Catch` 数据块，因为该方法不会检测分支状态机中的执行错误。
+ 根据通过的群组向 `awsiotdevicetester_report.xml` 文件添加功能
  + 如果 `GroupA` 通过，则该功能将设置为 `supported`。
  + 报告中未将该功能标记为可选。
+ 生成报告，如果没有错误，则过渡到 `Succeed`，否则过渡到 `Fail`

如果在设备池中配置了两个设备，则 `GroupA` 和 `GroupB` 可以同时运行。但是，如果其中一个 `GroupA` 或 `GroupB` 有多个测试，则两个设备都可能分配给这些测试。如果只配置了一台设备，则测试组将按顺序运行。

```
{
    "Comment": "Runs GroupA and GroupB in parallel",
    "StartAt": "RunGroupAAndB",
    "States": {
        "RunGroupAAndB": {
            "Type": "Parallel",
            "Next": "CheckForErrors",
            "Branches": [
                {
                    "Comment": "Run GroupA state machine",
                    "StartAt": "RunGroupA",
                    "States": {
                        "RunGroupA": {
                            "Type": "RunTask",
                            "Next": "Succeed",
                            "TestGroup": "GroupA",
                            "ResultVar": "GroupA_passed",
                            "Catch": [
                                {
                                    "ErrorEquals": [
                                        "RunTaskError"
                                    ],
                                    "Next": "Fail"
                                }
                            ]
                        },
                        "Succeed": {
                            "Type": "Succeed"
                        },
                        "Fail": {
                            "Type": "Fail"
                        }
                    }
                },
                {
                    "Comment": "Run GroupB state machine",
                    "StartAt": "RunGroupB",
                    "States": {
                        "RunGroupA": {
                            "Type": "RunTask",
                            "Next": "Succeed",
                            "TestGroup": "GroupB",
                            "ResultVar": "GroupB_passed",
                            "Catch": [
                                {
                                    "ErrorEquals": [
                                        "RunTaskError"
                                    ],
                                    "Next": "Fail"
                                }
                            ]
                        },
                        "Succeed": {
                            "Type": "Succeed"
                        },
                        "Fail": {
                            "Type": "Fail"
                        }
                    }
                }
            ]
        },
        "CheckForErrors": {
            "Type": "Choice",
            "Default": "AddProductFeatures",
            "FallthroughOnError": true,
            "Choices": [
                {
                    "Expression": "{{$.hasExecutionErrors}} == true",
                    "Next": "Fail"
                }
            ]
        },
        "AddProductFeatures": {
            "Type": "AddProductFeatures",
            "Next": "Report",
            "Features": [
                {
                    "Feature": "FeatureThatDependsOnGroupA",
                    "Groups": [
                        "GroupA"
                    ],
                    "IsRequired": true
                },
                {
                    "Feature": "FeatureThatDependsOnGroupB",
                    "Groups": [
                        "GroupB"
                    ],
                    "IsRequired": true
                }
            ]
        },
        "Report": {
            "Type": "Report",
            "Next": "Succeed",
            "Catch": [
                {
                    "ErrorEquals": [
                        "ReportError"
                    ],
                    "Next": "Fail"
                }
            ]
        },
        "Succeed": {
            "Type": "Succeed"
        },
        "Fail": {
            "Type": "Fail"
        }
    }
}
```

# 创建 IDT 测试用例可执行文件
<a name="create-test-executables"></a>

您可以通过以下方式，创建测试用例可执行文件并将其放在测试套件文件夹中：
+ 如果测试套件使用 `test.json` 文件中的参数或环境变量来确定要运行哪些测试，您可以为整个测试套件创建一个测试用例可执行文件，也可为测试套件中的每个测试组分别创建一个测试可执行文件。
+ 对于要基于指定命令运行特定测试的测试套件，您可以为测试套件中的每个测试用例创建一个测试用例可执行文件。

作为测试编写者，您可以决定哪一种方法适合您的用例，并相应地构建测试用例可执行文件。请确保在每个 `test.json` 文件中提供正确的测试用例可执行文件路径，并且指定的可执行文件能够正确地运行。

当所有设备都准备好运行测试用例时，IDT 将会读取以下文件：
+ 所选测试用例的 `test.json` 决定了要启动的进程以及要设置的环境变量。
+ 测试套件的 `suite.json` 决定了要设置的环境变量。

IDT 根据 `test.json` 文件中指定的命令和参数启动所需的测试可执行文件进程，并将必要的环境变量传递给这个进程。

## 使用 IDT 客户端软件开发工具包
<a name="idt-client-sdk"></a>

通过 IDT 客户端软件开发工具包，您可以使用 API 命令来简化在测试可执行文件中编写测试逻辑的方式，这些命令可用于跟 IDT 和被测设备交互。IDT 当前提供以下开发工具包：
+ 适用于 Python 的 IDT 客户端软件开发工具包
+ 适用于 Go 的 IDT 客户端软件开发工具包
+ 适用于 Java 的 IDT 客户端软件开发工具包

这些开发工具包位于 `<device-tester-extract-location>/sdks` 文件夹中。创建新的测试用例可执行文件时，您必须将要使用的软件开发工具包复制到包含测试用例可执行文件的文件夹中，并在代码中引用这个软件开发工具包。本节简要描述了可以在测试用例可执行文件中使用的 API 命令。

**Topics**
+ [

### 设备交互
](#api-device-interaction)
+ [

### IDT 交互
](#api-idt-interaction)
+ [

### 主机交互
](#api-host-interaction)

### 设备交互
<a name="api-device-interaction"></a>

通过运行以下命令，您无需实施任何其他设备交互和连接管理功能，即可与被测设备通信。

`ExecuteOnDevice`  
允许测试套件在支持 SSH 或 Docker shell 连接的设备上运行 shell 命令。

`CopyToDevice`  
允许测试套件将本地文件从运行 IDT 的主机复制到支持 SSH 或 Docker shell 连接的设备上的指定位置。

`ReadFromDevice`  
允许测试套件从支持 UART 连接的设备的串行端口进行读取。

**注意**  
由于 IDT 不管理使用上下文中设备访问信息与设备建立的直接连接，因此我们建议在测试用例可执行文件中使用这些设备交互 API 命令。但是，如果这些命令不满足测试用例要求，您可以从 IDT 环境中检索设备访问信息，并使用该信息从测试套件建立与设备的直接连接。  
要建立直接连接，请分别在 `device.connectivity` 和 `resource.devices.connectivity` 字段中检索被测设备和资源设备的信息。有关使用 IDT 上下文的更多信息，请参阅 [使用 IDT 上下文](idt-context.md)。

### IDT 交互
<a name="api-idt-interaction"></a>

您可以通过运行以下命令，使测试套件与 IDT 进行通信。

`PollForNotifications`  
允许测试套件检查来自 IDT 的通知。

`GetContextValue `"and"`GetContextString`  
允许测试套件从 IDT 上下文中检索值。有关更多信息，请参阅 [使用 IDT 上下文](idt-context.md)。

`SendResult`  
允许测试套件向 IDT 报告测试用例结果。此命令必须在测试套件中每个测试用例结束时进行调用。

### 主机交互
<a name="api-host-interaction"></a>

您可以通过运行以下命令，使测试套件与主机进行通信。

`PollForNotifications`  
允许测试套件检查来自 IDT 的通知。

`GetContextValue `"and"`GetContextString`  
允许测试套件从 IDT 上下文中检索值。有关更多信息，请参阅 [使用 IDT 上下文](idt-context.md)。

`ExecuteOnHost`  
允许测试套件在本地计算机上运行命令，并使 IDT 能够管理测试用例可执行文件的生命周期。

## 启用 IDT CLI 命令
<a name="idt-cli-coop"></a>

IDT CLI `run-suite` 命令提供了多个选项，允许测试运行器自定义测试执行。要允许测试运行器使用这些选项来运行您的自定义测试套件，您需要实施对 IDT CLI 的支持。如果您不实施支持，测试运行器仍然可以运行测试，但是某些 CLI 选项将无法正常运作。为了提供理想的客户体验，我们建议您在 IDT CLI 中实施对以下 `run-suite` 命令参数的支持：

`timeout-multiplier`  
指定一个大于 1.0 的值，该值将应用于测试运行期间的所有超时。  
测试运行器可以使用此参数来延长他们想要运行的测试用例的超时时间。测试运行器在其 `run-suite` 命令中指定此参数后，IDT 会使用它来计算 IDT\$1TEST\$1TIMEOUT 环境变量的值，并在 IDT 上下文中设置 `config.timeoutMultiplier` 字段。要支持这个参数，您必须执行以下操作：  
+ 读取 IDT\$1TEST\$1TIMEOUT 环境变量来获取正确计算的超时值，而不是直接使用 `test.json` 文件中的超时值。
+ 从 IDT 上下文中检索 `config.timeoutMultiplier` 值，并将其应用于长时间运行的超时。
有关因超时事件而提前退出的更多信息，请参阅[指定退出行为](#test-exec-exiting)。

`stop-on-first-failure`  
指定 IDT 在遇到故障时应当停止运行所有测试。  
测试运行器在其 `run-suite` 命令中指定此参数后，IDT 会在遇到故障时立即停止运行测试。但是，如果测试用例是并行运行的，可能会导致意外的结果。要实施支持，请确保当 IDT 遇到此事件时，您的测试逻辑会指示所有运行中的测试用例停止运行、清理临时资源并向 IDT 报告测试结果。有关失败时提早退出的更多信息，请参阅 [指定退出行为](#test-exec-exiting)。

`group-id`"and"`test-id`  
指定 IDT 应当仅运行选定的测试组或测试用例。  
测试运行器可以在 `run-suite` 命令中使用这些参数来指定以下测试执行行为：  
+ 在指定的测试组中运行所有测试。
+ 运行一组来自指定测试组的测试。
为了支持这些参数，测试套件的测试编排工具必须在测试编排工具中包含一组特定的 `RunTask` 和 `Choice` 状态。如果您不使用自定义状态机，默认 IDT 测试编排工具包含了所需的状态，您无需采取其他操作。但是，如果您要使用自定义测试编排工具，则可以将 [状态机示例：运行用户选择的测试组](idt-state-machine.md#allow-specific-groups) 作为示例，在测试编排工具中添加所需的状态。

有关 IDT CLI 命令的更多信息，请参阅 [调试和运行自定义测试套件](run-debug-custom-tests.md)。

## 写入事件日志
<a name="test-exec-logs"></a>

在测试运行期间，您可以通过向 `stdout` 和 `stderr` 发送数据，将事件日志和错误消息写入控制台。有关控制台消息格式的信息，请参阅 [控制台消息格式](idt-review-results-logs.md#idt-console-format)。

IDT 运行完测试套件后，也可以在 `<devicetester-extract-location>/results/<execution-id>/logs` 文件夹下的 `test_manager.log` 文件中找到此信息。

您可以将每个测试用例配置为将其测试运行的日志（包括来自被测设备的日志）写入 `<device-tester-extract-location>/results/execution-id/logs` 文件夹下的 `<group-id>_<test-id>` 文件中。为此，请使用 `testData.logFilePath` 查询从 IDT 上下文中检索日志文件的路径，在该路径上创建一个文件，然后将所需的内容写入这个文件中。IDT 会根据正在运行的测试用例来自动更新路径。如果您选择不为测试用例创建日志文件，则不会为该测试用例生成任何文件。

此外，也可将文本可执行文件设置为按需在 `<device-tester-extract-location>/logs` 文件夹中创建其他日志文件。我们建议您为日志文件名指定唯一的前缀，以避免您的文件被覆盖。

## 向 IDT 报告结果
<a name="test-exec-results"></a>

IDT 将测试结果写入 `awsiotdevicetester_report.xml` 和 `suite-name_report.xml` 文件中。这些报告文件位于 `<device-tester-extract-location>/results/<execution-id>/` 下。两个报告都捕获测试套件执行的结果。有关 IDT 用于这些报告的架构的更多信息，请参阅 [查看 IDT 测试结果和日志](idt-review-results-logs.md)

要在 `suite-name_report.xml` 文件中填充内容，您必须在测试执行结束前使用 `SendResult` 命令向 IDT 报告测试结果。如果 IDT 找不到测试结果，则会针对该测试用例发出错误。以下 Python 摘录显示了用于向 IDT 发送测试结果的命令：

```
request-variable = SendResultRequest(TestResult(result))
client.send_result(request-variable)
```

如果您不通过 API 报告结果，IDT 会在测试构件文件夹中查找测试结果。此文件夹的路径存储在 IDT 上下文中的 `testData.testArtifactsPath` 文件中。在此文件夹中，IDT 将找到的第一个按字母顺序排序的 XML 文件用作测试结果。

如果您的测试逻辑生成 JUnit XML 结果，您可以将测试结果写入构件文件夹下的 XML 文件中，以直接向 IDT 提供结果，而不必解析结果后再使用 API 将其提交给 IDT。

如果使用此方法，请确保您的测试逻辑准确汇总了测试结果，并将结果文件格式化为与 `suite-name_report.xml` 文件相同的格式。IDT 不会对您提供的数据进行任何验证，但以下情况除外：
+ IDT 会忽略 `testsuites` 标签的所有属性。相反，它会从其他报告的测试组结果计算标签属性。
+ `testsuites` 中必须至少存在一个 `testsuite` 标签。

IDT 对所有测试用例使用相同的构件文件夹，并且不会在两次测试运行之间删除结果文件。因此，如果 IDT 读取了错误的文件，此方法也可能会导致错误的报告。我们建议您在所有测试用例中对生成的 XML 结果文件使用相同的名称，以覆盖每个测试用例的结果，并将正确的结果提供给 IDT 使用。您可以在测试套件中使用混合方法来进行报告，即：对某些测试用例使用 XML 结果文件，同时通过 API 提交其他测试用例的结果。但是，我们不建议采用这种方法。

## 指定退出行为
<a name="test-exec-exiting"></a>

将您的文本可执行文件配置为始终以退出代码 0 退出，即使测试用例报告失败或错误结果时也不例外。仅使用非零退出代码来表示测试用例未运行，或者表示测试用例可执行文件无法向 IDT 传达任何结果。当 IDT 收到非零退出代码时，这表示测试用例遇到了阻碍其运行的错误。

在以下事件中，IDT 可能会请求或期望测试用例在完成之前停止运行。您可以使用此信息来配置测试用例可执行文件，以检测测试用例中的每个事件：

**超时**  
当测试用例的运行时间超过 `test.json` 文件中指定的超时值时发生。如果测试运行器使用 `timeout-multiplier` 参数来指定超时乘数，则 IDT 会使用该乘数来计算超时值。  
要检测此事件，请使用 IDT\$1TEST\$1TIMEOUT 环境变量。当测试运行器启动测试时，IDT 会将 IDT\$1TEST\$1TIMEOUT 环境变量的值设置为计算得出的超时值（以秒为单位），并将该变量传递给测试用例可执行文件。您可以读取变量值来设置相应的计时器。

**中断**  
在测试运行器中断 IDT 时发生。例如，按下 Ctrl\$1C。  
终端会将信号传播到所有子进程，因此您只需在测试用例中配置信号处理程序来检测中断信号即可。  
或者，也可以定期轮询 API 以检查 `PollForNotifications` API 响应中 `CancellationRequested` 布尔值的值。当 IDT 收到中断信号时，它会将 `CancellationRequested` 布尔值设置为 `true`。

**首次失败时停止**  
发生的条件为：与当前测试用例并行运行的测试用例失败，并且测试运行器使用了 `stop-on-first-failure` 参数来指定 IDT 应当在遇到任何失败时停止运行。  
要检测此事件，您可以定期轮询 API 以检查 `PollForNotifications` API 响应中 `CancellationRequested` 布尔值的值。如果 IDT 遇到故障并且已配置为在首次失败时停止，它会将 `CancellationRequested` 布尔值设置为 `true`。

发生其中任何一个事件时，IDT 会等待 5 分钟，让当前正在运行的测试用例完成运行。如果所有正在运行的测试用例未能在 5 分钟内退出，IDT 会强制停止它们的每个进程。如果 IDT 没有在进程结束之前收到测试结果，它会将测试用例标记为已超时。作为一种最佳实践，您应确保测试用例在遇到其中一个事件时执行以下操作：

1. 停止运行正常的测试逻辑。

1. 清理所有的临时资源，例如被测设备上的测试构件。

1. 向 IDT 报告测试结果，例如测试失败或错误。

1. 退出。

# 使用 IDT 上下文
<a name="idt-context"></a>

IDT 运行测试套件时，测试套件可以访问一组数据，这些数据可用于确定每个测试的运行方式。这些数据被称为 IDT 上下文。例如，测试运行器在 `userdata.json` 文件中提供的用户数据配置可用于 IDT 环境中的测试套件。

IDT 上下文可以被视为只读 JSON 文档。测试套件可以使用对象、阵列、数字等标准 JSON 数据类型从上下文中检索数据并将数据写入上下文。

## 上下文架构
<a name="idt-context-schema"></a>

IDT 上下文采用以下格式：

```
{
    "config": {
        <config-json-content>
        "timeoutMultiplier": timeout-multiplier
    },
    "device": {
        <device-json-device-element>
    },
    "devicePool": {
        <device-json-pool-element>
    },
    "resource": {
        "devices": [
            {
                <resource-json-device-element>
                "name": "<resource-name>"
            }
        ]
    },
    "testData": {
        "awsCredentials": {
            "awsAccessKeyId": "<access-key-id>",
            "awsSecretAccessKey": "<secret-access-key>",
            "awsSessionToken": "<session-token>"
        },
        "logFilePath": "/path/to/log/file"
    },
    "userData": {
        <userdata-json-content>
    }
}
```

`config`  
[`config.json`文件](set-custom-idt-config.md#config-json-custom)中的信息。`config` 字段还包含以下附加字段：    
`config.timeoutMultiplier`  
测试套件使用的任何超时值的乘数。此值由 IDT CLI 中的测试运行器指定。默认值为 `1`。

`device`  
有关为测试运行选择的设备的信息。此信息等同于所选设备[`device.json`文件](set-custom-idt-config.md#device-config-custom)中的 `devices` 阵列元素。

`devicePool`  
有关为测试运行选择的设备池的信息。此信息等同于 `device.json` 文件中为所选设备池定义的顶级设备池阵列元素。

`resource`  
`resource.json` 文件中有关资源设备的信息。    
`resource.devices`  
此信息等同于 `resource.json` 文件中定义的 `devices` 阵列。每个 `devices` 元素都包括以下附加字段：    
`resource.device.name`  
资源的名称。此值设置为 `test.json` 文件中的 `requiredResource.name` 值。

`testData.awsCredentials`  
测试用于连接到 AWS 云的 AWS 凭证。此信息是从 `config.json` 文件中获得的。

`testData.logFilePath`  
测试用例写入日志消息的日志文件的路径。如果日志文件不存在，则会创建。

`userData`  
[`userdata.json`文件](set-custom-idt-config.md#userdata-config-custom)中由测试运行器提供的信息。

## 在上下文中访问数据
<a name="accessing-context-data"></a>

您可以使用 JSON 文件中的 JSONPath 表示法以及带 `GetContextValue` 和 `GetContextString` API 的文本可执行文件查询上下文。访问 IDT 上下文的 JSONPath 字符串的语法各不相同，如下所示：
+ 在 `suite.json` 和`test.json` 中，使用 `{{query}}`。也就是说，不要使用根元素 `$.` 开始表达式。
+ 在 `test_orchestrator.yaml` 中，使用 `{{query}}`。

  如果您使用已弃用的状态机，那么在 `state_machine.json` 中，请使用 `{{$.query}}`。
+ 在 API 命令中，根据命令的不同，您可以使用 `query` 或 `{{$.query}}`。有关更多信息，请参阅开发工具包中的内联文档。

下表描述典型 JSONPath 表达式中的运算符：


| Operator  | Description  | 
| --- |--- |
| \$1 | The root element. Because the top-level context value for IDT is an object, you will typically use \$1. to start your queries. | 
| .childName | Accesses the child element with name childName from an object. If applied to an array, yields a new array with this operator applied to each element. The element name is case sensitive. For example, the query to access the awsRegion value in the config object is \$1.config.awsRegion. | 
| [start:end] | Filters elements from an array, retrieving items beginning from the 开启 index and going up to the 最终 index, both inclusive. | 
| [index1, index2, ... , indexN] | Filters elements from an array, retrieving items from only the specified indices. | 
| [?(expr)] | Filters elements from an array using the expr expression. This expression must evaluate to a boolean value. | 

要创建筛选表达式，请使用以下语法：

```
<jsonpath> | <value> operator <jsonpath> | <value> 
```

在此语法中：
+ `jsonpath` 是一个使用标准 JSON 语法的 JSONPath。
+ `value` 是使用标准 JSON 语法的任何自定义值。
+ `operator` 下列运算符之一：
  + `<`（小于）
  + `<=`（小于或等于）
  + `==`（等于）

    如果表达式中的 jsonPath 或值是阵列、布尔值或对象值，则这是您可以使用的唯一受支持的二进制运算符。
  + `>=`（大于或等于）
  + `>`（大于）
  + `=~`（正则表达式匹配）。要在过滤器表达式中使用此运算符，表达式左侧的 jsonPath 或值必须计算为字符串，而右侧必须是遵循 [RE2 语法](https://github.com/google/re2/wiki/Syntax)的模式值。

您可以使用 \$1\$1*query*\$1\$1 形式的 JSONPath 查询作为 `test.json` 文件 `args` 和`environmentVariables` 字段以及 `suite.json` 文件 `environmentVariables` 字段中的占位符字符串。IDT 执行上下文查找，并使用查询的评估值填充字段。例如，在 `suite.json` 文件中，您可以使用占位符字符串来指定随每个测试用例而变化的环境变量值，IDT 将使用每个测试用例的正确值填充环境变量。但是，当您在 `test.json` 和 `suite.json` 文件中使用占位符字符串时，以下注意事项适用于您的查询：
+ 查询中每次出现的 `devicePool` 密钥都必须全部使用小写字母。也就是说，改用 `devicepool`。
+ 对于数组，只能使用字符串数组。此外，数组使用非标准 `item1, item2,...,itemN` 格式。如果数组仅包含一个元素，则将其序列化为 `item`，使其与字符串字段没有区别。
+ 不能使用占位符从上下文中检索对象。

出于这些考虑，我们建议您尽可能使用 API 来访问测试逻辑中的上下文，而不是 `test.json` 和 `suite.json` 文件中的占位符字符串。但是，在某些情况下，使用 JsonPath 占位符检索要设置为环境变量的单个字符串可能会更方便。

# 为测试运行者配置设置
<a name="set-custom-idt-config"></a>

要运行自定义测试套件，测试运行器必须根据他们要运行的测试套件配置设置。设置是根据位于该 `<device-tester-extract-location>/configs/` 文件夹中的配置文件模板指定的。如果需要，测试运行器还必须设置 IDT 用于连接 AWS 云的 AWS 凭证。

作为测试编写者，您需要配置这些文件来[调试您的测试套件](run-debug-custom-tests.md)。您必须向测试运行器提供说明，以便他们可以根据需要配置以下设置来运行您的测试套件。

## 配置 device.json
<a name="device-config-custom"></a>

`device.json` 文件包含有关运行测试的设备的信息（例如，IP 地址、登录信息、操作系统和 CPU 架构）。

测试运行器可以使用位于 `<device-tester-extract-location>/configs/` 文件夹中的以下模板 `device.json` 文件来提供此信息。

```
[
    {
        "id": "<pool-id>",
        "sku": "<pool-sku>",
        "features": [
            {
                "name": "<feature-name>",             
                "value": "<feature-value>",                
                "configs": [
                    {
                        "name": "<config-name>",                    
                        "value": "<config-value>"
                    }
                ],
            }
        ],     
        "devices": [
            {
                "id": "<device-id>",              
                "connectivity": {
                    "protocol": "ssh | uart | docker",                   
                    // ssh
                    "ip": "<ip-address>",
                    "port": <port-number>,
                    "auth": {
                        "method": "pki | password",
                        "credentials": {
                            "user": "<user-name>", 
                            // pki
                            "privKeyPath": "/path/to/private/key",
                                         
                            // password
                            "password": "<password>",
                        }
                    },
                    
                    // uart
                    "serialPort": "<serial-port>",
                    
                    // docker
                    "containerId": "<container-id>",
                    "containerUser": "<container-user-name>",
                }
            }
        ]
    }
]
```

包含值的所有字段都为必填字段，如下所述：

`id`  
一个用户定义的字母数字 ID，用于唯一地标识称作*设备池*的设备集合。属于池的设备必须具有相同的硬件。运行一组测试时，池中的设备将用于对工作负载进行并行化处理。多个设备用于运行不同测试。

`sku`  
唯一标识所测试设备的字母数字值。该 SKU 用于跟踪符合条件的设备。  
如果需要在 AWS Partner 设备目录中列出您的主板，在此处指定的 SKU 必须与在列表过程中使用的 SKU 相匹配。

`features`  
可选。包含设备支持的功能的数组。设备功能是您在测试套件中配置的用户定义值。您必须向测试运行器提供有关要包含在 `device.json` 文件中的功能名称和值的信息。例如，如果您想测试一台可充当其他设备的 MQTT 服务器的设备，则可以配置测试逻辑来验证名为 `MQTT_QOS` 的功能的特定支持级别。测试运行器提供此功能名称，并将该功能值设置为其设备支持的 QOS 级别。您可以通过 `devicePool.features` 查询从 [IDT 上下文](idt-context.md)中检索所提供的信息，也可以通过 `pool.features` 查询从[测试编排工具上下文](idt-state-machine.md#state-machine-context)中检索所提供的信息。    
`features.name`  
特征的名称。  
`features.value`  
支持的功能值。  
`features.configs`  
该功能的配置设置（如果需要）。    
`features.config.name`  
配置设置的名称。  
`features.config.value`  
支持的设置值。

`devices`  
池中待测试的设备阵列。至少需要选择一个设备。  <a name="device-array-fields"></a>  
`devices.id`  
用户定义的测试的设备的唯一标识符。  
`connectivity.protocol`  
用于与此设备通信的通信协议。池中的每台设备都必须使用相同的协议。  
目前，唯一支持的值，对于物理设备为 `ssh` 和 `uart`，对于 Docker 容器为 `docker`。  
`connectivity.ip`  
测试的设备 IP 地址。  
此属性仅在 `connectivity.protocol` 设置为 `ssh` 时适用。  
`connectivity.port`  
可选。用于 SSH 连接的端口号。  
默认值为 22。  
此属性仅在 `connectivity.protocol` 设置为 `ssh` 时适用。  
`connectivity.auth`  
连接的身份验证信息。  
此属性仅在 `connectivity.protocol` 设置为 `ssh` 时适用。    
`connectivity.auth.method`  
用于通过给定的连接协议访问设备的身份验证方法。  
支持的值为：  
+ `pki`
+ `password`  
`connectivity.auth.credentials`  
用于身份验证的凭证。    
`connectivity.auth.credentials.password`  
该密码用于登录到正在测试的设备。  
此值仅在 `connectivity.auth.method` 设置为 `password` 时适用。  
`connectivity.auth.credentials.privKeyPath`  
用于登录所测试设备的私有密钥的完整路径。  
此值仅在 `connectivity.auth.method` 设置为 `pki` 时适用。  
`connectivity.auth.credentials.user`  
用于登录所测试设备的用户名。  
`connectivity.serialPort`  
可选。设备所连接的串行端口。  
此属性仅在 `connectivity.protocol` 设置为 `uart` 时适用。  
`connectivity.containerId`  
所测试的 Docker 容器的容器 ID 或名称。  
此属性仅在 `connectivity.protocol` 设置为 `ssh` 时适用。  
`connectivity.containerUser`  
可选。容器内用户对用户的名称。默认值为 Dockerfile 中提供的用户。  
默认值为 22。  
此属性仅在 `connectivity.protocol` 设置为 `ssh` 时适用。
要检查测试运行器是否为测试配置了错误的设备连接，可以从测试编排工具上下文中检索 `pool.Devices[0].Connectivity.Protocol`，并将其与 `Choice` 状态下的预期值进行比较。如果使用的协议不正确，则使用 `LogMessage` 状态打印一条消息并过渡到 `Fail` 状态。  
或者，您可以使用错误处理代码来报告错误设备类型的测试失败。

## （可选）配置 userdata.json
<a name="userdata-config-custom"></a>

`userdata.json` 文件包含测试套件所需但 `device.json` 文件中未指定的任何其他信息。此文件的格式取决于测试套件中定义的[`userdata_scheme.json`文件](idt-json-config.md#userdata-schema-json)。如果您是测试编写者，请务必将此信息提供给将运行您编写的测试套件的用户。

## （可选）配置 resource.json
<a name="resource-config-custom"></a>

`resource.json` 文件包含有关将用作资源设备的所有设备的信息。资源设备是测试被测设备的某些功能所需的设备。例如，要测试设备的蓝牙功能，您可以使用资源设备来测试您的设备能否成功连接到该设备。资源设备是可选的，您可以根据需要任意数量的资源设备。作为测试编写者，您可以使用 [test.json 文件](idt-json-config.md#test-json)来定义测试所需的资源设备功能。然后，测试运行器使用 `resource.json` 文件提供具有所需功能的资源设备池。请务必将此信息提供给将运行您编写的测试套件的用户。

测试运行器可以使用位于 `<device-tester-extract-location>/configs/` 文件夹中的以下模板 `resource.json` 文件来提供此信息。

```
[
    {
        "id": "<pool-id>",
        "features": [
            {
                "name": "<feature-name>",             
                "version": "<feature-version>",                
                "jobSlots": <job-slots>
            }
        ],     
        "devices": [
            {
                "id": "<device-id>",              
                "connectivity": {
                    "protocol": "ssh | uart | docker",                   
                    // ssh
                    "ip": "<ip-address>",
                    "port": <port-number>,
                    "auth": {
                        "method": "pki | password",
                        "credentials": {
                            "user": "<user-name>", 
                            // pki
                            "privKeyPath": "/path/to/private/key",
                                         
                            // password
                            "password": "<password>",
                        }
                    },
                    
                    // uart
                    "serialPort": "<serial-port>",
                    
                    // docker
                    "containerId": "<container-id>",
                    "containerUser": "<container-user-name>",
                }
            }
        ]
    }
]
```

包含值的所有字段都为必填字段，如下所述：

`id`  
一个用户定义的字母数字 ID，用于唯一地标识称作*设备池*的设备集合。属于池的设备必须具有相同的硬件。运行一组测试时，池中的设备将用于对工作负载进行并行化处理。多个设备用于运行不同测试。

`features`  
可选。包含设备支持的功能的数组。此字段中所需的信息在测试套件的 [test.json 文件](idt-json-config.md#test-json)中定义，这些信息用于确定要运行哪些测试以及如何运行这些测试。如果测试套件不需要任何功能，则此字段不是必填字段。    
`features.name`  
功能的名称。  
`features.version`  
功能版本。  
`features.jobSlots`  
用于指明可以同时使用该设备的测试次数的设置。默认值为 `1`。

`devices`  <a name="device-array"></a>
池中待测试的设备阵列。至少需要选择一个设备。  <a name="device-array-fields"></a>  
`devices.id`  
用户定义的测试的设备的唯一标识符。  
`connectivity.protocol`  
用于与此设备通信的通信协议。池中的每台设备都必须使用相同的协议。  
目前，唯一支持的值，对于物理设备为 `ssh` 和 `uart`，对于 Docker 容器为 `docker`。  
`connectivity.ip`  
测试的设备 IP 地址。  
此属性仅在 `connectivity.protocol` 设置为 `ssh` 时适用。  
`connectivity.port`  
可选。用于 SSH 连接的端口号。  
默认值为 22。  
此属性仅在 `connectivity.protocol` 设置为 `ssh` 时适用。  
`connectivity.auth`  
连接的身份验证信息。  
此属性仅在 `connectivity.protocol` 设置为 `ssh` 时适用。    
`connectivity.auth.method`  
用于通过给定的连接协议访问设备的身份验证方法。  
支持的值为：  
+ `pki`
+ `password`  
`connectivity.auth.credentials`  
用于身份验证的凭证。    
`connectivity.auth.credentials.password`  
该密码用于登录到正在测试的设备。  
此值仅在 `connectivity.auth.method` 设置为 `password` 时适用。  
`connectivity.auth.credentials.privKeyPath`  
用于登录所测试设备的私有密钥的完整路径。  
此值仅在 `connectivity.auth.method` 设置为 `pki` 时适用。  
`connectivity.auth.credentials.user`  
用于登录所测试设备的用户名。  
`connectivity.serialPort`  
可选。设备所连接的串行端口。  
此属性仅在 `connectivity.protocol` 设置为 `uart` 时适用。  
`connectivity.containerId`  
所测试的 Docker 容器的容器 ID 或名称。  
此属性仅在 `connectivity.protocol` 设置为 `ssh` 时适用。  
`connectivity.containerUser`  
可选。容器内用户对用户的名称。默认值为 Dockerfile 中提供的用户。  
默认值为 22。  
此属性仅在 `connectivity.protocol` 设置为 `ssh` 时适用。

## （可选）配置 config.json
<a name="config-json-custom"></a>

`config.json` 文件包含 IDT 的配置信息。通常，测试运行器无需修改此文件，除非提供他们的 IDT AWS 用户凭证和 AWS 区域（可选）。如果提供了具有所需权限的 AWS 凭证，则 AWS IoT Device Tester 会收集使用情况指标并将其提交给 AWS。这是一项可选功能，用来改进 IDT 功能。有关更多信息，请参阅 [IDT 使用量指标](idt-usage-metrics.md)。

测试运行器可以通过以下方式之一配置 AWS 凭证：
+ **凭证文件**

  IDT 使用与 AWS CLI 相同的凭证文件。有关更多信息，请参阅[配置和凭证文件](https://docs.aws.amazon.com/cli/latest/userguide/cli-config-files.html)。

  凭证文件的位置因您使用的操作系统而异：
  + macOS、Linux：`~/.aws/credentials`
  + Windows：`C:\Users\UserName\.aws\credentials`
+ **环境变量**：

  环境变量是由操作系统维护且由系统命令使用的变量。在 SSH 会话期间定义的变量在该会话关闭后不可用。IDT 可使用 `AWS_ACCESS_KEY_ID` 和 `AWS_SECRET_ACCESS_KEY` 环境变量来存储 AWS 凭证

  要在 Linux、macOS 或 Unix 上设置这些变量，请使用 **export**：

  ```
  export AWS_ACCESS_KEY_ID=<your_access_key_id>
  export AWS_SECRET_ACCESS_KEY=<your_secret_access_key>
  ```

  要在 Windows 上设置这些变量，请使用 **set**：

  ```
  set AWS_ACCESS_KEY_ID=<your_access_key_id>
  set AWS_SECRET_ACCESS_KEY=<your_secret_access_key>
  ```

要配置 IDT 的 AWS 凭证，测试运行器需要编辑 `<device-tester-extract-location>/configs/` 文件夹中 `config.json` 文件中的 `auth` 部分。

```
{
    "log": {
        "location": "logs"
    },
    "configFiles": {
        "root": "configs",
        "device": "configs/device.json"
    },
    "testPath": "tests",
    "reportPath": "results",
    "awsRegion": "<region>",
    "auth": {
        "method": "file | environment",
        "credentials": {
            "profile": "<profile-name>"
        }
    }
}
]
```

包含值的所有字段都为必填字段，如下所述：

**注意**  
此文件中的所有路径都是相对于 *<device-tester-extract-location>* 定义的。

`log.location`  
*<device-tester-extract-location>* 中日志文件夹的路径。

`configFiles.root`  
包含配置文件的文件夹的路径。

`configFiles.device`  
`device.json` 文件的路径。

`testPath`  
包含测试套件的文件夹的路径。

`reportPath`  
IDT 运行测试套件后将包含测试结果的文件夹的路径。

`awsRegion`  
可选。测试套件将使用的 AWS 区域。如果未设置，则测试套件将使用每个测试套件中指定的默认区域。

`auth.method`  
IDT 用于检索 AWS 凭证的方法。支持的值是用于从凭证文件中检索凭证的 `file`，以及使用环境变量检索凭证的 `environment`。

`auth.credentials.profile`  
要从凭证文件中使用的凭证配置文件。此属性仅在 `auth.method` 设置为 `file` 时适用。

# 调试和运行自定义测试套件
<a name="run-debug-custom-tests"></a>

设置[所需的配置](set-custom-idt-config.md)后，IDT 就可以运行您的测试套件了。完整测试套件的运行时取决于硬件和测试套件的组成。作为参考，在 Raspberry Pi 3B 上完成整套 AWS IoT Greengrass 资格测试大约需要 30 分钟。

在编写测试套件时，您可以使用 IDT 在调试模式下运行测试套件，以便在运行代码之前检查代码或将其提供给测试运行者。

## 在调试模式下运行 IDT
<a name="idt-debug-mode"></a>

由于测试套件依赖于 IDT 来与设备交互、提供上下文和接收结果，因此如果没有任何 IDT 交互，您就无法在 IDE 中简单地调试测试套件。为此，IDT CLI 提供了 `debug-test-suite` 命令，供您用于在调试模式下运行 IDT。运行以下命令以查看 `debug-test-suite` 的可用选项：

```
devicetester_[linux | mac | win_x86-64] debug-test-suite -h
```

当您在调试模式下运行 IDT 时，IDT 实际上并不启动测试套件或运行编排工具；相反，它会与您的 IDE 交互以响应在 IDE 中运行的测试套件所发出的请求，并将日志输出到控制台。IDT 不会超时，而会等待退出，直到手动中断。在调试模式下，IDT 也不运行测试编排工具，也不会生成任何报告文件。要调试测试套件，您必须使用 IDE 来提供 IDT 通常从配置 JSON 文件中获得的一些信息。务必提供以下信息：
+ 每个测试的环境变量和参数。IDT 不会从 `test.json` 或 `suite.json` 中读取此信息。
+ 用于选择资源设备的参数。IDT 不会从 `test.json` 中读取此信息。

要调试您的测试套件，请完成以下步骤：

1.  创建运行测试套件所需的设置配置文件。例如，如果您的测试套件需要 `device.json`、`resource.json` 和 `user data.json`，请确保根据需要来配置所有测试套件。

1. 运行以下命令将 IDT 置于调试模式，然后选择运行测试需要的所有设备。

   ```
   devicetester_[linux | mac | win_x86-64] debug-test-suite [options]
   ```

   运行此命令后，IDT 会等待来自测试套件的请求，然后响应这些请求。IDT 还会生成 IDT 客户端软件开发工具包案例处理所需的环境变量。

1. 在您的 IDE 中，使用 `run` 或 `debug` 配置来执行以下操作：

   1. 设置 IDT 生成的环境变量的值。

   1. 设置您在 `test.json` 和 `suite.json` 文件中指定的任何环境变量或参数的值。

   1. 根据需要设置断点。

1. 在 IDE 中运行测试套件。

   您可以根据需要多次调试和重新运行测试套件。IDT 在调试模式下不会超时。

1.  完成调试后，请中断 IDT 以退出调试模式。

## 用于运行测试的 IDT CLI 命令
<a name="idt-cli-commands"></a>

以下小节介绍了 IDT CLI 命令。

------
#### [ IDT v4.0.0 ]

`help`  <a name="idt-command-help"></a>
列出有关指定命令的信息。

`list-groups`  <a name="idt-command-list-groups"></a>
列出给定测试套件中的组。

`list-suites`  <a name="idt-command-list-suites"></a>
列出可用的测试套件。

`list-supported-products`  
列出您的 IDT 版本支持的产品（本例中为 AWS IoT Greengrass 版本），以及当前 IDT 版本适用的 AWS IoT Greengrass 资格测试套件版本。

`list-test-cases`  
列出给定测试组中的测试用例。支持以下选项：  
+ `group-id`. 要搜索的测试组。此选项是必需的，必须指定单个组。

`run-suite`  
对某个设备池运行一组测试。以下是一些常用的选项：  
+ `suite-id`. 要运行的测试套件版本。如果未指定，IDT 将使用 `tests` 文件夹中的最新版本。
+ `group-id`. 要以逗号分隔的列表形式运行的测试组。如果未指定，IDT 将运行测试套件中的所有测试组。
+ `test-id`. 要以逗号分隔的列表形式运行的测试用例。指定后，`group-id` 必须指定单个组。
+ `pool-id`. 要测试的设备池。如果您在 `device.json` 文件中定义了多个设备池，则测试运行器必须指定一个池。
+ `timeout-multiplier`。将 IDT 配置为使用用户定义的乘数来修改 `test.json` 文件中为测试指定的测试执行超时。
+ `stop-on-first-failure`. 将 IDT 配置为在第一次失败时停止执行。应将此选项与 `group-id` 结合使用来调试指定的测试组。
+ `userdata`。设置包含运行测试套件所需用户数据信息的文件。只有在测试套件的 `suite.json` 文件中 `userdataRequired` 被设置为 true 时，才需要这样做。
有关 `run-suite` 选项的更多信息，请使用 `help` 选项：  

```
devicetester_[linux | mac | win_x86-64] run-suite -h
```

`debug-test-suite`  
在调试模式下运行测试套件。有关更多信息，请参阅 [在调试模式下运行 IDT](#idt-debug-mode)。

------

# 查看 IDT 测试结果和日志
<a name="idt-review-results-logs"></a>

本节介绍 IDT 生成控制台日志和测试报告的格式。

## 控制台消息格式
<a name="idt-console-format"></a>

AWS IoT Device Tester 在启动测试套件时使用标准格式将消息输出到控制台。以下摘录显示了一个由 IDT 生成的控制台消息示例。

```
time="2000-01-02T03:04:05-07:00" level=info msg=Using suite: MyTestSuite_1.0.0 
executionId=9a52f362-1227-11eb-86c9-8c8590419f30
```

大多数控制台消息都包含以下字段：

`time`  
所记录事件的完整 ISO 8601 时间戳。

`level`  
所记录事件的消息级别。通常，记录的消息级别为 `info`、`warn` 或 `error`。如果遇到导致其提前退出的预期事件，IDT 会发出 `fatal` 或 `panic` 消息。

`msg`  
记录的消息。

`executionId`  
当前 IDT 流程的唯一 ID 字符串。此 ID 用于区分各个 IDT 运行。

测试套件生成的控制台消息提供了有关被测设备以及 IDT 运行的测试套件、测试组和测试用例的更多信息。以下摘录显示了从测试套件生成的控制台消息的示例。

```
time="2000-01-02T03:04:05-07:00" level=info msg=Hello world! suiteId=MyTestSuite
groupId=myTestGroup testCaseId=myTestCase deviceId=my-device
executionId=9a52f362-1227-11eb-86c9-8c8590419f30
```

控制台消息中特定于测试套件的部分包含以下字段：

`suiteId`  
当前正在运行的测试套件的名称。

`groupId`  
当前正在运行的测试组的 ID。

`testCaseId`  
当前正在运行的测试用例的 ID。

`deviceId`  
当前测试用例正在使用的被测设备的 ID。

要在 IDT 完成测试运行后将测试摘要打印到控制台，您必须在测试编排工具中包含一个 [`Report` 状态](idt-state-machine.md#state-report)。测试摘要包含有关测试套件、每个已运行组的测试结果以及生成的日志和报告文件位置的信息。以下示例显示了测试摘要消息。

```
========== Test Summary ==========
Execution Time:     5m00s
Tests Completed:    4
Tests Passed:       3
Tests Failed:       1
Tests Skipped:      0
----------------------------------
Test Groups:
    GroupA:         PASSED
    GroupB:         FAILED
----------------------------------
Failed Tests:
    Group Name: GroupB
        Test Name: TestB1
            Reason: Something bad happened
----------------------------------
Path to IoT Device Tester Report: /path/to/awsiotdevicetester_report.xml
Path to Test Execution Logs: /path/to/logs
Path to Aggregated JUnit Report: /path/to/MyTestSuite_Report.xml
```

## AWS IoT Device Tester 报告架构
<a name="idt-report"></a>

 `awsiotdevicetester_report.xml` 是一份包含以下信息的签名报告：
+ IDT 版本。
+ 测试套件版本。
+ 用于对报告进行签名的报告签名和密钥。
+ `device.json` 文件中指定的设备 SKU 和设备池名称。
+ 经过测试的产品版本和设备功能。
+ 测试结果的摘要汇总。此信息与 `suite-name_report.xml` 文件中包含的信息相同。

```
<apnreport>
    <awsiotdevicetesterversion>idt-version</awsiotdevicetesterversion>
    <testsuiteversion>test-suite-version</testsuiteversion>
    <signature>signature</signature>
    <keyname>keyname</keyname>
    <session>
        <testsession>execution-id</testsession>
        <starttime>start-time</starttime>
        <endtime>end-time</endtime>
    </session>
    <awsproduct>
        <name>product-name</name>
        <version>product-version</version>
        <features>
            <feature name="<feature-name>" value="supported | not-supported | <feature-value>" type="optional | required"/>
        </features>
    </awsproduct>
    <device>
        <sku>device-sku</sku>
        <name>device-name</name>
        <features>
            <feature name="<feature-name>" value="<feature-value>"/>
        </features>
        <executionMethod>ssh | uart | docker</executionMethod>
    </device>
    <devenvironment>
        <os name="<os-name>"/>
    </devenvironment>
    <report>
        <suite-name-report-contents>
    </report>
</apnreport>
```

`awsiotdevicetester_report.xml` 文件包含一个 `<awsproduct>` 标签，其中包含有关正测试的产品以及在运行测试套件后验证的产品功能的信息。`<awsproduct>` 标签中使用的属性

`name`  
所测试的产品的名称。

`version`  
所测试的产品的版本。

`features`  
验证的功能。标记为 `required` 的功能是测试套件验证设备所必需的。以下代码段演示了此信息在 `awsiotdevicetester_report.xml` 文件中的显示方式。  

```
<feature name="ssh" value="supported" type="required"></feature>
```
标记为 `optional` 的功能不是验证所必需的。以下代码段显示了可选功能。  

```
<feature name="hsi" value="supported" type="optional"></feature> 
<feature name="mqtt" value="not-supported" type="optional"></feature>
```

## 测试套件报告架构
<a name="suite-report"></a>

`suite-name_Result.xml` 报告采用 [JUnit XML 格式](https://llg.cubic.org/docs/junit/)。您可以将它集成到持续集成和开发平台，例如 [Jenkins](https://jenkins.io/)、[Bamboo](https://www.atlassian.com/software/bamboo) 等。报告包含测试结果的摘要汇总。

```
<testsuites name="<suite-name> results" time="<run-duration>" tests="<number-of-test>" failures="<number-of-tests>" skipped="<number-of-tests>" errors="<number-of-tests>" disabled="0">
    <testsuite name="<test-group-id>" package="" tests="<number-of-tests>" failures="<number-of-tests>" skipped="<number-of-tests>" errors="<number-of-tests>" disabled="0">
        <!--success-->
        <testcase classname="<classname>" name="<name>" time="<run-duration>"/>
        <!--failure-->
        <testcase classname="<classname>" name="<name>" time="<run-duration>">
            <failure type="<failure-type>">
                reason
            </failure>
        </testcase>
        <!--skipped-->
        <testcase classname="<classname>" name="<name>" time="<run-duration>">
            <skipped>
                reason
            </skipped>
        </testcase>
        <!--error-->
        <testcase classname="<classname>" name="<name>" time="<run-duration>">
            <error>
                reason
            </error>
        </testcase>
    </testsuite>
</testsuites>
```

`awsiotdevicetester_report.xml` 或 `suite-name_report.xml` 中的报告部分列出了运行的测试以及结果。

第一个 XML 标签 `<testsuites>` 包含测试执行情况的摘要。例如：

```
<testsuites name="MyTestSuite results" time="2299" tests="28" failures="0" errors="0" disabled="0">
````<testsuites>` 标签中使用的属性

`name`  
测试套件的名称。

`time`  
运行测试套件所用的时间（以秒为单位）。

`tests`  
执行的测试数。

`failures`  
已运行但未通过的测试数。

`errors`  
IDT 无法执行的测试数。

`disabled`  
此属性未使用，可以忽略。

如果出现测试失败或错误，则可以通过检查 `<testsuites>` XML 标签来确定失败的测试。`<testsuite>` 标签内的 `<testsuites>` XML 标签显示了测试组的测试结果摘要。例如：

```
<testsuite name="combination" package="" tests="1" failures="0" time="161" disabled="0" errors="0" skipped="0">
```

其格式与 `<testsuites>` 标签类似，但包含一个未使用并可忽略的 `skipped` 属性。在每个 `<testsuite>` XML 标签内部，对于一个测试组，所执行的每个测试都有 `<testcase>` 标签。例如：

```
<testcase classname="Security Test" name="IP Change Tests" attempts="1"></testcase>>
````<testcase>` 标签中使用的属性

`name`  
测试的名称。

`attempts`  
IDT 执行测试用例的次数。

当测试失败或出现错误时，将会在 `<failure>` 标签中添加包含用于故障排除的信息的 `<error>` 或 `<testcase>` 标签。例如：

```
<testcase classname="mcu.Full_MQTT" name="MQTT_TestCase" attempts="1">
	<failure type="Failure">Reason for the test failure</failure>
	<error>Reason for the test execution error</error>
</testcase>
```

# IDT 使用量指标
<a name="idt-usage-metrics"></a>

如果您提供具有所需权限的 AWS 证书，则 AWS IoT Device Tester 会收集使用情况指标并将其提交给 AWS。这是一项可选功能，用来改进 IDT 功能。IDT 将收集以下信息：
+ 用于运行 AWS 账户 IDT 的 ID
+  用于运行测试的 IDT AWS CLI 命令
+ 正在运行的测试套件
+ *<device-tester-extract-location>*文件夹中的测试套件
+ 设备池中配置的设备数量
+ 测试用例名称和运行时间
+ 测试结果信息，例如测试是通过、失败、遇到错误，还是已被跳过
+ 测试的产品功能
+ IDT 退出行为，例如意外退出或提前退出 

 IDT 发送的所有信息也会记录到 `<device-tester-extract-location>/results/<execution-id>/` 文件夹下的 `metrics.log` 文件中。您可以查看日志文件以检查在测试运行期间收集的信息。只有选择了收集使用量指标后，才会生成此文件。

要禁用指标收集，您无需采取其他操作。请不要存储您的 AWS 凭证，如果您确实存储了 AWS 凭据，也不要将`config.json`文件配置为访问它们。

## 配置您的 AWS 凭证
<a name="configure-aws-creds-for-metrics"></a>

如果您还没有 AWS 账户，则必须[创建一个](#idt-metrics-aws-account)。如果您已经拥有 AWS 账户，则只需为您的账户[配置所需的权限](#idt-metrics-permissions)，以允许 IDT 代表您向其发送使用量指标。 AWS 

### 步骤 1：创建一个 AWS 账户
<a name="idt-metrics-aws-account"></a>

在此步骤中，将创建并配置 AWS 账户。如果您已有 AWS 账户，请跳至 [步骤 2：为 IDT 配置权限](#idt-metrics-permissions)。

如果您没有 AWS 账户，请完成以下步骤来创建一个。

**报名参加 AWS 账户**

1. 打开[https://portal.aws.amazon.com/billing/注册。](https://portal.aws.amazon.com/billing/signup)

1. 按照屏幕上的说明操作。

   在注册时，将接到电话或收到短信，要求使用电话键盘输入一个验证码。

   当您注册时 AWS 账户，就会创建*AWS 账户根用户*一个。根用户有权访问该账户中的所有 AWS 服务 和资源。作为最佳安全实践，请为用户分配管理访问权限，并且只使用根用户来执行[需要根用户访问权限的任务](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#root-user-tasks)。

要创建管理员用户，请选择以下选项之一。


****  

| 选择一种方法来管理您的管理员 | 目标 | 方式 | 您也可以 | 
| --- | --- | --- | --- | 
| 在 IAM Identity Center 中 （推荐） | 使用短期凭证访问 AWS。这符合安全最佳实操。有关最佳实践的信息，请参阅《IAM 用户指南》**中的 [IAM 中的安全最佳实践](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#bp-users-federation-idp)。 | 有关说明，请参阅《AWS IAM Identity Center 用户指南》中的[入门](https://docs.aws.amazon.com//singlesignon/latest/userguide/getting-started.html)。 | 通过在《AWS Command Line Interface 用户指南[》 AWS IAM Identity Center中配置 AWS CLI 要使用的来](https://docs.aws.amazon.com//cli/latest/userguide/cli-configure-sso.html)配置编程访问权限。 | 
| 在 IAM 中 （不推荐使用） | 使用长期凭证访问 AWS。 | 按照《IAM 用户指南》中的[创建用于紧急访问的 IAM 用户](https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-started-emergency-iam-user.html)中的说明进行操作。 | 按照《IAM 用户指南》中的[管理 IAM 用户的访问密钥](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_credentials_access-keys.html)，配置编程式访问。 | 

### 步骤 2：为 IDT 配置权限
<a name="idt-metrics-permissions"></a>

在此步骤中，将配置 IDT 运行测试和收集 IDT 使用情况数据所需的权限。您可以使用 AWS 管理控制台 或 AWS Command Line Interface (AWS CLI) 为 IDT 创建 IAM 策略和用户，然后将策略附加到该用户。
+ [为 IDT 配置权限（控制台）](#idt-metrics-permissions-console)
+ [为 IDT 配置权限 (AWS CLI)](#idt-metrics-permissions-cli)<a name="idt-metrics-permissions-console"></a>

**为 IDT 配置权限（控制台）**

请按照以下步骤使用控制台为 IDT for AWS IoT Greengrass配置权限。

1. 登录 [IAM 控制台](https://console.aws.amazon.com/iam)。

1. 创建客户托管策略，该策略授权创建具有特定权限的角色。

   1. 在导航窗格中，选择 **策略**，然后选择 **创建策略**。

   1. 在 **JSON** 选项卡中，将占位符内容替换为以下策略。

------
#### [ JSON ]

****  

      ```
      {
          "Version":"2012-10-17",		 	 	 
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot-device-tester:SendMetrics"
                  ],
                  "Resource": "*"
              }
          ]
      }
      ```

------

   1. 选择**查看策略**。

   1. 对于 **Name (名称)**，请输入 **IDTUsageMetricsIAMPermissions**。在 **Summary (摘要)** 下，查看策略授予的权限。

   1. 选择**创建策略**。

1. 创建 IAM 用户并将权限附加到该用户。

   1. 创建 IAM 用户。按照 *IAM 用户指南*的[创建 IAM 用户（控制台）](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html#id_users_create_console)中的步骤 1 到 5 操作。如果您已创建 IAM 用户，请跳到下一步。

   1. 将权限附加到您的 IAM 用户：

      1. 在 **Set permissions (设置权限)** 页面上，选择 **Attach existing policies to user directly (直接附加现有策略到用户)**。

      1. 搜索您在上一步中创建的**IDTUsage指标IAMPermissions**策略。选中复选框。

   1. 选择**下一步：标签**。

   1. 选择 **Next: Review (下一步：审核)** 以查看您的选择摘要。

   1. 选择**创建用户**。

   1. 要查看用户的访问密钥（访问密钥 IDs 和私有访问密钥），请选择密码和访问密钥旁边的**显示**。要保存访问密钥，请选择**Download.csv (下载 .csv)**，然后将文件保存到安全位置。稍后您将使用此信息来配置您的 AWS 凭据文件。

 <a name="idt-metrics-permissions-cli"></a>

**为 IDT 配置权限 (AWS CLI)**

按照以下步骤 AWS CLI 使用配置 IDT 的 AWS IoT Greengrass权限。

1.  AWS CLI 如果尚未安装，请在您的计算机上进行安装和配置。按照《AWS Command Line Interface 用户指南》**中[安装 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) 的步骤来操作。
**注意**  
 AWS CLI 是一个开源工具，可用于通过命令行 shell 与 AWS 服务进行交互。

1. 创建以下客户托管策略，授予管理 IDT 和 AWS IoT Greengrass 角色的权限。

------
#### [ Linux or Unix ]

   ```
   aws iam create-policy --policy-name IDTUsageMetricsIAMPermissions --policy-document '{
       "Version": "2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "iot-device-tester:SendMetrics"
               ],
               "Resource": "*"
           }
       ]
   }'
   ```

------
#### [ Windows command prompt ]

   ```
   aws iam create-policy --policy-name IDTUsageMetricsIAMPermissions --policy-document
                                           '{\"Version\": \"2012-10-17\",		 	 	  \"Statement\": [{\"Effect\": \"Allow\", \"Action\": [\"iot-device-tester:SendMetrics\"], \"Resource": \"*\"}]}'
   ```

**注意**  
此步骤包含一个 Windows 命令提示符示例，因为它使用的 JSON 语法与 Linux、macOS 或 Unix 终端命令不同。

------
#### [ PowerShell ]

   ```
   aws iam create-policy --policy-name IDTUsageMetricsIAMPermissions --policy-document '{
       "Version": "2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "iot-device-tester:SendMetrics"
               ],
               "Resource": "*"
           }
       ]
   }'
   ```

------

1. 创建 IAM 用户并附加适用于 AWS IoT Greengrass的 IDT 所需的权限。

   1. 创建 IAM 用户。

      ```
      aws iam create-user --user-name user-name
      ```

   1. 将您创建的 `IDTUsageMetricsIAMPermissions` 策略附加到 IAM 用户。*user-name*替换为您的 IAM 用户名，*<account-id>*在命令中替换为您的 ID AWS 账户。

      ```
      aws iam attach-user-policy --user-name user-name --policy-arn arn:aws:iam::<account-id>:policy/IDTGreengrassIAMPermissions
      ```

1. 为用户创建私密访问密钥。

   ```
   aws iam create-access-key --user-name user-name
   ```

   将输出存储在安全位置。稍后您将使用此信息来配置您的 AWS 凭据文件。

## 向 ID AWS T 提供凭证
<a name="idt-metrics-creds"></a>

要允许 IDT 访问您的 AWS 凭证并向其提交指标 AWS，请执行以下操作：

1. 将您的 IAM 用户的 AWS 证书存储为环境变量或存储在证书文件中：

   1. 要使用环境变量，请运行以下命令。

------
#### [ Linux or Unix ]

      ```
      export AWS_ACCESS_KEY_ID=access-key
      export AWS_SECRET_ACCESS_KEY=secret-access-key
      ```

------
#### [ Windows Command Prompt (CMD) ]

      ```
      set AWS_ACCESS_KEY_ID=access-key
      set AWS_SECRET_ACCESS_KEY=secret-access-key
      ```

------
#### [ PowerShell ]

      ```
      $env:AWS_ACCESS_KEY_ID="access-key"
      $env:AWS_SECRET_ACCESS_KEY="secret-access-key"
      ```

------

   1. 要使用凭证文件，请将以下信息添加到 `~/.aws/credentials` 文件。

      ```
      [profile-name]
      aws_access_key_id=access-key
      aws_secret_access_key=secret-access-key
      ```

1. 配置 `config.json` 文件的 `auth` 部分。有关更多信息，请参阅 [（可选）配置 config.json](set-custom-idt-config.md#config-json-custom)。

# V2 版 IDT 故障排除 AWS IoT Greengrass
<a name="idt-troubleshooting"></a>

IDT fo AWS IoT Greengrass r V2 会根据错误的类型将错误写入不同位置。IDT 会将错误写入控制台、日志文件和测试报告中。

## 查找错误的位置
<a name="where-to-look"></a>

在测试运行时，控制台上会显示高级别错误，并且在所有测试完成后会显示失败测试的摘要。`awsiotdevicetester_report.xml` 包含导致测试失败的所有错误的摘要。IDT 将每个测试运行的日志文件都存储在一个包含 UUID 的目录中，用于在测试运行期间在控制台上显示的测试执行。

IDT 测试日志目录是 `<device-tester-extract-location>/results/<execution-id>/logs/`。此目录包含表中显示的以下文件。这对于调试非常有用。


| 文件 | 说明 | 
| --- | --- | 
| test\$1manager.log |  测试运行时写入控制台的日志。此文件末尾的结果摘要包含失败测试的列表。 此文件中的警告和错误日志可以为您提供有关失败的一些信息。  | 
| test-group-id/test-case-id/test-name.log | 测试组中特定测试的详细日志。对于部署 Greengrass 组件的测试，测试用例日志文件称为 greengrass-test-run.log。 | 
| test-group-id/test-case-id/greengrass.log |  AWS IoT Greengrass 核心软件的详细日志。IDT 在运行在设备上安装 C AWS IoT Greengrass ore 软件的测试时，会从被测设备复制此文件。有关此日志文件中消息的更多信息，请参阅[故障排除 AWS IoT Greengrass V2](troubleshooting.md)。 | 
| test-group-id/test-case-id/component-name.log | 测试运行期间部署的 Greengrass 组件的详细日志。IDT 在运行部署特定组件的测试时，会从被测设备复制组件日志文件。每个组件日志文件的名称对应于已部署组件的名称。有关此日志文件中消息的更多信息，请参阅[故障排除 AWS IoT Greengrass V2](troubleshooting.md)。 | 

## 解决 AWS IoT Greengrass V2 错误的 IDT
<a name="idt-gg-resolve-errors"></a>

在运行 IDT 之前 AWS IoT Greengrass，请准备好正确的配置文件。如果接收解析和配置错误，第一步应找到并使用适合环境的配置模板。

如果仍有问题，请参阅以下调试过程。

**Topics**
+ [

### 别名解析错误
](#alias-resolution-errors)
+ [

### 冲突错误
](#conflict-error)
+ [

### 无法启动测试错误
](#could-not-start-test)
+ [

### Docker 资格认证镜像存在错误
](#docker-qualification-image-exists)
+ [

### 无法读取凭证
](#failed-to-read-credential-windows)
+ [

### Greengrass 的 PreInstalled 指导错误
](#guice-errors)
+ [

### 签名异常无效
](#invalid-signature-exception-lambda)
+ [

### 机器学习资格认证错误
](#machine-learning-qualification-failure)
+ [

### 开放测试框架（OTF）部署失败
](#otf-deployment-failure)
+ [

### 解析错误
](#parse-error)
+ [

### 权限被拒绝错误
](#permission-denied-pwd-sudo)
+ [

### 资格认证报告生成错误
](#qualification-report-policy-error)
+ [

### 缺少必需参数错误
](#required-param-missing)
+ [

### macOS 上的安全例外
](#security-exception-macos)
+ [

### SSH 连接错误
](#ssh-connect-errors)
+ [

### 流管理器资格认证错误
](#stream-manager-qualification-failure)
+ [

### 超时错误
](#test-timeout)
+ [

### 版本检查错误
](#version-compatibility-check-failure)

### 别名解析错误
<a name="alias-resolution-errors"></a>

运行自定义测试套件时，您可能会在控制台和 `test_manager.log` 中看到以下错误。

```
Couldn't resolve placeholders: couldn't do a json lookup: index out of range
```

当 IDT 测试编排工具中配置的别名无法正确解析或者配置文件中不存在已解析的值时，就会发生此错误。要解决此错误，请确保 `device.json` 和 `userdata.json ` 包含测试套件所需的正确信息。有关 AWS IoT Greengrass 资格认证所需的配置的信息，请参见[配置 IDT 设置以运行 AWS IoT Greengrass 资格套件](set-config.md)。

### 冲突错误
<a name="conflict-error"></a>

当您在多台设备上同时运行 AWS IoT Greengrass 资格套件时，您可能会看到以下错误。

```
ConflictException: Component [com.example.IDTHelloWorld : 1.0.0] for account [account-id] already exists with state: [DEPLOYABLE] { RespMetadata: { StatusCode: 409, RequestID: “id” }, Message_: “Component [com.example.IDTHelloWorld : 1.0.0] for account [account-id] already exists with state: [DEPLOYABLE]” }
```

 AWS IoT Greengrass 资格套件尚不支持并行测试执行。按顺序为每台设备运行资格认证套件。

### 无法启动测试错误
<a name="could-not-start-test"></a>

您可能会遇到错误，这些错误指向测试尝试开始时发生的故障。有几种可能的原因，因此，请执行以下操作：
+ 确保执行命令中的池名称实际存在。IDT 直接从 `device.json` 文件中引用池名称。
+ 确保池中的设备具有正确的配置参数。

### Docker 资格认证镜像存在错误
<a name="docker-qualification-image-exists"></a>

Docker 应用程序管理器资格认证测试使用 Amazon ECR 中的 `amazon/amazon-ec2-metadata-mock` 容器镜像来鉴定被测设备。

如果镜像已存在于被测设备上的 Docker 容器中，则可能会收到以下错误。

```
The Docker image amazon/amazon-ec2-metadata-mock:version already exists on the device.
```

如果您之前下载了此镜像并在设备上运行了 `amazon/amazon-ec2-metadata-mock` 容器，请务必在运行资格认证测试之前从被测设备中移除此镜像。

### 无法读取凭证
<a name="failed-to-read-credential-windows"></a>

在测试 Windows 设备时，如果用于连接被测设备的用户未在该设备的凭证管理器中设置，则可能会在 `greengrass.log` 文件中遇到 `Failed to read credential` 错误。

要解决此错误，请在被测设备的凭证管理器中配置 IDT 用户的用户名和密码。

有关更多信息，请参阅 [为 Windows 设备配置用户凭证](device-config-setup.md#configure-windows-user-for-idt)。

### Greengrass 的 PreInstalled 指导错误
<a name="guice-errors"></a>

在使用 Gre PreInstalled engrass 运行 IDT 时，如果遇到`ErrorInCustomProvider`或的错误`Guice`，请检查文件是否`userdata.json`已`InstalledDirRootOnDevice`设置为 Greengrass 安装文件夹。IDT 检查 `<InstallationDirRootOnDevice>/config/effectiveConfig.yaml` 下的文件 `effectiveConfig.yaml`。

有关更多信息，请参阅 [为 Windows 设备配置用户凭证](device-config-setup.md#configure-windows-user-for-idt)。

### 签名异常无效
<a name="invalid-signature-exception-lambda"></a>

运行 Lambda 资格认证测试时，如果 IDT 主机遇到网络访问问题，则可能会遇到 `invalidsignatureexception` 错误。重置路由器并再次运行测试。

### 机器学习资格认证错误
<a name="machine-learning-qualification-failure"></a>

在运行机器学习 (ML) 资格测试时，如果您的设备不符合部署 AWS提供的机器学习组件的[要求](dlr-component.md#dlr-component-requirements)，则可能会遇到资格认证失败的情况。要排查 ML 资格认证错误，请执行以下操作：
+ 在组件日志中查找测试运行期间部署的组件的错误详细信息。组件日志位于 `<device-tester-extract-location>/results/<execution-id>/logs/<test-group-id>` 目录中。
+ 将 `-Dgg.persist=installed.software` 参数添加到失败测试用例的 `test.json` 文件中。`test.json` 文件位于 `<device-tester-extract-location>/tests/GGV2Q_version directory. ` 中。

### 开放测试框架（OTF）部署失败
<a name="otf-deployment-failure"></a>

如果 OTF 测试未能完成部署，则可能的原因可能是为 `TempResourcesDirOnDevice` 和 `InstallationDirRootOnDevice` 的父文件夹设置了权限。要正确设置此文件夹的权限，请运行以下命令。将 `folder-name` 替换为父文件夹的名称。

```
sudo chmod 755 folder-name
```

### 解析错误
<a name="parse-error"></a>

有时候，JSON 配置中的拼写错误可能会导致解析错误。大部分情况下，问题是因 JSON 文件中漏掉括号、逗号或引号所导致。IDT 执行 JSON 验证并输入调试信息。它输出发生错误的行、行号以及语法错误的列号。这些信息应该足以帮助您修复错误，但是如果您仍然找不到错误，则可以在IDE、Atom或Sublime等文本编辑器中手动进行验证，也可以通过诸如此类的在线工具进行验证。 JSONLint

### 权限被拒绝错误
<a name="permission-denied-pwd-sudo"></a>

IDT 将对被测设备中的各种目录和文件执行操作。其中一些操作需要根用户访问权限。要自动执行这些操作，IDT 必须能够在不键入密码的情况下使用 sudo 运行命令。

请按照以下步骤操作，以允许在不键入密码的情况下进行 sudo 访问。

**注意**  
`user` 和 `username` 是指 IDT 用来访问所测试设备的 SSH 用户。

1. 使用 **sudo usermod -aG sudo *<ssh-username>*** 将 SSH 用户添加到 sudo 组。

1. 注销，然后重新登录，以使更改生效。

1. 打开 `/etc/sudoers` 文件，并将以下行添加到文件末尾：`<ssh-username> ALL=(ALL) NOPASSWD: ALL`
**注意**  
作为最佳实践，我们建议您在编辑 `/etc/sudoers` 时使用 **sudo visudo**。

### 资格认证报告生成错误
<a name="qualification-report-policy-error"></a>

IDT 支持四个最新`major.minor`版本的 AWS IoT Greengrass V2 资格套件 (GGV2Q) 来生成资格报告，您可以提交这些报告 AWS Partner Network 以将您的设备包含在设备目录中 AWS Partner 。早期版本的资格认证套件不生成资格认证报告。

如果您对支持策略有疑问，请联系 [AWS 支持](https://aws.amazon.com/contact-us/)。

### 缺少必需参数错误
<a name="required-param-missing"></a>

当 IDT 添加新功能时，它可能会对配置文件进行更改。使用旧配置文件可能会破坏您的配置。如果出现这种情况，`/results/<execution-id>/logs` 下的 `<test_case_id>.log` 文件明确列出了所有缺少的参数。IDT 还将验证 JSON 配置文件架构，以验证您是否使用最新支持的版本。

### macOS 上的安全例外
<a name="security-exception-macos"></a>

在 macOS 主机上运行 IDT 时，它会阻止 IDT 运行。要运行 IDT，请向可执行文件授予安全异常，这是 IDT 运行时功能的一部分。当主机上显示警告消息时，请对每个适用的可执行文件执行以下操作：

**要向 IDT 可执行文件授予安全异常，请执行以下操作**

1. 在 macOS 电脑上，在苹果菜单中打开**系统偏好设置**。

1. 选择**安全与隐私**，然后在**通用**选项卡上，选择锁定图标以更改安全设置。

1. 如果 `devicetester_mac_x86-64` 受阻，查找消息 `"devicetester_mac_x86-64" was blocked from use because it is not from an identified developer.` 并选择**仍然允许**。

1. 恢复 IDT 测试，直到完成所有涉及的可执行文件。

### SSH 连接错误
<a name="ssh-connect-errors"></a>

当 IDT 无法连接到被测设备时，会在 `/results/<execution-id>/logs/<test-case-id>.log` 中记录连接失败。SSH 消息将显示在此日志文件的顶部，因为连接到被测设备是 IDT 最先执行的操作之一。

大多数 Windows 配置使用 Pu TTy 终端应用程序连接到 Linux 主机。该应用程序要求将标准 PEM 私有密钥文件转换为称为 PPK 的专有 Windows 格式。如果您在 `device.json` 文件中配置 SSH，请使用 PEM 文件。如果您使用 PPK 文件，IDT 将无法与 AWS IoT Greengrass 设备建立 SSH 连接，也无法运行测试。

从 IDT v4.4.0 开始，如果您尚未在被测设备上启用 SFTP，则可能会在日志文件中看到以下错误。

```
SSH connection failed with EOF
```

要解决此错误，请在设备上启用 SFTP。

### 流管理器资格认证错误
<a name="stream-manager-qualification-failure"></a>

运行流管理器资格认证测试时，您可能会在 `com.aws.StreamManagerExport.log` 文件中看到以下错误。

```
Failed to upload data to S3
```

当流管理器使用设备上`~/root/.aws/credentials`文件中的 AWS 凭证而不是使用 IDT 导出到被测设备的环境凭证时，可能会发生此错误。为防止出现此问题，请删除设备上的 `credentials` 文件，然后重新运行资格认证测试。

### 超时错误
<a name="test-timeout"></a>

您可以通过指定超时乘数来增加每个测试的超时，该超时乘数应用于每个测试超时的默认值。为此标志配置的任何值都必须大于或等于 1.0。

要使用超时乘数，请在运行测试时使用标志 `--timeout-multiplier`。例如：

```
./devicetester_linux run-suite --suite-id GGV2Q_1.0.0 --pool-id DevicePool1 --timeout-multiplier 2.5
```

有关更多信息，请运行 `run-suite --help`。

由于配置问题而无法完成 IDT 测试用例时，会出现一些超时错误。您无法通过增加超时乘数来解决这些错误。使用测试运行中的日志对基础配置问题进行故障排除。
+ 如果 MQTT 或 Lambda 组件日志包含 `Access denied` 错误，则 Greengrass 安装文件夹可能没有正确的文件权限。对 `userdata.json` 文件中定义的安装路径中的每个文件夹运行以下命令。

  ```
  sudo chmod 755 folder-name
  ```
+ 如果 Greengrass 日志表明 Greengrass CLI 部署尚未完成，请执行以下操作：
  + 验证 `bash` 是否已安装在被测设备上。
  + 如果 `userdata.json` 文件包含 `GreengrassCliVersion` 配置参数，请将其移除。此参数在 IDT v4.1.0 及更高版本中已弃用。有关更多信息，请参阅 [配置 userdata.json](set-config.md#userdata-config)。
+ 如果 Lambda 部署测试失败并显示错误消息“Validating Lambda publish: time out”，并且在测试日志文件（`idt-gg2-lambda-function-idt-<resource-id>.log`）中收到一条显示 `Error: Could not find or load main class com.amazonaws.greengrass.runtime.LambdaRuntime.` 的错误，请执行以下操作：
  + 验证 `userdata.json` 文件中的 `InstallationDirRootOnDevice` 使用了哪个文件夹。
  + 确保在您的设备上设置了正确的用户权限。有关更多详细信息，请参阅[在设备上配置用户权限](https://docs.aws.amazon.com/greengrass/v2/developerguide/device-config-setup.html#root-access)。

### 版本检查错误
<a name="version-compatibility-check-failure"></a>

当 IDT AWS 用户的用户证书没有所需的 IAM 权限时，IDT 会发出以下错误。

```
Failed to check version compatibility
```

没有所需 IAM 权限的 AWS 用户。

# 适用于 AWS IoT Device Tester 的 AWS IoT Greengrass 的支持策略
<a name="idt-support-policy"></a>

适用于 AWS IoT Greengrass 的 AWS IoT Device Tester 是一个测试自动化工具，用于验证和[认证](https://aws.amazon.com/partners/dqp/)您的 AWS IoT Greengrass 设备是否有资格包括在 [AWS Partner 设备目录](https://devices.amazonaws.com/)中。我们建议您使用最新版本的 AWS IoT Greengrass 和 AWS IoT Device Tester 来测试您的设备或认证其资格。

对于每个受支持的 AWS IoT Greengrass 版本，至少提供一个版本的 AWS IoT Device Tester。有关受支持的 AWS IoT Greengrass 版本，请参阅 [Greengrass Nucleus 版本](greengrass-nucleus-component.md#greengrass-nucleus-component-versions)。有关受支持的 AWS IoT Device Tester 版本，请参阅[支持的 f AWS IoT Device Tester or AWS IoT Greengrass V2 版本](dev-test-versions.md)。

您还可以使用任何受支持的 AWS IoT Greengrass 和 AWS IoT Device Tester 版本来测试您的设备或认定其资格。尽管您可以继续使用不受支持的 AWS IoT Device Tester 版本，但这些版本不会收到错误修复或更新。如果您对支持策略有疑问，请联系 [AWS 支持](https://aws.amazon.com/contact-us/)。