package workflows // workflows 包定义了 Temporal 工作流的实现 import ( "beacon/pkg/pb" "fmt" "go.temporal.io/sdk/temporal" "go.temporal.io/sdk/workflow" "time" ) // 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"}, // 自定义不可重试的错误类型 }, }) // 初始化变量用于存储测试结果和状态 var ( apiResults []*pb.ApiTestResult // 存储所有 API 测试的结果 uiResults []*pb.UiTestResult // 存储所有 UI 测试的结果 overallSuccess = true // 整体测试是否成功的标志 completionMessage = "Test run completed successfully." // 完成时的状态消息 ) // 条件执行 API 测试 Activity // 只有当输入配置中指定需要运行 API 测试时才执行 if input.RunApiTests { // 构造 API 测试的请求参数 // 这里使用硬编码的示例数据,实际应用中应该从配置或输入中获取 apiTestInput := &pb.ApiTestRequest{ 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) // 标记整体测试为失败,但继续执行后续测试 overallSuccess = false // 设置测试结果的失败状态和错误信息 apiRes.BaseResult.Success = false apiRes.BaseResult.Message = fmt.Sprintf("API Test Failed: %v", err) } // 将 API 测试结果添加到结果集合中 apiResults = append(apiResults, &apiRes) } // 条件执行 UI 测试 Activity // 只有当输入配置中指定需要运行 UI 测试时才执行 if input.RunUiTests { // 构造 UI 测试的请求参数 // 包含浏览器配置和测试页面信息 uiTestInput := &pb.UiTestRequest{ 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, // 所有 API 测试结果 UiResults: uiResults, // 所有 UI 测试结果 }, nil }