diff --git a/workflows/workflow.go b/workflows/workflow.go index d1dc9d3..d414aa9 100644 --- a/workflows/workflow.go +++ b/workflows/workflow.go @@ -1,6 +1,6 @@ package workflows -// 定义 Temporal Workflow +// workflows 包定义了 Temporal 工作流的实现 import ( "beacon/pkg/pb" "fmt" @@ -10,80 +10,118 @@ import ( ) // TestRunWorkflow 定义了整个测试执行的工作流 +// 该工作流负责协调和执行 API 测试和 UI 测试的整个流程 +// 参数: +// - ctx: Temporal 工作流上下文,用于控制工作流的执行 +// - input: 测试运行的输入参数,包含运行配置和标识 +// +// 返回值: +// - *pb.TestRunOutput: 测试运行的结果输出 +// - error: 执行过程中的错误信息 func TestRunWorkflow(ctx workflow.Context, input *pb.TestRunInput) (*pb.TestRunOutput, error) { + // 获取工作流日志记录器,用于记录执行过程中的关键信息 logger := workflow.GetLogger(ctx) logger.Info("TestRunWorkflow started", "runID", input.RunId) + // 配置 Activity 的执行选项,包括超时时间和重试策略 ctx = workflow.WithActivityOptions(ctx, workflow.ActivityOptions{ - StartToCloseTimeout: 10 * time.Minute, // Activity 执行超时时间 - HeartbeatTimeout: 30 * time.Second, // Heartbeat 防止 Worker 假死 - RetryPolicy: &temporal.RetryPolicy{ // Activity 级别的重试策略 - InitialInterval: time.Second, - BackoffCoefficient: 2.0, - MaximumInterval: time.Minute, - MaximumAttempts: 3, - NonRetryableErrorTypes: []string{"NonRetryableErrorType"}, // 自定义不可重试的错误 + StartToCloseTimeout: 10 * time.Minute, // Activity 从开始到完成的最大允许时间 + HeartbeatTimeout: 30 * time.Second, // Heartbeat 超时时间,防止 Worker 假死 + RetryPolicy: &temporal.RetryPolicy{ // Activity 级别的重试策略配置 + InitialInterval: time.Second, // 首次重试前的等待时间 + BackoffCoefficient: 2.0, // 重试间隔的递增系数 + MaximumInterval: time.Minute, // 重试间隔的最大值 + MaximumAttempts: 3, // 最大重试次数 + NonRetryableErrorTypes: []string{"NonRetryableErrorType"}, // 自定义不可重试的错误类型 }, }) + // 初始化变量用于存储测试结果和状态 var ( - apiResults []*pb.ApiTestResult - uiResults []*pb.UiTestResult - overallSuccess = true - completionMessage = "Test run completed successfully." + apiResults []*pb.ApiTestResult // 存储所有 API 测试的结果 + uiResults []*pb.UiTestResult // 存储所有 UI 测试的结果 + overallSuccess = true // 整体测试是否成功的标志 + completionMessage = "Test run completed successfully." // 完成时的状态消息 ) - // 执行 API 测试 Activity + // 条件执行 API 测试 Activity + // 只有当输入配置中指定需要运行 API 测试时才执行 if input.RunApiTests { + // 构造 API 测试的请求参数 + // 这里使用硬编码的示例数据,实际应用中应该从配置或输入中获取 apiTestInput := &pb.ApiTestRequest{ - TestCaseId: "api-example-1", - Endpoint: "/api/v1/data", - HttpMethod: "GET", - Headers: map[string]string{"Authorization": "Bearer token123"}, - ExpectedStatusCode: 200, + TestCaseId: "api-example-1", // 测试用例唯一标识 + Endpoint: "/api/v1/data", // 要测试的 API 端点 + HttpMethod: "GET", // HTTP 请求方法 + Headers: map[string]string{"Authorization": "Bearer token123"}, // 请求头信息 + ExpectedStatusCode: 200, // 预期的 HTTP 状态码 } + + // 声明变量用于接收 API 测试的结果 var apiRes pb.ApiTestResult + + // 执行 API 测试 Activity 并等待结果 + // "run_api_test" 是注册的 Activity 名称 err := workflow.ExecuteActivity(ctx, "run_api_test", apiTestInput).Get(ctx, &apiRes) if err != nil { + // API 测试执行失败时的错误处理 logger.Error("API test activity failed", "error", err) - // 可以选择标记为失败,或者继续执行UI测试 + // 标记整体测试为失败,但继续执行后续测试 overallSuccess = false + // 设置测试结果的失败状态和错误信息 apiRes.BaseResult.Success = false apiRes.BaseResult.Message = fmt.Sprintf("API Test Failed: %v", err) } + // 将 API 测试结果添加到结果集合中 apiResults = append(apiResults, &apiRes) } - // 执行 UI 测试 Activity + // 条件执行 UI 测试 Activity + // 只有当输入配置中指定需要运行 UI 测试时才执行 if input.RunUiTests { + // 构造 UI 测试的请求参数 + // 包含浏览器配置和测试页面信息 uiTestInput := &pb.UiTestRequest{ - TestCaseId: "ui-example-1", - UrlPath: "/dashboard", - BrowserType: "chromium", - Headless: true, - UserData: map[string]string{"user": "test", "pass": "password"}, + TestCaseId: "ui-example-1", // UI 测试用例标识 + UrlPath: "/dashboard", // 要测试的页面路径 + BrowserType: "chromium", // 使用的浏览器类型 + Headless: true, // 是否使用无头模式运行浏览器 + UserData: map[string]string{"user": "test", "pass": "password"}, // 测试用的用户数据 } + + // 声明变量用于接收 UI 测试的结果 var uiRes pb.UiTestResult + + // 执行 UI 测试 Activity 并等待结果 + // "run_ui_test" 是注册的 Activity 名称 err := workflow.ExecuteActivity(ctx, "run_ui_test", uiTestInput).Get(ctx, &uiRes) if err != nil { + // UI 测试执行失败时的错误处理 logger.Error("UI test activity failed", "error", err) + // 标记整体测试为失败 overallSuccess = false + // 设置测试结果的失败状态和错误信息 uiRes.BaseResult.Success = false uiRes.BaseResult.Message = fmt.Sprintf("UI Test Failed: %v", err) } + // 将 UI 测试结果添加到结果集合中 uiResults = append(uiResults, &uiRes) } + // 根据整体测试结果更新完成消息 if !overallSuccess { completionMessage = "Test run completed with failures." } + // 记录工作流完成的日志信息 logger.Info("TestRunWorkflow completed", "overallSuccess", overallSuccess) + + // 构造并返回测试运行的完整结果 return &pb.TestRunOutput{ - RunId: input.RunId, - OverallSuccess: overallSuccess, - CompletionMessage: completionMessage, - ApiResults: apiResults, - UiResults: uiResults, + RunId: input.RunId, // 测试运行的唯一标识 + OverallSuccess: overallSuccess, // 整体测试是否成功 + CompletionMessage: completionMessage, // 完成状态消息 + ApiResults: apiResults, // 所有 API 测试结果 + UiResults: uiResults, // 所有 UI 测试结果 }, nil }