Files
httprunner/uixt/ai/ai_test.go
debugtalk c6f358ffca fix: convert AI tests from skip statements to build tags (#1783)
* fix: convert AI tests from skip statements to build tags

- Add //go:build localtest tag to uixt/ai/ai_test.go and examples/game/llk/main_test.go
- Remove environment-based skip statements and hasRequiredEnvVars functions
- Maintain consistency with existing build tag approach for mobile/device tests
- Prevents CI/CD failures when external AI services are not available

Co-authored-by: debugtalk <debugtalk@users.noreply.github.com>

* fix: add missing BoundBox type and field to Element struct

- Add BoundBox struct with X, Y, Width, Height fields
- Update Element struct to include BoundBox field
- Fix structural mismatch between test expectations and Go code
- Resolves CI compilation failures

Co-authored-by: debugtalk <debugtalk@users.noreply.github.com>

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2025-08-03 11:43:21 +08:00

202 lines
6.2 KiB
Go

//go:build localtest
package ai
import (
"context"
"testing"
"github.com/httprunner/httprunner/v5/internal/builtin"
"github.com/httprunner/httprunner/v5/uixt/option"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestILLMServiceQuery(t *testing.T) {
// Create LLM service
service, err := NewLLMService(option.OPENAI_GPT_4O)
require.NoError(t, err)
require.NotNil(t, service)
// Load test image
screenshot, size, err := builtin.LoadImage("testdata/llk_1.png")
require.NoError(t, err)
// Test basic query functionality
t.Run("BasicQuery", func(t *testing.T) {
opts := &QueryOptions{
Query: "请描述这张图片中的内容",
Screenshot: screenshot,
Size: size,
}
result, err := service.Query(context.Background(), opts)
assert.NoError(t, err)
assert.NotNil(t, result)
assert.NotEmpty(t, result.Content)
assert.NotEmpty(t, result.Thought)
assert.Nil(t, result.Data) // Should be nil for standard query
t.Logf("Query result: %s", result.Content)
})
// Test custom schema query
t.Run("CustomSchemaQuery", func(t *testing.T) {
type GameInfo struct {
Content string `json:"content"`
Thought string `json:"thought"`
Rows int `json:"rows"`
Cols int `json:"cols"`
Icons []string `json:"icons"`
}
opts := &QueryOptions{
Query: "请分析这个连连看游戏界面,告诉我有多少行多少列,有哪些不同类型的图案",
Screenshot: screenshot,
Size: size,
OutputSchema: GameInfo{},
}
result, err := service.Query(context.Background(), opts)
assert.NoError(t, err)
assert.NotNil(t, result)
assert.NotEmpty(t, result.Content)
assert.NotEmpty(t, result.Thought)
assert.NotNil(t, result.Data)
// Verify type conversion
if gameInfo, ok := result.Data.(*GameInfo); ok {
assert.NotEmpty(t, gameInfo.Content)
assert.NotEmpty(t, gameInfo.Thought)
assert.Greater(t, gameInfo.Rows, 0)
assert.Greater(t, gameInfo.Cols, 0)
assert.NotEmpty(t, gameInfo.Icons)
t.Logf("Game info: %+v", gameInfo)
} else {
t.Errorf("Expected *GameInfo, got %T", result.Data)
}
})
}
func TestILLMServiceIntegration(t *testing.T) {
// Create LLM service
service, err := NewLLMService(option.OPENAI_GPT_4O)
require.NoError(t, err)
require.NotNil(t, service)
// Load test image
screenshot, size, err := builtin.LoadImage("testdata/llk_1.png")
require.NoError(t, err)
ctx := context.Background()
// Test that all three methods work
t.Run("AllMethods", func(t *testing.T) {
// Test Query
queryOpts := &QueryOptions{
Query: "请分析这张图片",
Screenshot: screenshot,
Size: size,
}
queryResult, err := service.Query(ctx, queryOpts)
assert.NoError(t, err)
assert.NotNil(t, queryResult)
t.Logf("Query result: %s", queryResult.Content)
// Test Assert
assertOpts := &AssertOptions{
Assertion: "这是一个连连看游戏界面",
Screenshot: screenshot,
Size: size,
}
assertResult, err := service.Assert(ctx, assertOpts)
assert.NoError(t, err)
assert.NotNil(t, assertResult)
t.Logf("Assert result: pass=%v, thought=%s", assertResult.Pass, assertResult.Thought)
// Note: Planning test would require proper user instruction and message setup
// which is more complex, so we skip it in this integration test
})
}
// TestLLMServiceConfig tests the LLM service configuration functionality
func TestLLMServiceConfig(t *testing.T) {
t.Run("BasicConfiguration", func(t *testing.T) {
// Test creating config with same model for all components
modelType := option.DOUBAO_1_5_THINKING_VISION_PRO_250428
config := option.NewLLMServiceConfig(modelType)
assert.Equal(t, modelType, config.PlannerModel)
assert.Equal(t, modelType, config.AsserterModel)
assert.Equal(t, modelType, config.QuerierModel)
})
t.Run("MixedConfiguration", func(t *testing.T) {
// Test configuring different models for each component
config := option.NewLLMServiceConfig(option.DOUBAO_1_5_THINKING_VISION_PRO_250428).
WithPlannerModel(option.DOUBAO_1_5_UI_TARS_250328).
WithAsserterModel(option.OPENAI_GPT_4O).
WithQuerierModel(option.DEEPSEEK_R1_250528)
assert.Equal(t, option.DOUBAO_1_5_UI_TARS_250328, config.PlannerModel)
assert.Equal(t, option.OPENAI_GPT_4O, config.AsserterModel)
assert.Equal(t, option.DEEPSEEK_R1_250528, config.QuerierModel)
})
t.Run("RecommendedConfigurations", func(t *testing.T) {
configs := option.RecommendedConfigurations()
// Test mixed optimal configuration
mixedOptimal := configs["mixed_optimal"]
assert.NotNil(t, mixedOptimal)
assert.Equal(t, option.DOUBAO_1_5_UI_TARS_250328, mixedOptimal.PlannerModel)
assert.Equal(t, option.OPENAI_GPT_4O, mixedOptimal.AsserterModel)
assert.Equal(t, option.DEEPSEEK_R1_250528, mixedOptimal.QuerierModel)
// Test high performance configuration
highPerf := configs["high_performance"]
assert.NotNil(t, highPerf)
assert.Equal(t, option.OPENAI_GPT_4O, highPerf.PlannerModel)
assert.Equal(t, option.OPENAI_GPT_4O, highPerf.AsserterModel)
assert.Equal(t, option.OPENAI_GPT_4O, highPerf.QuerierModel)
})
}
// TestLLMServiceCreation tests service creation with different configurations
func TestLLMServiceCreation(t *testing.T) {
t.Run("BackwardCompatibility", func(t *testing.T) {
// Test that the original NewLLMService function still works
modelType := option.DOUBAO_1_5_THINKING_VISION_PRO_250428
service, err := NewLLMService(modelType)
// We expect an error due to missing environment variables in test environment
// but the function signature should be correct
if err != nil {
assert.NotNil(t, err)
assert.Nil(t, service)
} else {
assert.NotNil(t, service)
}
})
t.Run("WithAdvancedConfig", func(t *testing.T) {
// Test the new API with different models for each component
config := option.NewLLMServiceConfig(option.DOUBAO_1_5_THINKING_VISION_PRO_250428).
WithPlannerModel(option.DOUBAO_1_5_UI_TARS_250328).
WithAsserterModel(option.OPENAI_GPT_4O)
service, err := NewLLMServiceWithOptionConfig(config)
// We expect an error due to missing environment variables in test environment
// but the function signature should be correct
if err != nil {
assert.NotNil(t, err)
assert.Nil(t, service)
} else {
assert.NotNil(t, service)
}
})
}