优化API测试参数处理,增加调试信息,更新复合案例和API测试参数结构
This commit is contained in:
parent
a2e209e530
commit
7c68cd9952
@ -42,6 +42,8 @@ func LoadCompositeCaseSteps(ctx context.Context, compositeCaseId string) ([]*pb.
|
||||
// 转换数据库模型为 Protobuf 结构
|
||||
var pbSteps []*pb.CompositeCaseStepDefinition
|
||||
for _, step := range steps {
|
||||
fmt.Printf("DEBUG: Processing step ID: %d, Type: %s, ApiTestParameters: %v\n",
|
||||
step.ID, step.StepType, step.ApiTestParameters != nil)
|
||||
// 序列化参数为JSON
|
||||
parametersJson, err := serializeStepParameters(step)
|
||||
if err != nil {
|
||||
@ -89,13 +91,19 @@ func serializeStepParameters(step models.CompositeCaseStep) (string, error) {
|
||||
switch step.StepType {
|
||||
case "API_TEST":
|
||||
if step.ApiTestParameters != nil {
|
||||
// 转换API参数
|
||||
// Debug: 打印API参数信息
|
||||
fmt.Printf("DEBUG: API Parameters - Endpoint: '%s', Method: '%s', Body: '%s'\n",
|
||||
step.ApiTestParameters.Endpoint,
|
||||
step.ApiTestParameters.HttpMethod,
|
||||
step.ApiTestParameters.Body)
|
||||
|
||||
// 转换API参数 - 只包含protobuf定义的字段
|
||||
apiParams := map[string]interface{}{
|
||||
"endpoint": step.ApiTestParameters.Endpoint,
|
||||
"method": step.ApiTestParameters.HttpMethod,
|
||||
"body": step.ApiTestParameters.Body,
|
||||
"timeout": step.ApiTestParameters.Timeout,
|
||||
"retry_count": step.ApiTestParameters.RetryCount,
|
||||
"test_case_id": fmt.Sprintf("step_%d", step.ID),
|
||||
"endpoint": step.ApiTestParameters.Endpoint,
|
||||
"http_method": step.ApiTestParameters.HttpMethod,
|
||||
"request_body": step.ApiTestParameters.Body,
|
||||
"expected_status_code": 200, // 默认期望200状态码
|
||||
}
|
||||
|
||||
// 解析headers和query_params JSON字符串
|
||||
@ -114,6 +122,7 @@ func serializeStepParameters(step models.CompositeCaseStep) (string, error) {
|
||||
|
||||
params = apiParams
|
||||
} else {
|
||||
fmt.Printf("DEBUG: step.ApiTestParameters is nil for step ID: %d\n", step.ID)
|
||||
params = map[string]interface{}{}
|
||||
}
|
||||
|
||||
|
@ -7,13 +7,18 @@ import (
|
||||
|
||||
// CompositeCase 复合案例定义
|
||||
type CompositeCase struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
Name string `json:"name" gorm:"not null;size:255"`
|
||||
Description string `json:"description" gorm:"type:text"`
|
||||
Status string `json:"status" gorm:"default:'active';size:50"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
CreatedBy string `json:"created_by" gorm:"size:64;default:''"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
UpdatedBy string `json:"updated_by" gorm:"size:64;default:''"`
|
||||
Version int16 `json:"version" gorm:"default:0"`
|
||||
IsDel int8 `json:"is_del" gorm:"default:0"`
|
||||
ExtJson string `json:"ext_json" gorm:"size:2048;default:''"`
|
||||
Name string `json:"name" gorm:"not null;size:255"`
|
||||
Description string `json:"description" gorm:"type:text"`
|
||||
Status string `json:"status" gorm:"default:'active';size:50"`
|
||||
DeletedAt *time.Time `json:"deleted_at"`
|
||||
|
||||
// 关联的步骤
|
||||
Steps []CompositeCaseStep `json:"steps" gorm:"foreignKey:CompositeCaseID"`
|
||||
@ -22,6 +27,13 @@ type CompositeCase struct {
|
||||
// ApiTestParameters API测试参数
|
||||
type ApiTestParameters struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
CreatedBy string `json:"created_by" gorm:"size:64;default:''"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
UpdatedBy string `json:"updated_by" gorm:"size:64;default:''"`
|
||||
Version int16 `json:"version" gorm:"default:0"`
|
||||
IsDel int8 `json:"is_del" gorm:"default:0"`
|
||||
ExtJson string `json:"ext_json" gorm:"size:2048;default:''"`
|
||||
StepID uint `json:"step_id" gorm:"not null"`
|
||||
Endpoint string `json:"endpoint" gorm:"not null;size:512"`
|
||||
HttpMethod string `json:"http_method" gorm:"not null;size:10;default:'GET'"`
|
||||
@ -30,8 +42,6 @@ type ApiTestParameters struct {
|
||||
Body string `json:"body" gorm:"type:text"`
|
||||
Timeout int `json:"timeout" gorm:"default:30"`
|
||||
RetryCount int `json:"retry_count" gorm:"default:0"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// BeforeCreate GORM hook to ensure JSON fields are never empty
|
||||
@ -59,6 +69,13 @@ func (params *ApiTestParameters) BeforeUpdate(tx *gorm.DB) error {
|
||||
// UiTestParameters UI测试参数
|
||||
type UiTestParameters struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
CreatedBy string `json:"created_by" gorm:"size:64;default:''"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
UpdatedBy string `json:"updated_by" gorm:"size:64;default:''"`
|
||||
Version int16 `json:"version" gorm:"default:0"`
|
||||
IsDel int8 `json:"is_del" gorm:"default:0"`
|
||||
ExtJson string `json:"ext_json" gorm:"size:2048;default:''"`
|
||||
StepID uint `json:"step_id" gorm:"not null"`
|
||||
Selector string `json:"selector" gorm:"not null;size:512"`
|
||||
SelectorType string `json:"selector_type" gorm:"default:'css';size:20"`
|
||||
@ -70,8 +87,6 @@ type UiTestParameters struct {
|
||||
ScreenshotName string `json:"screenshot_name" gorm:"size:255"`
|
||||
AssertionType string `json:"assertion_type" gorm:"size:50"`
|
||||
AssertionValue string `json:"assertion_value" gorm:"type:text"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// ApiTestParametersRequest API测试参数请求
|
||||
@ -102,18 +117,23 @@ type UiTestParametersRequest struct {
|
||||
// CompositeCaseStep 复合案例步骤
|
||||
type CompositeCaseStep struct {
|
||||
ID uint `json:"id" gorm:"primaryKey"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
CreatedBy string `json:"created_by" gorm:"size:64;default:''"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
UpdatedBy string `json:"updated_by" gorm:"size:64;default:''"`
|
||||
Version int16 `json:"version" gorm:"default:0"`
|
||||
IsDel int8 `json:"is_del" gorm:"default:0"`
|
||||
ExtJson string `json:"ext_json" gorm:"size:2048;default:''"`
|
||||
CompositeCaseID uint `json:"composite_case_id" gorm:"not null"`
|
||||
StepName string `json:"step_name" gorm:"not null;size:128"`
|
||||
StepOrder int `json:"step_order" gorm:"not null"`
|
||||
StepName string `json:"step_name" gorm:"not null;size:255"`
|
||||
StepDescription string `json:"step_description" gorm:"type:text"`
|
||||
StepType string `json:"step_type" gorm:"not null;size:100"`
|
||||
ActivityName string `json:"activity_name" gorm:"not null;size:255"`
|
||||
StepType string `json:"step_type" gorm:"not null;size:64"`
|
||||
ActivityName string `json:"activity_name" gorm:"not null;size:128"`
|
||||
IsRequired bool `json:"is_required" gorm:"default:true"`
|
||||
StepDescription string `json:"step_description" gorm:"type:text"`
|
||||
SuccessNextStepOrder *int `json:"success_next_step_order" gorm:"column:success_next_step_order"`
|
||||
FailureNextStepOrder *int `json:"failure_next_step_order" gorm:"column:failure_next_step_order"`
|
||||
RunCondition string `json:"run_condition" gorm:"type:json"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
// 关联的参数表
|
||||
ApiTestParameters *ApiTestParameters `json:"api_test_parameters,omitempty" gorm:"foreignKey:StepID"`
|
||||
|
@ -26,9 +26,13 @@ func CreateCompositeCase(tx *gorm.DB, compositeCase *models.CompositeCase) error
|
||||
func GetCompositeCaseByID(id uint) (*models.CompositeCase, error) {
|
||||
var compositeCase models.CompositeCase
|
||||
|
||||
err := DB.Preload("Steps.ApiTestParameters").Preload("Steps.UiTestParameters").Preload("Steps", func(db *gorm.DB) *gorm.DB {
|
||||
return db.Order("step_order ASC")
|
||||
}).First(&compositeCase, id).Error
|
||||
err := DB.Preload("Steps.ApiTestParameters", "is_del = 0").
|
||||
Preload("Steps.UiTestParameters", "is_del = 0").
|
||||
Preload("Steps", func(db *gorm.DB) *gorm.DB {
|
||||
return db.Where("is_del = 0").Order("step_order ASC")
|
||||
}).
|
||||
Where("is_del = 0").
|
||||
First(&compositeCase, id).Error
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
@ -67,7 +71,7 @@ func ListCompositeCases(page, pageSize int, status string) ([]models.CompositeCa
|
||||
var compositeCases []models.CompositeCase
|
||||
var total int64
|
||||
|
||||
query := DB.Model(&models.CompositeCase{})
|
||||
query := DB.Model(&models.CompositeCase{}).Where("is_del = 0")
|
||||
|
||||
if status != "" {
|
||||
query = query.Where("status = ?", status)
|
||||
@ -80,9 +84,12 @@ func ListCompositeCases(page, pageSize int, status string) ([]models.CompositeCa
|
||||
|
||||
// 分页查询
|
||||
offset := (page - 1) * pageSize
|
||||
err := query.Preload("Steps.ApiTestParameters").Preload("Steps.UiTestParameters").Preload("Steps", func(db *gorm.DB) *gorm.DB {
|
||||
return db.Order("step_order ASC")
|
||||
}).Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&compositeCases).Error
|
||||
err := query.Preload("Steps.ApiTestParameters", "is_del = 0").
|
||||
Preload("Steps.UiTestParameters", "is_del = 0").
|
||||
Preload("Steps", func(db *gorm.DB) *gorm.DB {
|
||||
return db.Where("is_del = 0").Order("step_order ASC")
|
||||
}).
|
||||
Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&compositeCases).Error
|
||||
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("获取复合案例列表失败: %w", err)
|
||||
@ -98,7 +105,7 @@ func ExistsCompositeCase(tx *gorm.DB, id uint) (*models.CompositeCase, error) {
|
||||
}
|
||||
|
||||
var compositeCase models.CompositeCase
|
||||
err := tx.First(&compositeCase, id).Error
|
||||
err := tx.Where("is_del = 0").First(&compositeCase, id).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, fmt.Errorf("复合案例不存在")
|
||||
@ -132,7 +139,10 @@ func GetCompositeCaseSteps(compositeCaseId string) ([]models.CompositeCaseStep,
|
||||
return nil, fmt.Errorf("invalid composite case id: %w", err)
|
||||
}
|
||||
|
||||
err = DB.Preload("ApiTestParameters").Preload("UiTestParameters").Where("composite_case_id = ?", uint(id)).
|
||||
// 查询步骤时,预加载参数表并过滤未删除的记录
|
||||
err = DB.Preload("ApiTestParameters", "is_del = 0").
|
||||
Preload("UiTestParameters", "is_del = 0").
|
||||
Where("composite_case_id = ? AND is_del = 0", uint(id)).
|
||||
Order("step_order ASC").
|
||||
Find(&steps).Error
|
||||
|
||||
|
@ -3,6 +3,7 @@ package workflows
|
||||
import (
|
||||
"encoding/json"
|
||||
"go.temporal.io/sdk/temporal"
|
||||
"go.uber.org/zap"
|
||||
"sort"
|
||||
"strconv"
|
||||
"time"
|
||||
@ -109,6 +110,7 @@ func DynamicTestSuiteWorkflow(ctx workflow.Context, input *pb.DynamicTestRunInpu
|
||||
var activityInput interface{} // 存储特定 Activity 的输入参数(类型由 activity_name 决定)
|
||||
var activityResult interface{} // 存储特定 Activity 的输出结果(类型由 activity_name 决定)
|
||||
|
||||
zap.L().Debug("ParametersJson", zap.Any("ParametersJson", step.ParametersJson))
|
||||
// 使用参数处理器解析参数模板,替换其中的变量引用
|
||||
processedParametersJson, err := parameterProcessor.ProcessTemplate(step.ParametersJson)
|
||||
if err != nil {
|
||||
@ -116,6 +118,7 @@ func DynamicTestSuiteWorkflow(ctx workflow.Context, input *pb.DynamicTestRunInpu
|
||||
overallSuccess = false
|
||||
break
|
||||
}
|
||||
zap.L().Debug("parameterProcessor.ProcessTemplate", zap.Any("processedParametersJson", processedParametersJson))
|
||||
|
||||
// 验证模板中的变量引用是否有效
|
||||
if isValid, errors := parameterProcessor.ValidateTemplate(step.ParametersJson); !isValid {
|
||||
@ -131,11 +134,13 @@ func DynamicTestSuiteWorkflow(ctx workflow.Context, input *pb.DynamicTestRunInpu
|
||||
apiReq := &pb.ApiTestRequest{}
|
||||
// 1. 首先验证JSON格式
|
||||
if !json.Valid([]byte(processedParametersJson)) {
|
||||
logger.Error("Invalid JSON format in parameters")
|
||||
logger.Error("Invalid JSON format in parameters", "json", processedParametersJson)
|
||||
overallSuccess = false
|
||||
break
|
||||
}
|
||||
|
||||
logger.Info("Processing API test parameters", "json", processedParametersJson)
|
||||
|
||||
// 2. 解析JSON时增加错误详情
|
||||
if err := json.Unmarshal([]byte(processedParametersJson), apiReq); err != nil {
|
||||
logger.Error("Failed to unmarshal API test parameters",
|
||||
@ -145,9 +150,13 @@ func DynamicTestSuiteWorkflow(ctx workflow.Context, input *pb.DynamicTestRunInpu
|
||||
break
|
||||
}
|
||||
|
||||
logger.Info("Parsed API request", "endpoint", apiReq.Endpoint, "method", apiReq.HttpMethod)
|
||||
|
||||
// 3. 验证必要字段
|
||||
if apiReq.Endpoint == "" || apiReq.HttpMethod == "" {
|
||||
logger.Error("Missing required fields in API test parameters")
|
||||
logger.Error("Missing required fields in API test parameters",
|
||||
"endpoint", apiReq.Endpoint,
|
||||
"http_method", apiReq.HttpMethod)
|
||||
overallSuccess = false
|
||||
break
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user