second commit

This commit is contained in:
Rogee
2026-06-04 15:44:48 +08:00
parent 4db6efb3a7
commit 8ac150bc7b
1275 changed files with 286124 additions and 0 deletions
+219
View File
@@ -0,0 +1,219 @@
# GoChat Test Coverage Report
> Generated: Initial template
> Target: 80%+ coverage across all modules
> Reference: Chatwoot RSpec coverage patterns mapped to Go testing conventions
## Coverage Targets Per Module
| Module | Target Coverage | Priority | Status |
|--------|----------------|----------|--------|
| `internal/model` | 90% | High | Pending |
| `internal/repository` | 85% | High | Pending |
| `internal/service` | 80% | High | Pending |
| `internal/auth` | 85% | High | Pending |
| `internal/handler` | 75% | Medium | Pending |
| `internal/middleware` | 80% | Medium | Pending |
| `internal/channel` | 75% | Medium | Pending |
| `internal/channel/provider` | 70% | Medium | Pending |
| `internal/config` | 80% | Low | Pending |
| `internal/app` | 60% | Low | Pending |
| `internal/router` | 70% | Low | Pending |
| `internal/ws` | 75% | Medium | Pending |
| `internal/pubsub` | 75% | Medium | Pending |
| `pkg/crypto` | 90% | High | Pending |
| `pkg/logger` | 80% | Medium | Pending |
## Module Coverage Details
### internal/model (Target: 90%)
Model tests focus on:
- CRUD operations via GORM (Create, Read, Update, Delete)
- Association integrity (foreign keys, belongs-to, has-many)
- Validation rules (required fields, unique constraints, format checks)
- Soft delete behavior (DeletedAt field, recovery)
- Custom types (JSONB permissions, enum fields)
- Edge cases (null fields, empty strings, boundary values)
Key test files:
- `internal/model/base_test.go` — Base model fields, timestamps, soft delete
- `internal/model/user_test.go` — User CRUD, role validation, email uniqueness
- `internal/model/account_test.go` — Account CRUD, locale/timezone defaults
- `internal/model/conversation_test.go` — Conversation status transitions, assignee
- `internal/model/message_test.go` — Message types, content validation, privacy
- `internal/model/custom_role_test.go` — Permission matrix parsing, role CRUD
- `internal/model/contact_test.go` — Contact identification, channel binding
### internal/repository (Target: 85%)
Repository tests focus on:
- BaseRepository generic CRUD operations
- Specialized repository query methods (FindByAccount, FindByStatus, etc.)
- Pagination (offset/limit)
- Error handling (record not found, duplicate key)
- Soft-delete scoped queries
- Transaction support
Key test files:
- `internal/repository/repository_test.go` — BaseRepository[T] generic CRUD
- `internal/repository/user_repo_test.go` — FindByEmail, FindByAccount
- `internal/repository/conversation_repo_test.go` — FindByAccount, FindByStatus, FindByAssignee
- `internal/repository/message_repo_test.go` — FindByConversation, Search
- `internal/repository/account_repo_test.go` — Account CRUD operations
### internal/service (Target: 80%)
Service tests focus on:
- Business logic correctness
- Input validation
- Error handling and propagation
- Cross-service coordination
- Authorization checks (RBAC integration)
- AI/Copilot features (Captain, LLM Provider)
Key test files:
- `internal/service/auth_service_test.go` — Login, Register, Refresh, Logout flows
- `internal/service/conversation_service_test.go` — CRUD, status transitions, assignment
- `internal/service/message_service_test.go` — Create, Search, privacy controls
- `internal/service/rbac_service_test.go` — Role assignment, permission checking, custom roles
- `internal/service/captain_service_test.go` — Captain Assistant CRUD, Document, Scenario
- `internal/service/copilot_service_test.go` — Thread, Message, AI reply suggestions
- `internal/service/llm_provider_test.go` — LLM Provider interface compliance
### internal/auth (Target: 85%)
Auth tests focus on:
- JWT token generation and validation
- Refresh token lifecycle
- Permission system (administrator, agent, custom_role)
- Policy context construction
- MFA (TOTP) verification
- OAuth provider integration
Key test files:
- `internal/auth/jwt_test.go` — Token pair generation, expiry, validation
- `internal/auth/permission_test.go` — Permission sets for each role level
- `internal/auth/policy_test.go` — PolicyContext authorization checks
- `internal/auth/mfa_test.go` — TOTP generation and verification
- `internal/auth/oauth_test.go` — OAuth provider flow
### internal/handler (Target: 75%)
Handler tests focus on:
- HTTP request/response correctness
- Route parameter binding
- Authentication middleware integration
- Response format (JSON structure, status codes)
- Error response formatting
Key test files:
- `internal/handler/auth/auth_handler_test.go` — Auth endpoints
- `internal/handler/api_v1/conversation_handler_test.go` — Conversation API
- `internal/handler/api_v1/message_handler_test.go` — Message API
- `internal/handler/webhook/webhook_handler_test.go` — Webhook processing
- `internal/handler/ws/ws_handler_test.go` — WebSocket connection
### internal/middleware (Target: 80%)
Middleware tests focus on:
- Authentication extraction from headers
- Role-based access control enforcement
- CORS configuration
- Rate limiting behavior
- Request logging
### internal/channel (Target: 75%)
Channel tests focus on:
- Channel provider interface compliance
- Webhook processing pipeline
- Message broker routing
- Provider-specific configuration validation
- Incoming/outgoing message transformation
### pkg/crypto (Target: 90%)
Crypto tests focus on:
- Password hashing (bcrypt)
- JWT token generation and validation
- Token expiry handling
- Invalid token rejection
### pkg/logger (Target: 80%)
Logger tests focus on:
- Log level filtering
- Structured logging output
- Context-aware logging
## Test Strategy Matrix
| Test Type | Scope | Tool | Count Target |
|-----------|-------|------|-------------|
| Unit Tests | Single function/method | `go test` | 200+ |
| Integration Tests | Service + Repository | `go test` with SQLite | 50+ |
| E2E Tests | Full HTTP flow | httptest + SQLite | 30+ |
| Benchmark Tests | Performance | `go test -bench` | 20+ |
| Mock Tests | External dependencies | httptest mock server | 15+ |
## Coverage Collection Method
```bash
# Run all tests with coverage
go test -coverprofile=coverage.out -covermode=atomic ./...
# View per-function coverage
go tool cover -func=coverage.out
# Generate HTML report
go tool cover -html=coverage.out -o coverage.html
# Run benchmarks
go test -bench=. -benchmem ./internal/service/ ./internal/repository/ ./pkg/crypto/
```
## Coverage Quality Gates
- **Critical modules** (model, repository, auth, crypto): Must achieve 85%+ coverage
- **Business logic** (service, middleware): Must achieve 80%+ coverage
- **HTTP layer** (handler, channel): Must achieve 75%+ coverage
- **Infrastructure** (app, config, router): Must achieve 60%+ coverage
- **Overall project**: Must achieve 80%+ average coverage
## Chatwoot Test Pattern Mapping
| Chatwoot Pattern | Go Equivalent | Coverage Focus |
|-----------------|---------------|---------------|
| `spec/models/` (RSpec model specs) | `internal/model/*_test.go` | Model CRUD + validations |
| `spec/services/` (service_object specs) | `internal/service/*_test.go` | Business logic |
| `spec/controllers/` (controller specs) | `internal/handler/*_test.go` | HTTP API responses |
| `spec/policies/` (Pundit policy specs) | `internal/auth/*_test.go` | RBAC permission checks |
| `spec/integration/` (integration specs) | `tests/e2e/*_test.go` | Full flow scenarios |
| `spec/jobs/` (Sidekiq job specs) | `internal/worker/*_test.go` | Background task processing |
| FactoryBot fixtures | SQLite in-memory GORM seeds | Test data setup |
| Shoulda Matchers | testify/assert + custom validators | Assertion helpers |
## Running the Report
```bash
# Quick unit test coverage
./scripts/coverage/generate_report.sh --quick
# Full coverage with HTML report
./scripts/coverage/generate_report.sh --html
# Include E2E tests
./scripts/coverage/generate_report.sh --e2e --html
# Include benchmarks
./scripts/coverage/generate_report.sh --bench --html
```
## Continuous Improvement
Coverage targets should be reviewed quarterly. As new features are added:
1. Each new module must have tests before merge
2. Coverage must not decrease on existing modules
3. Critical paths (auth, payments, data integrity) require 90%+ coverage
4. Use `go test -race` to catch concurrent access issues
+198
View File
@@ -0,0 +1,198 @@
#!/bin/bash
# generate_report.sh — Run all tests, collect coverage, generate HTML report
# Reference: Chatwoot's test coverage tracking approach mapped to Go tooling
#
# Usage:
# ./scripts/coverage/generate_report.sh # Full coverage report
# ./scripts/coverage/generate_report.sh --quick # Quick report (unit tests only)
# ./scripts/coverage/generate_report.sh --html # Generate HTML report
#
# Output:
# - coverage.out: Raw coverage profile
# - coverage.html: HTML coverage report (with --html)
# - coverage_summary.txt: Per-package coverage summary
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
COVERAGE_DIR="$SCRIPT_DIR"
# Colors for terminal output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${BLUE}=== GoChat Test Coverage Report Generator ===${NC}"
echo ""
# Parse arguments
QUICK_MODE=false
HTML_MODE=false
E2E_MODE=false
BENCHMARK_MODE=false
for arg in "$@"; do
case $arg in
--quick) QUICK_MODE=true ;;
--html) HTML_MODE=true ;;
--e2e) E2E_MODE=true ;;
--bench) BENCHMARK_MODE=true ;;
--help)
echo "Usage: $0 [--quick] [--html] [--e2e] [--bench]"
echo ""
echo " --quick Run unit tests only (skip E2E and benchmarks)"
echo " --html Generate HTML coverage report"
echo " --e2e Include E2E tests in coverage"
echo " --bench Include benchmark tests"
exit 0
;;
*) echo "Unknown argument: $arg"; exit 1 ;;
esac
done
cd "$PROJECT_ROOT"
# Ensure coverage output directory exists
mkdir -p "$COVERAGE_DIR"
COVERAGE_FILE="$COVERAGE_DIR/coverage.out"
COVERAGE_HTML="$COVERAGE_DIR/coverage.html"
COVERAGE_SUMMARY="$COVERAGE_DIR/coverage_summary.txt"
# Clean previous coverage data
rm -f "$COVERAGE_FILE" "$COVERAGE_HTML" "$COVERAGE_SUMMARY"
echo -e "${YELLOW}Running test suite with coverage profiling...${NC}"
# Build the test command
TEST_PKGS=(
"./internal/model/..."
"./internal/repository/..."
"./internal/service/..."
"./internal/auth/..."
"./internal/handler/..."
"./internal/middleware/..."
"./internal/channel/..."
"./internal/channel/provider/..."
"./internal/config/..."
"./internal/app/..."
"./internal/router/..."
"./internal/ws/..."
"./internal/pubsub/..."
"./pkg/crypto/..."
"./pkg/logger/..."
)
if [ "$E2E_MODE" = true ]; then
TEST_PKGS+=("./tests/e2e/...")
fi
# Run tests with coverage
echo -e "${BLUE}Running unit tests...${NC}"
FAIL_COUNT=0
for pkg in "${TEST_PKGS[@]}"; do
echo -e " Testing: ${GREEN}$pkg${NC}"
# Check if package has test files
HAS_TESTS=$(find "$PROJECT_ROOT/${pkg%/...}" -name "*_test.go" 2>/dev/null | head -1)
if [ -z "$HAS_TESTS" ]; then
echo -e " ${YELLOW}No test files found — skipping${NC}"
continue
fi
# Run tests with coverage
PKG_COVERAGE="$COVERAGE_DIR/pkg_$(echo "$pkg" | tr '/' '_' | sed 's/\.\.\.//g').out"
if go test -coverprofile="$PKG_COVERAGE" -covermode=atomic -v "$pkg" 2>&1 | tee "$COVERAGE_DIR/test_output_$(echo "$pkg" | tr '/' '_').log"; then
echo -e " ${GREEN}PASS${NC}"
else
echo -e " ${RED}FAIL${NC}"
FAIL_COUNT=$((FAIL_COUNT + 1))
fi
# Append package coverage to main coverage file
if [ -f "$PKG_COVERAGE" ]; then
cat "$PKG_COVERAGE" >> "$COVERAGE_FILE"
fi
done
echo ""
# Generate per-package coverage summary
echo -e "${YELLOW}Generating coverage summary...${NC}"
echo "# GoChat Coverage Summary" > "$COVERAGE_SUMMARY"
echo "# Generated: $(date)" >> "$COVERAGE_SUMMARY"
echo "" >> "$COVERAGE_SUMMARY"
for pkg in "${TEST_PKGS[@]}"; do
PKG_COVERAGE="$COVERAGE_DIR/pkg_$(echo "$pkg" | tr '/' '_' | sed 's/\.\.\.//g').out"
if [ -f "$PKG_COVERAGE" ]; then
COVERAGE_PCT=$(go tool cover -func="$PKG_COVERAGE" 2>/dev/null | tail -1 | awk '{print $3}')
echo " $pkg: $COVERAGE_PCT" >> "$COVERAGE_SUMMARY"
echo -e " ${GREEN}$pkg${NC}: ${COVERAGE_PCT}"
fi
done
echo ""
# Calculate overall coverage
if [ -f "$COVERAGE_FILE" ]; then
OVERALL_COVERAGE=$(go tool cover -func="$COVERAGE_FILE" 2>/dev/null | tail -1 | awk '{print $3}')
echo -e "${BLUE}Overall coverage: ${GREEN}${OVERALL_COVERAGE}${NC}"
echo "" >> "$COVERAGE_SUMMARY"
echo "Overall: $OVERALL_COVERAGE" >> "$COVERAGE_SUMMARY"
fi
# Generate HTML report if requested
if [ "$HTML_MODE" = true ] && [ -f "$COVERAGE_FILE" ]; then
echo -e "${YELLOW}Generating HTML coverage report...${NC}"
go tool cover -html="$COVERAGE_FILE" -o "$COVERAGE_HTML"
echo -e "${GREEN}HTML report saved to: $COVERAGE_HTML${NC}"
fi
# Run benchmark tests if requested
if [ "$BENCHMARK_MODE" = true ]; then
echo ""
echo -e "${YELLOW}Running benchmark tests...${NC}"
BENCHMARK_PKGS=(
"./internal/service/..."
"./internal/repository/..."
"./pkg/crypto/..."
)
BENCHMARK_FILE="$COVERAGE_DIR/benchmark_results.txt"
for pkg in "${BENCHMARK_PKGS[@]}"; do
echo -e " Benchmarking: ${GREEN}$pkg${NC}"
go test -bench=. -benchmem -run=^$ "$pkg" 2>&1 | tee -a "$BENCHMARK_FILE"
done
echo -e "${GREEN}Benchmark results saved to: $BENCHMARK_FILE${NC}"
fi
# Summary
echo ""
echo -e "${BLUE}=== Report Summary ===${NC}"
echo -e " Coverage profile: $COVERAGE_FILE"
echo -e " Coverage summary: $COVERAGE_SUMMARY"
if [ "$HTML_MODE" = true ]; then
echo -e " HTML report: $COVERAGE_HTML"
fi
if [ "$BENCHMARK_MODE" = true ]; then
echo -e " Benchmark results: $BENCHMARK_FILE"
fi
echo -e " Failed packages: $FAIL_COUNT"
echo ""
if [ "$FAIL_COUNT" -gt 0 ]; then
echo -e "${RED}Some tests failed. Please review the logs.${NC}"
exit 1
else
echo -e "${GREEN}All tests passed!${NC}"
exit 0
fi