数据中心/云端

构建 AI 智能体以自动创建软件测试案例

在软件开发中,测试对于确保最终产品的质量和可靠性至关重要。然而,创建测试计划和规范可能耗时且需要大量人力,尤其是在复杂系统中管理多种需求和不同测试类型时。许多此类任务通常由测试工程师手动执行。

为了简化这一过程, NVIDIA 的 DriveOS 团队开发了 Hephaestus(HEPH),这是一个用于自动测试生成的 内部生成式 AI 框架。HEPH 可自动执行各种测试的设计和实施,包括集成测试和单元测试。它使用 大语言模型 (LLMs)进行输入分析和代码生成,显著减少了创建测试用例所花费的时间。通过根据输入文档、代码样本和反馈循环生成上下文感知测试,HEPH 使测试更快、更高效。

本文概述了如何构建智能体框架以生成各种类型的软件测试。该文介绍了如何使用大型语言模型(LLM)智能体确保文档的可溯性,以及如何根据软件要求创建可执行测试。您还可以了解到如何提高智能体的测试生成能力。

用于自动创建测试用例的智能体框架

在软件开发过程中,开发、安全和 QA 团队通常会面临手动创建测试用例的劳动密集型任务。

测试创建过程涉及耗时的步骤,包括检索需求信息、将这些需求追踪到相关文档,以及最终根据匹配的需求和文档生成测试。

为了简化此工作流程,DriveOS 团队设计了 HEPH,这是一种用于实现整个测试流程自动化的自定义内部框架,显著减少了创建测试规范和实现所花费的时间。HEPH 使用大型语言模型(LLMs)分析输入文档和代码示例,生成根据所提供的要求定制的测试。

测试自动化的价值 

HEPH 在测试生成过程的每个步骤(从文档追踪到代码生成)中都使用 LLM 智能体。这实现了整个测试工作流程的自动化,并为工程团队节省了大量时间。

  • 节省时间: HEPH 显著加快了测试创建过程。在 NVIDIA 多个试点团队的试验中,团队报告节省了多达 10 周的开发时间。
  • 上下文感知测试生成: HEPH 使用项目文档和接口规范生成测试规范和实现。每个测试都经过编译、执行和验证,以确保正确性。测试覆盖率数据会反馈回模型,以进一步优化测试生成。
  • 多格式支持和模块化:HEPH 支持各种输入格式,包括 PDF、RST、RSTI 和 HTML,并与内部工具如 Confluence 和 JIRA 集成。

HEPH 的工作原理是什么?

HEPH 接受软件需求、软件架构文档(SWAD)、接口控制文档(ICD)和测试示例作为输入,输出是针对给定需求的一组测试规范和实现(图 1)。

The diagram shows various inputs for analysis that undergo a feedback loop, resulting in relevant outputs for test generation.
图 1.HEPH 技术架构

测试生成流程包括以下主要步骤:

  • 数据准备: 输入文档(如 SWAD 和 ICD)被编入索引并存储在嵌入数据库中,之后用于查询相关信息。
  • 需求提取: 从需求存储系统(例如 Jama )检索需求详细信息。如果输入需求缺乏生成测试所需的详细信息,HEPH 会自动连接到存储服务,定位需求并下载缺失的信息。
  • 数据可追溯性:HEPH 搜索嵌入数据库以追踪与输入需求相关的信息。输出是需求与相关 SWAD 和 ICD 片段之间的映射连接。
  • 测试规范生成: 基于需求的验证步骤以及已识别的 SWAD 和 ICD 片段(可追踪性),HEPH 生成正面和负面的测试规范,以涵盖需求的各个方面。
  • 测试实现生成 :HEPH 使用 ICD 片段(可追溯性)和生成的测试规范来创建 C/C++ 测试。ICD 提供函数名称、数据类型、枚举和返回代码等上下文,供 LLM 在代码生成过程中使用。该步骤生成可执行测试。
  • 测试执行: 编译并执行生成的测试,收集覆盖率数据。HEPH 代理分析测试覆盖率结果,并重复生成缺失案例的测试规范和实施。

