- Updated DESIGN_V2.md to reflect changes in the handling of before/after scripts, removing the `scripts:` prefix and clarifying their usage in JSONL test cases. - Enhanced runner.go to integrate global before/after hooks, ensuring they execute correctly before and after test cases. - Revised types.go to include new fields for before/after scripts in test case and options structures. - Improved TODO_V2.md to track the implementation progress of before/after script functionality and related tasks. - Added utility function LoadAgentTestScripts to facilitate loading of test scripts from the agent's src directory.
244 lines
5.9 KiB
Go
244 lines
5.9 KiB
Go
package test_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
v8 "github.com/yaoapp/gou/runtime/v8"
|
|
agenttest "github.com/yaoapp/yao/agent/test"
|
|
"github.com/yaoapp/yao/config"
|
|
"github.com/yaoapp/yao/test"
|
|
)
|
|
|
|
const hooksTestAgent = "assistants/tests/hooks-test"
|
|
|
|
func TestParseHookRef(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
wantFile string
|
|
wantFunc string
|
|
expectErr bool
|
|
}{
|
|
{
|
|
name: "function only",
|
|
input: "Before",
|
|
wantFile: "",
|
|
wantFunc: "Before",
|
|
},
|
|
{
|
|
name: "with script file",
|
|
input: "env_test.Before",
|
|
wantFile: "env_test.ts",
|
|
wantFunc: "Before",
|
|
},
|
|
{
|
|
name: "with src prefix",
|
|
input: "src/env_test.Before",
|
|
wantFile: "env_test.ts",
|
|
wantFunc: "Before",
|
|
},
|
|
{
|
|
name: "nested path",
|
|
input: "setup/db_test.Before",
|
|
wantFile: "setup/db_test.ts",
|
|
wantFunc: "Before",
|
|
},
|
|
{
|
|
name: "empty string",
|
|
input: "",
|
|
expectErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
ref, err := agenttest.ParseHookRef(tt.input)
|
|
if tt.expectErr {
|
|
assert.Error(t, err)
|
|
return
|
|
}
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, tt.wantFile, ref.ScriptFile)
|
|
assert.Equal(t, tt.wantFunc, ref.Function)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestHookExecutorLoadTestScripts(t *testing.T) {
|
|
// Prepare test environment
|
|
test.Prepare(t, config.Conf)
|
|
defer test.Clean()
|
|
|
|
// Load agent test scripts using the utility function
|
|
scripts := test.LoadAgentTestScripts(t, hooksTestAgent)
|
|
|
|
assert.NotEmpty(t, scripts, "Should load at least one test script")
|
|
|
|
// Verify the script was loaded into V8
|
|
found := false
|
|
for _, scriptID := range scripts {
|
|
if _, ok := v8.Scripts[scriptID]; ok {
|
|
found = true
|
|
t.Logf("Loaded script: %s", scriptID)
|
|
break
|
|
}
|
|
}
|
|
assert.True(t, found, "At least one script should be loaded into V8")
|
|
}
|
|
|
|
func TestHookExecutorExecuteBefore(t *testing.T) {
|
|
// Prepare test environment
|
|
test.Prepare(t, config.Conf)
|
|
defer test.Clean()
|
|
|
|
// Load agent test scripts
|
|
test.LoadAgentTestScripts(t, hooksTestAgent)
|
|
|
|
executor := agenttest.NewHookExecutor(true)
|
|
|
|
testCase := &agenttest.Case{
|
|
ID: "TEST001",
|
|
Input: "Hello World",
|
|
}
|
|
|
|
// Execute Before hook
|
|
beforeData, err := executor.ExecuteBefore("env_test.Before", testCase, hooksTestAgent)
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, beforeData)
|
|
|
|
// Verify returned data
|
|
dataMap, ok := beforeData.(map[string]interface{})
|
|
assert.True(t, ok, "beforeData should be a map")
|
|
assert.Equal(t, "TEST001", dataMap["test_id"])
|
|
assert.NotEmpty(t, dataMap["mock_user_id"])
|
|
assert.NotEmpty(t, dataMap["mock_session_id"])
|
|
}
|
|
|
|
func TestHookExecutorExecuteAfter(t *testing.T) {
|
|
// Prepare test environment
|
|
test.Prepare(t, config.Conf)
|
|
defer test.Clean()
|
|
|
|
// Load agent test scripts
|
|
test.LoadAgentTestScripts(t, hooksTestAgent)
|
|
|
|
executor := agenttest.NewHookExecutor(true)
|
|
|
|
testCase := &agenttest.Case{
|
|
ID: "TEST002",
|
|
Input: "Test input",
|
|
}
|
|
|
|
result := &agenttest.Result{
|
|
ID: "TEST002",
|
|
Status: agenttest.StatusPassed,
|
|
DurationMs: 100,
|
|
}
|
|
|
|
beforeData := map[string]interface{}{
|
|
"test_id": "TEST002",
|
|
"mock_user_id": "user_TEST002_12345",
|
|
"mock_session_id": "session_12345",
|
|
}
|
|
|
|
// Execute After hook
|
|
err := executor.ExecuteAfter("env_test.After", testCase, result, beforeData, hooksTestAgent)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestHookExecutorExecuteBeforeAll(t *testing.T) {
|
|
// Prepare test environment
|
|
test.Prepare(t, config.Conf)
|
|
defer test.Clean()
|
|
|
|
// Load agent test scripts
|
|
test.LoadAgentTestScripts(t, hooksTestAgent)
|
|
|
|
executor := agenttest.NewHookExecutor(true)
|
|
|
|
testCases := []*agenttest.Case{
|
|
{ID: "T001", Input: "Test 1"},
|
|
{ID: "T002", Input: "Test 2"},
|
|
{ID: "T003", Input: "Test 3"},
|
|
}
|
|
|
|
// Execute BeforeAll hook
|
|
globalData, err := executor.ExecuteBeforeAll("env_test.BeforeAll", testCases, hooksTestAgent)
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, globalData)
|
|
|
|
// Verify returned data
|
|
dataMap, ok := globalData.(map[string]interface{})
|
|
assert.True(t, ok, "globalData should be a map")
|
|
assert.NotEmpty(t, dataMap["suite_id"])
|
|
assert.Equal(t, float64(3), dataMap["test_count"]) // JSON numbers are float64
|
|
}
|
|
|
|
func TestHookExecutorExecuteAfterAll(t *testing.T) {
|
|
// Prepare test environment
|
|
test.Prepare(t, config.Conf)
|
|
defer test.Clean()
|
|
|
|
// Load agent test scripts
|
|
test.LoadAgentTestScripts(t, hooksTestAgent)
|
|
|
|
executor := agenttest.NewHookExecutor(true)
|
|
|
|
results := []*agenttest.Result{
|
|
{ID: "T001", Status: agenttest.StatusPassed, DurationMs: 100},
|
|
{ID: "T002", Status: agenttest.StatusFailed, DurationMs: 200, Error: "assertion failed"},
|
|
{ID: "T003", Status: agenttest.StatusPassed, DurationMs: 150},
|
|
}
|
|
|
|
globalData := map[string]interface{}{
|
|
"suite_id": "suite_12345",
|
|
"test_count": 3,
|
|
}
|
|
|
|
// Execute AfterAll hook
|
|
err := executor.ExecuteAfterAll("env_test.AfterAll", results, globalData, hooksTestAgent)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestHookExecutorFunctionNotFound(t *testing.T) {
|
|
// Prepare test environment
|
|
test.Prepare(t, config.Conf)
|
|
defer test.Clean()
|
|
|
|
// Load agent test scripts
|
|
test.LoadAgentTestScripts(t, hooksTestAgent)
|
|
|
|
executor := agenttest.NewHookExecutor(true)
|
|
|
|
testCase := &agenttest.Case{
|
|
ID: "TEST001",
|
|
Input: "Hello",
|
|
}
|
|
|
|
// Try to execute non-existent function
|
|
_, err := executor.ExecuteBefore("env_test.NonExistent", testCase, hooksTestAgent)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "not defined")
|
|
}
|
|
|
|
func TestHookExecutorScriptNotFound(t *testing.T) {
|
|
// Prepare test environment
|
|
test.Prepare(t, config.Conf)
|
|
defer test.Clean()
|
|
|
|
// Load agent test scripts
|
|
test.LoadAgentTestScripts(t, hooksTestAgent)
|
|
|
|
executor := agenttest.NewHookExecutor(true)
|
|
|
|
testCase := &agenttest.Case{
|
|
ID: "TEST001",
|
|
Input: "Hello",
|
|
}
|
|
|
|
// Try to execute from non-existent script
|
|
_, err := executor.ExecuteBefore("nonexistent_test.Before", testCase, hooksTestAgent)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "not found")
|
|
}
|