refactor: [shitty claude AI first try] restructure server and user services, add new test cases, and improve error handling
This commit is contained in:
225
test/testutil/test_helpers.go
Normal file
225
test/testutil/test_helpers.go
Normal file
@ -0,0 +1,225 @@
|
||||
package testutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.logidex.ru/fakz9/logidex-id/internal/api/user/domain"
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// TestContext creates a context with timeout for tests
|
||||
func TestContext(t *testing.T) context.Context {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
t.Cleanup(cancel)
|
||||
return ctx
|
||||
}
|
||||
|
||||
// CreateTestUser creates a test user with default values
|
||||
func CreateTestUser(t *testing.T) *domain.User {
|
||||
return &domain.User{
|
||||
Uuid: uuid.New().String(),
|
||||
PhoneNumber: "+79161234567",
|
||||
}
|
||||
}
|
||||
|
||||
// CreateTestUserWithPhone creates a test user with specified phone number
|
||||
func CreateTestUserWithPhone(t *testing.T, phoneNumber string) *domain.User {
|
||||
return &domain.User{
|
||||
Uuid: uuid.New().String(),
|
||||
PhoneNumber: phoneNumber,
|
||||
}
|
||||
}
|
||||
|
||||
// AssertValidUUID checks if a string is a valid UUID
|
||||
func AssertValidUUID(t *testing.T, uuidStr string) {
|
||||
_, err := uuid.Parse(uuidStr)
|
||||
assert.NoError(t, err, "Expected valid UUID, got: %s", uuidStr)
|
||||
}
|
||||
|
||||
// AssertValidPhoneNumber checks if a phone number follows expected format
|
||||
func AssertValidPhoneNumber(t *testing.T, phoneNumber string) {
|
||||
assert.NotEmpty(t, phoneNumber)
|
||||
assert.True(t, len(phoneNumber) >= 10, "Phone number should be at least 10 characters")
|
||||
assert.True(t, phoneNumber[0] == '+', "Phone number should start with +")
|
||||
}
|
||||
|
||||
// TimeoutContext creates a context that times out after the specified duration
|
||||
// Note: This function returns a context without a cancel function.
|
||||
// Use TestContext(t) instead for proper cleanup in tests.
|
||||
func TimeoutContext(timeout time.Duration) (context.Context, context.CancelFunc) {
|
||||
return context.WithTimeout(context.Background(), timeout)
|
||||
}
|
||||
|
||||
// ErrorsContain checks if an error contains a specific substring
|
||||
func ErrorsContain(t *testing.T, err error, substring string) {
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), substring)
|
||||
}
|
||||
|
||||
// AssertNoError is a helper that fails the test if error is not nil
|
||||
func AssertNoError(t *testing.T, err error, msgAndArgs ...interface{}) {
|
||||
assert.NoError(t, err, msgAndArgs...)
|
||||
}
|
||||
|
||||
// AssertError is a helper that fails the test if error is nil
|
||||
func AssertError(t *testing.T, err error, msgAndArgs ...interface{}) {
|
||||
assert.Error(t, err, msgAndArgs...)
|
||||
}
|
||||
|
||||
// StringPtr returns a pointer to a string value
|
||||
func StringPtr(s string) *string {
|
||||
return &s
|
||||
}
|
||||
|
||||
// IntPtr returns a pointer to an int value
|
||||
func IntPtr(i int) *int {
|
||||
return &i
|
||||
}
|
||||
|
||||
// BoolPtr returns a pointer to a bool value
|
||||
func BoolPtr(b bool) *bool {
|
||||
return &b
|
||||
}
|
||||
|
||||
// TestPhoneNumbers contains various phone numbers for testing
|
||||
var TestPhoneNumbers = struct {
|
||||
ValidRussian string
|
||||
ValidUS string
|
||||
ValidUK string
|
||||
Invalid string
|
||||
Empty string
|
||||
TooShort string
|
||||
WithSpaces string
|
||||
WithDashes string
|
||||
WithParentheses string
|
||||
}{
|
||||
ValidRussian: "+79161234567",
|
||||
ValidUS: "+12345678901",
|
||||
ValidUK: "+441234567890",
|
||||
Invalid: "not-a-phone",
|
||||
Empty: "",
|
||||
TooShort: "123",
|
||||
WithSpaces: "+7 916 123 45 67",
|
||||
WithDashes: "+7-916-123-45-67",
|
||||
WithParentheses: "+7 (916) 123-45-67",
|
||||
}
|
||||
|
||||
// TestUUIDs contains various UUIDs for testing
|
||||
var TestUUIDs = struct {
|
||||
Valid1 string
|
||||
Valid2 string
|
||||
Invalid string
|
||||
Empty string
|
||||
}{
|
||||
Valid1: "123e4567-e89b-12d3-a456-426614174000",
|
||||
Valid2: "987fcdeb-51a2-43d1-9f12-345678901234",
|
||||
Invalid: "not-a-uuid",
|
||||
Empty: "",
|
||||
}
|
||||
|
||||
// TestErrors contains common test errors
|
||||
var TestErrors = struct {
|
||||
Generic error
|
||||
NotFound error
|
||||
Invalid error
|
||||
Timeout error
|
||||
}{
|
||||
Generic: assert.AnError,
|
||||
NotFound: domain.ErrUserNotFound{PhoneNumber: "+79161234567"},
|
||||
Invalid: assert.AnError,
|
||||
Timeout: context.DeadlineExceeded,
|
||||
}
|
||||
|
||||
// CleanupFunc is a function that cleans up test resources
|
||||
type CleanupFunc func()
|
||||
|
||||
// SetupTestEnvironment sets up a test environment and returns cleanup function
|
||||
func SetupTestEnvironment(t *testing.T) CleanupFunc {
|
||||
// This could set up test databases, Redis connections, etc.
|
||||
// For now, it's a placeholder for future implementation
|
||||
|
||||
return func() {
|
||||
// Cleanup resources
|
||||
}
|
||||
}
|
||||
|
||||
// WaitFor waits for a condition to be true or timeout
|
||||
func WaitFor(t *testing.T, condition func() bool, timeout time.Duration, message string) {
|
||||
ticker := time.NewTicker(100 * time.Millisecond)
|
||||
defer ticker.Stop()
|
||||
|
||||
timeoutChan := time.After(timeout)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
if condition() {
|
||||
return
|
||||
}
|
||||
case <-timeoutChan:
|
||||
t.Fatalf("Timeout waiting for condition: %s", message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Eventually runs a function until it succeeds or times out
|
||||
func Eventually(t *testing.T, fn func() error, timeout time.Duration, message string) {
|
||||
ticker := time.NewTicker(100 * time.Millisecond)
|
||||
defer ticker.Stop()
|
||||
|
||||
timeoutChan := time.After(timeout)
|
||||
|
||||
var lastErr error
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
if err := fn(); err == nil {
|
||||
return
|
||||
} else {
|
||||
lastErr = err
|
||||
}
|
||||
case <-timeoutChan:
|
||||
t.Fatalf("Timeout waiting for function to succeed: %s. Last error: %v", message, lastErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ParallelTest runs a test function in parallel multiple times
|
||||
func ParallelTest(t *testing.T, fn func(*testing.T), count int) {
|
||||
for i := 0; i < count; i++ {
|
||||
i := i // capture loop variable
|
||||
t.Run(fmt.Sprintf("parallel_%d", i), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
fn(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// BenchmarkHelper provides utilities for benchmark tests
|
||||
type BenchmarkHelper struct {
|
||||
b *testing.B
|
||||
}
|
||||
|
||||
// NewBenchmarkHelper creates a new benchmark helper
|
||||
func NewBenchmarkHelper(b *testing.B) *BenchmarkHelper {
|
||||
return &BenchmarkHelper{b: b}
|
||||
}
|
||||
|
||||
// ResetTimer resets the benchmark timer
|
||||
func (bh *BenchmarkHelper) ResetTimer() {
|
||||
bh.b.ResetTimer()
|
||||
}
|
||||
|
||||
// StopTimer stops the benchmark timer
|
||||
func (bh *BenchmarkHelper) StopTimer() {
|
||||
bh.b.StopTimer()
|
||||
}
|
||||
|
||||
// StartTimer starts the benchmark timer
|
||||
func (bh *BenchmarkHelper) StartTimer() {
|
||||
bh.b.StartTimer()
|
||||
}
|
||||
Reference in New Issue
Block a user