真实场景

这是一个了解 HEPH 工作原理的真实示例。

NVIDIA DriveOS 使用 QNX 操作系统。为了演示 HEPH 的功能,我使用了一个 QNX BSP 驱动作为示例,以及对 QNX BSP 中的热功能要求。鉴于输入要求和驱动文档,HEPH 从 Jama 中提取需求信息,将其追溯到相应的文档片段,并生成测试规范和实现。

  • 需求提取
  • SWAD 数据可追踪性
  • ICD 数据追踪
  • 测试规范生成
  • 测试实现生成

需求提取 

HEPH 使用需求标识符从需求存储(Jama)中提取详细信息。生成的需求格式为 JSON:

{
  "requirement_id": "DOSBSP60-REQ-3874",
  "name": "Get Temperature for Thermal Zones in the SOC_THERM Domain",
    "description": "When a request to retrieve the temperature of a thermal zone in the SOC_THERM domain is made via TMON_GUEST_LIF#GetTempSocTherm, QNX_BSP shall retrieve and return two consecutive temperature values for the thermal zone via TEGRA_CTRL_LIF#GetTemp, preserving the temperature resolution, along with two corresponding timestamps via DRIVE_OS::QNX_System::OS_LIBC_LIF#ReadClockCycles."
}

SWAD 数据可追踪性 

HEPH 可搜索所有架构文档(SWAD),以找到与需求相关的信息。输出是架构细节的集合,包括单元要求、方法、错误处理和验证标准。

### Extracted Information for Requirement: DOSBSP60-REQ-3874

#### Unit Requirements and Functional Blocks
- **UREQ_NvThermmon_Library_0601**:
      If the thermal zone bound to **Handle** is in the SOC_THERM domain, Thermal_API#GetTempSocTherm shall retrieve the bound zone ID, pass it to BPMP_Comm_API#GetZoneTemp to get the zone temperature, populate **TempVal1** with the zone temperature, use libc_api#QnxLibcReadClockCycles to populate **Timestamp1**, call BPMP_Comm_API#GetZoneTemp to get the zone temperature again, populate **TempVal2** with the zone temperature, use libc_api#QnxLibcReadClockCycles to populate **Timestamp2**, and return success as per Thermal_API ICD.
   
- **UREQ_NvThermmon_Library_0602**:
      If BPMP_Comm_API#GetZoneTemp fails, Thermal_API#GetTempSocTherm shall return error as per Thermal_API ICD and perform no other action.

#### Methods and Functions
- **Functional Block FUNC_NvThermmon_01**:
  FUNC_NvThermmon_01
      Thermal_API provides the Thermal_API#GetTempSmTmon and Thermal_API#GetTempSocTherm interface to query the temperature of the thermal zone bound to **Handle** and return the result in **zone_temp**.

#### Error Handling
- **UREQ_NvThermmon_Resmgr_1201**:
      If NvThermmon_Resmgr encounters a SW diagnostic error, the NvThermmon_Resmgr returns error as per Thermal_devctl_API ICD for all current and future Thermal_devctl_API requests and performs no other action.

- **UREQ_NvThermmon_Resmgr_1202**:
      If libc_api#QnxLibcIoctl is called on ``/dev/<ZoneName>`` and the command is not Thermal_devctl_API#GetTemp or Thermal_devctl_API#SetAlert, NvThermmon_Resmgr shall return error as per Thermal_devctl_API ICD.

#### Verification Criteria (Verification Environment: AV+Q Safety prod-debug)
Verification Environment: AV+Q Safety prod-debug
Pre-Condition: N/A
Constraints: N/A
Verification Steps:
- Run interface tests on API
- Pass invalid thermal zones and verify the API fails
- Pass valid thermal zones from a process with required privileges and permissions and verify that the temperature can be read.
- Inject error such that I2C_API#SendReceive returns error and verify that Thermal_API#GetTempSmTmon fails as expected.
- Inject error such that BPMP_Comm_API#GetZoneTemp returns error and verify that Thermal_API#GetTempSocTherm fails as expected.

ICD 数据追踪 

