diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..480de9d --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +.PHONY: all gen_go gen_py clean + + +all: gen_go gen_py + +gen_go: + @echo "Generating Go Protobuf code..." + mkdir -p server/gen/pb + protoc --proto_path=proto \ + --go_out=server/gen/pb \ + --go_opt=paths=source_relative \ + --go-temporal_out=server/gen/pb \ + --go-temporal_opt=paths=source_relative \ + proto/*.proto + +gen_py: + @echo "Generating Python Protobuf code..." + mkdir -p worker/gen + python3 -m grpc_tools.protoc \ + --proto_path=proto \ + --python_out=worker/gen \ + --pyi_out=worker/gen \ + proto/*.proto + +clean: + @echo "Cleaning generated files..." + rm -rf server/gen + rm -rf worker/gen \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..5efbec3 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module beacon + +go 1.24.4 diff --git a/proto/common_test.proto b/proto/common_test.proto new file mode 100644 index 0000000..716e997 --- /dev/null +++ b/proto/common_test.proto @@ -0,0 +1,70 @@ +syntax = "proto3"; + +package test_pb; + +option go_package = "Beacon/server/gen/pb"; // 替换 your_module_path +// Python 生成时,会在 proto_gen 目录下直接生成 common_test_pb2.py, +// Python 代码中 import proto_gen.common_test_pb2 即可。 + +// -------- 输入消息 -------- +// 整个测试任务的输入 +message TestRunInput { + string run_id = 1; // 唯一的测试运行ID + string environment_url = 2; // 被测环境URL + repeated string tags = 3; // 测试标签,例如 "smoke", "regression" + bool run_api_tests = 4; + bool run_ui_tests = 5; +} + +// 单个API测试请求的参数 +message ApiTestRequest { + string test_case_id = 1; // API测试用例ID + string endpoint = 2; // API路径 + string http_method = 3; // "GET", "POST", etc. + map headers = 4; + bytes request_body = 5; // JSON或其他二进制数据 + int32 expected_status_code = 6; +} + +// 单个UI测试请求的参数 +message UiTestRequest { + string test_case_id = 1; // UI测试用例ID + string url_path = 2; // 相对于 base_url 的路径 + string browser_type = 3; // "chromium", "firefox", "webkit" + bool headless = 4; // 是否无头模式 + map user_data = 5; // 用户名、密码等敏感信息,不建议直接传输,建议 Worker 端获取 +} + +// -------- 结果消息 -------- +// 通用测试结果字段 +message BaseTestResult { + string test_case_id = 1; + bool success = 2; + string message = 3; // 成功/失败信息 + string log_output = 4; // 详细日志 + double duration_seconds = 5; + string error_details = 6; // 失败时的详细错误堆栈 +} + +// API测试结果 +message ApiTestResult { + BaseTestResult base_result = 1; + int32 actual_status_code = 2; + string response_body = 3; +} + +// UI测试结果 +message UiTestResult { + BaseTestResult base_result = 1; + string screenshot_url = 2; // 截图存储URL (worker上传后返回) + string html_report_url = 3; // HTML报告URL +} + +// 整个测试任务的输出结果 +message TestRunOutput { + string run_id = 1; + bool overall_success = 2; + string completion_message = 3; + repeated ApiTestResult api_results = 4; + repeated UiTestResult ui_results = 5; +} \ No newline at end of file diff --git a/server/activity.go b/server/activity.go new file mode 100644 index 0000000..56ba981 --- /dev/null +++ b/server/activity.go @@ -0,0 +1,3 @@ +package main + +// 定义 Temporal Activity 接口 diff --git a/server/main.go b/server/main.go new file mode 100644 index 0000000..39f4c83 --- /dev/null +++ b/server/main.go @@ -0,0 +1,61 @@ +package main +// Go 服务端入口,触发 Workflow +import ( +"context" +"fmt" +"log" +"time" + +"server/gen/pb" // 替换为你的模块路径 +"server/workflow" + +"github.com/google/uuid" +"go.temporal.io/sdk/client" +) + +func main() { + // 创建 Temporal 客户端 + c, err := client.Dial(client.Options{ + HostPort: client.Default : TemporalClientPort, // 根据你的 Temporal Server 配置 + }) + if err != nil { + log.Fatalf("Unable to create Temporal client: %v", err) + } + defer c.Close() + + // 模拟一个触发测试的事件 (例如来自 Web UI 或 CI/CD) + runID := uuid.New().String() + testInput := &pb.TestRunInput{ + RunId: runID, + EnvironmentUrl: "https://example.com", + Tags: []string{"smoke", "critical"}, + RunApiTests: true, + RunUiTests: true, + } + + workflowOptions := client.StartWorkflowOptions{ + ID: "test_workflow_" + runID, + TaskQueue: "test-task-queue", // 保持与 Python Worker 一致 + } + + fmt.Printf("Starting TestRunWorkflow for run ID: %s\n", runID) + we, err := c.ExecuteWorkflow(context.Background(), workflowOptions, workflow.TestRunWorkflow, testInput) + if err != nil { + log.Fatalf("Unable to execute workflow: %v", err) + } + + fmt.Printf("Workflow started. Workflow ID: %s, Run ID: %s\n", we.GetID(), we.GetRunID()) + + // 等待 Workflow 完成并获取结果 + var result pb.TestRunOutput + err = we.Get(context.Background(), &result) + if err != nil { + log.Fatalf("Unable to get workflow result: %v", err) + } + + fmt.Printf("Workflow finished. Overall Success: %t, Message: %s\n", result.OverallSuccess, result.CompletionMessage) + fmt.Printf("API Test Results: %+v\n", result.ApiResults) + fmt.Printf("UI Test Results: %+v\n", result.UiResults) + + // 后续可以根据 result 生成报告、发送通知等 +} \ No newline at end of file diff --git a/server/workflow.go b/server/workflow.go new file mode 100644 index 0000000..93cbcdc --- /dev/null +++ b/server/workflow.go @@ -0,0 +1,3 @@ +package main + +// 定义 Temporal Workflow diff --git a/worker/activities.py b/worker/activities.py new file mode 100644 index 0000000..c6d435c --- /dev/null +++ b/worker/activities.py @@ -0,0 +1 @@ +# 实现 Temporal Activity 逻辑 \ No newline at end of file diff --git a/worker/api_tests.py b/worker/api_tests.py new file mode 100644 index 0000000..5607c2f --- /dev/null +++ b/worker/api_tests.py @@ -0,0 +1 @@ +# 接口测试具体实现 \ No newline at end of file diff --git a/worker/gen/__init__.py b/worker/gen/__init__.py new file mode 100644 index 0000000..8ab29a8 --- /dev/null +++ b/worker/gen/__init__.py @@ -0,0 +1 @@ +# Protobuf 生成的 Python 代码 \ No newline at end of file diff --git a/worker/main.py b/worker/main.py new file mode 100644 index 0000000..0950274 --- /dev/null +++ b/worker/main.py @@ -0,0 +1 @@ +# Python Worker 入口,注册并运行 Activity \ No newline at end of file diff --git a/worker/requirements.txt b/worker/requirements.txt new file mode 100644 index 0000000..a80f052 --- /dev/null +++ b/worker/requirements.txt @@ -0,0 +1 @@ +# Python 依赖 \ No newline at end of file diff --git a/worker/ui_tests.py b/worker/ui_tests.py new file mode 100644 index 0000000..e206773 --- /dev/null +++ b/worker/ui_tests.py @@ -0,0 +1 @@ +# UI 测试具体实现 (使用 Playwright) \ No newline at end of file diff --git a/worker/utils.py b/worker/utils.py new file mode 100644 index 0000000..01090f0 --- /dev/null +++ b/worker/utils.py @@ -0,0 +1 @@ +# 辅助函数 (例如截图、报告生成) \ No newline at end of file