#!/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