starter-kit/docs/testing.md
2025-05-21 12:39:40 +07:00

120 lines
3.1 KiB
Markdown

# Testing
## Tổng quan
Testing là một phần quan trọng trong quy trình phát triển, đảm bảo chất lượng mã nguồn và giảm thiểu bugs. Dự án này sử dụng các công cụ và phương pháp testing tiêu chuẩn trong Golang.
## Unit Testing
### Công cụ sử dụng
- Testify: Framework unit testing cho Go
- Table-driven tests: Thiết kế test cases linh hoạt
- Mocking: Giả lập dependencies
### Quy ước và cấu trúc
- Mỗi package cần có file `*_test.go` tương ứng
- Các test functions có format `Test{FunctionName}`
- Test cases nên bao gồm cả happy path và error cases
- Coverage yêu cầu tối thiểu: 80%
- Sử dụng t.Run() để chạy các subtest
### Mẫu Unit Test
```go
// user_service_test.go
package user
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
// Mocking repository
type MockUserRepository struct {
mock.Mock
}
func (m *MockUserRepository) FindByID(id string) (*User, error) {
args := m.Called(id)
if args.Get(0) == nil {
return nil, args.Error(1)
}
return args.Get(0).(*User), args.Error(1)
}
func TestGetUser(t *testing.T) {
// Test cases
testCases := []struct {
name string
userID string
mockUser *User
mockError error
expectedUser *User
expectedError error
}{
{
name: "successful_get",
userID: "123",
mockUser: &User{ID: "123", Name: "Test User"},
mockError: nil,
expectedUser: &User{ID: "123", Name: "Test User"},
expectedError: nil,
},
{
name: "user_not_found",
userID: "456",
mockUser: nil,
mockError: ErrUserNotFound,
expectedUser: nil,
expectedError: ErrUserNotFound,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
// Setup mock
mockRepo := new(MockUserRepository)
mockRepo.On("FindByID", tc.userID).Return(tc.mockUser, tc.mockError)
// Create service with mock dependency
service := NewUserService(mockRepo)
// Call the method
user, err := service.GetUser(tc.userID)
// Assert results
assert.Equal(t, tc.expectedUser, user)
assert.Equal(t, tc.expectedError, err)
// Verify expectations
mockRepo.AssertExpectations(t)
})
}
}
```
## Integration Testing
### Approach
- Test containers: Chạy dependent services (database, caching, etc) trong Docker containers
- API testing: Kiểm tra endpoints và responses
- DB testing: Kiểm tra queries và migrations
### Setup và Teardown
- Sử dụng `TestMain` để setup và teardown test environment
- Cấu hình Docker containers cho testing
- Cleanup sau khi chạy tests
## E2E Testing
- API black-box testing
- Sequence testing cho business flows
- Performance testing
## CI/CD Integration
- Chạy tests trên mỗi commit và PR
- Lưu test results và coverage
- Chỉ merge khi tests pass
## Best Practices
1. **Write tests first (TDD approach)**
2. **Keep tests independent và idempotent**
3. **Sử dụng fixtures cho test data**
4. **Tránh hard-coding external dependencies**
5. **Tách common test code thành helper functions**