搜索 SWADs 后,HEPH 会在 ICDs 中查找信息。结果包括方法、函数、数据结构、错误代码和函数依赖项的详细信息。

### Extracted Information from ICDs

#### Methods and Functions:

1. **NvThermmonOpen**
    **Description**: Opens a connection to the nvthermmon driver for the thermal sensor/zone user is interested in.

    **Parameters**:
    - `const char *const ZoneName`: Thermal sensor/zone name
    - `NvThermmonHandle *const Handle`: User handle for further API calls

    **Returns**:
    - `NV_THERMMON_ERR_CODE_NO_ERROR`: Success
    - `NV_THERMMON_ERR_CODE_INVALID_PARAM`: Invalid parameters
    - `NV_THERMMON_ERR_CODE_DT_FAILED`: Device tree failure
    - `NV_THERMMON_ERR_CODE_INVALID_PERM`: Permission error
    - `NV_THERMMON_ERR_CODE_INVALID_STATE`: Invalid system state
    - `NV_THERMMON_ERR_CODE_ERROR`: BPMP Comm error

    **Precondition**: None

    **Usage Considerations**:
    - Allowed context for the API call
    - Sync, not re-entrant
2. **NvThermmonGetZoneTemp**
    **Description**: Read temperature from selected thermal zone. Populates memory pointed to by `temp` with temperature of thermal zone in millidegrees Celsius and returns status.

    **Parameters**:
    - `const NvThermmonHandle Handle`: Handle for execution context bound in `NvThermmonOpen`
    - `int32_t * const TempVal`: Pointer to save temperature value in millidegrees Celsius.

    **Returns**:
    - `NvThermmonErrCode`: Error Code (e.g., `NV_THERMMON_ERR_CODE_NO_ERROR`, `NV_THERMMON_ERR_CODE_INVALID_PARAM`)

#### Data Structures and Fields:

1. **zone_temp_t Structure**
    **Fields**:
    - `int32_t temp_1`: First temperature reading
    - `int32_t temp_2`: Second temperature reading
    - `uint64_t ts_1`: Timestamp for first temp reading
    - `uint64_t ts_2`: Timestamp for second temp reading

#### Enumerations:
1. **NvThermmonErrCode**

    **Error Codes**:
    - `NV_THERMMON_ERR_CODE_NO_ERROR`
    - `NV_THERMMON_ERR_CODE_INVALID_PARAM`
    - `NV_THERMMON_ERR_CODE_DT_FAILED`
    - `NV_THERMMON_ERR_CODE_INVALID_PERM`
    - `NV_THERMMON_ERR_CODE_INVALID_STATE`
    - `NV_THERMMON_ERR_CODE_ERROR`

### Integration of Information for Testing:

1. **NvThermmonOpen()**:
    **Precondition**: Ensure that `NvThermmonOpen` returns success for the thermal zone.
    **Dependencies**:
    - Handle for execution context

2. **NvThermmonGetZoneTemp()**:
    **Dependencies**:
    - `zone_temp_t` structure to store temperature readings and timestamps.
    - Error codes to handle different edge cases and validation steps.

测试规范生成 

根据需求中的验证步骤以及追踪的 SWAD 和 ICD 片段,HEPH 生成测试规范。以下代码块是生成的测试用例示例。

######
Test Case ID: TC_DOSBSP60-REQ-3874_001
Test Case Name: Verify successful temperature query for a supported thermal zone
Test Type: Positive
Test Design: Ensure the temperature for a thermal zone in the SOC_THERM domain can be queried successfully.
Pre-condition: Thermal zone is supported and NvThermmonOpen() returns success for the thermal zone.
Test Procedure:
1. Open a connection to the thermal zone using NvThermmonOpen().
2. Query the temperature for the thermal zone using NvThermmonGetZoneTemp().
3. Retrieve two consecutive temperature values.
Expected Result: The API should return success with two temperature values that differ by no more than the delta determined by the thermal characteristics of the board.

######
Test Case ID: TC_DOSBSP60-REQ-3874_002
Test Case Name: Verify accompanying timestamp for temperature queries
Test Type: Positive
Test Design: Ensure that two timestamp values are returned with temperature queries.
Pre-condition: Thermal zone is supported and NvThermmonOpen() returns success for the thermal zone.
Test Procedure:
1. Open a connection to the thermal zone using NvThermmonOpen().
2. Query the temperature for the thermal zone using NvThermmonGetZoneTemp().
3. Retrieve two consecutive temperature values along with two corresponding timestamps.
Expected Result: The API should return success with two timestamp values that do not exceed T microseconds between them.

######
Test Case ID: TC_DOSBSP60-REQ-3874_003
Test Case Name: Verify temperature variation over successive calls
Test Type: Positive
Test Design: Ensure that the temperature for the thermal zone varies over successive queries.
Pre-condition: Thermal zone is supported and NvThermmonOpen() returns success for the thermal zone.
Test Procedure:
1. Open a connection to the thermal zone using NvThermmonOpen().
2. Query the temperature for the thermal zone using NvThermmonGetZoneTemp() multiple times.
3. Compare temperature values over successive calls.
Expected Result: The temperature values should show a difference of >0 and should vary with the resolution supported by the temperature sensor.

测试实现生成 

基于测试规范和 ICD 详细信息,HEPH 以 C 生成测试。

#include <stdio.h>
#include <stdint.h>
#include "NvThermmonAPI.h"

// Test Case TC_DOSBSP60-REQ-3874_001
// Verify successful temperature query for a supported thermal zone
void TC_DOSBSP60_REQ_3874_001(void) {
    NvThermmonHandle handle;
    zone_temp_t zoneTemp;

    // Step 1: Open a connection to the thermal zone using NvThermmonOpen()
    NvThermmonErrCode status = NvThermmonOpen("CPU-therm", &handle);
    if (status != NV_THERMMON_ERR_CODE_NO_ERROR) {
        printf("TC_DOSBSP60-REQ-3874_001: NvThermmonOpen failed\n");
        return;
    }

    // Step 2: Query the temperature for the thermal zone using NvThermmonGetZoneTemp()
    status = NvThermmonGetZoneTemp(handle, &zoneTemp);
    if (status != NV_THERMMON_ERR_CODE_NO_ERROR) {
        printf("TC_DOSBSP60-REQ-3874_001: NvThermmonGetZoneTemp failed\n");
        return;
    }

    // Step 3: Retrieve two consecutive temperature values
    int32_t delta = zoneTemp.temp_2 - zoneTemp.temp_1;
    if (delta > 100) { // Assume 100 is the delta determined by the thermal characteristics of the board
        printf("TC_DOSBSP60-REQ-3874_001: Temperature delta is too large\n");
    } else {
        printf("TC_DOSBSP60-REQ-3874_001: Passed\n");
    }
}

// Test Case TC_DOSBSP60-REQ-3874_002
// Verify accompanying timestamp for temperature queries
void TC_DOSBSP60_REQ_3874_002(void) {
    NvThermmonHandle handle;
    zone_temp_t zoneTemp;

    // Step 1: Open a connection to the thermal zone using NvThermmonOpen()
    NvThermmonErrCode status = NvThermmonOpen("CPU-therm", &handle);
    if (status != NV_THERMMON_ERR_CODE_NO_ERROR) {
        printf("TC_DOSBSP60-REQ-3874_002: NvThermmonOpen failed\n");
        return;
    }

    // Step 2: Query the temperature for the thermal zone using NvThermmonGetZoneTemp()
    status = NvThermmonGetZoneTemp(handle, &zoneTemp);
    if (status != NV_THERMMON_ERR_CODE_NO_ERROR) {
        printf("TC_DOSBSP60-REQ-3874_002: NvThermmonGetZoneTemp failed\n");
        return;
    }

    // Step 3: Retrieve two consecutive temperature values along with two corresponding timestamps
    uint64_t deltaTs = zoneTemp.ts_2 - zoneTemp.ts_1;
    if (deltaTs > 1000) { // Assume 1000 microseconds is the maximum allowed delta
        printf("TC_DOSBSP60-REQ-3874_002: Timestamp delta is too large\n");
    } else {
        printf("TC_DOSBSP60-REQ-3874_002: Passed\n");
    }
}

// Test Case TC_DOSBSP60-REQ-3874_003
// Verify temperature variation over successive calls
void TC_DOSBSP60_REQ_3874_003(void) {
    NvThermmonHandle handle;
    zone_temp_t zoneTemp1, zoneTemp2;

    // Step 1: Open a connection to the thermal zone using NvThermmonOpen()
    NvThermmonErrCode status = NvThermmonOpen("CPU-therm", &handle);
    if (status != NV_THERMMON_ERR_CODE_NO_ERROR) {
        printf("TC_DOSBSP60-REQ-3874_003: NvThermmonOpen failed\n");
        return;
    }

    // Step 2: Query the temperature for the thermal zone using NvThermmonGetZoneTemp() multiple times
    status = NvThermmonGetZoneTemp(handle, &zoneTemp1);
    if (status != NV_THERMMON_ERR_CODE_NO_ERROR) {
        printf("TC_DOSBSP60-REQ-3874_003: NvThermmonGetZoneTemp (1st call) failed\n");
        return;
    }

    status = NvThermmonGetZoneTemp(handle, &zoneTemp2);
    if (status != NV_THERMMON_ERR_CODE_NO_ERROR) {
        printf("TC_DOSBSP60-REQ-3874_003: NvThermmonGetZoneTemp (2nd call) failed\n");
        return;
    }

    // Step 3: Compare temperature values over successive calls
    int32_t temperatureDifference = zoneTemp2.temp_1 - zoneTemp1.temp_1;
    if (temperatureDifference <= 0) {
        printf("TC_DOSBSP60-REQ-3874_003: Temperature did not vary as expected\n");
    } else {
        printf("TC_DOSBSP60-REQ-3874_003: Passed\n");
    }
}

未来增强功能 

在设计测试生成框架时,需要关注以下几个核心问题:

  • 支持不同的测试工作流程
  • 集成实时人类反馈

支持不同的测试工作流程 

HEPH 旨在支持软件团队的大多数测试生成用例。然而,在某些情况下,团队需要自定义测试框架或不受支持的测试创建工作流程。

为了应对这些挑战,HEPH 的未来潜在改进可能包括模块化设计,使软件团队能够为非标准工作流程定义自定义模块。例如,团队可能会受益于直接从输入代码(而不是文档)或扩展 LLM 提示生成测试的能力。这种模块化方法有助于解决自定义和非标准测试生成场景的复杂性。

集成实时人类反馈 

虽然最新的 LLMs 在理解开发环境和生成高质量代码方面表现良好,但在某些情况下,生成的测试集可能需要改进。

HEPH 未来可能的增强功能包括在当前的自动模式下引入交互模式。在此交互模式下,您将在测试生成过程的每个步骤中与 HEPH 代理进行交互,在继续之前审查结果、提供反馈并优化输出。例如,如果生成的测试规范缺乏有关寄存器映射的详细信息,您可以添加此上下文,HEPH 将重新生成更准确的测试规范。

开始使用 HEPHing 生成自动测试 

Hephaestus (HEPH) 利用大型语言模型 (LLMs) 自动生成全面且上下文感知的测试,从而实现软件开发中的测试自动化。这种自动化可以减少人工工作量、加速开发并提高最终产品的质量和可靠性。

即将推出的增强功能包括模块化,允许自定义模块支持非标准测试工作流程,以及交互模式,允许您提供反馈并优化测试生成流程,以提高准确性和相关性。

构建您的 AI 智能体应用 

有关使用 NVIDIA 生成式 AI 技术和工具创建您自己的 AI 代理和应用的更多信息,请参阅 ai.nvidia.com 或试用 NVIDIA NIM APIs

如果您不熟悉此领域,请探索我们的初学者友好型系列: 构建您的首个大型语言模型智能体应用

致谢 

感谢 DriveOS QNX BSP 团队试用 HEPH

 

 

标签