blob: 02360a19953974c0d33f5fa7ba15d430b3b65565 [file] [log] [blame]
#!/bin/bash
# CSV Test Report Generator
# Parses Go test JSON output and generates CSV report with test results
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Logging functions
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Function to show usage
show_usage() {
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Generate CSV report from Go test JSON output"
echo ""
echo "OPTIONS:"
echo " -u, --unit FILE Unit test JSON file"
echo " -i, --integration FILE Integration test JSON file"
echo " -o, --output FILE Output CSV file (default: test-results.csv)"
echo " -h, --help Show this help"
echo ""
echo "EXAMPLES:"
echo " $0 -u unit-tests.json -i integration-tests.json -o results.csv"
echo " $0 --unit unit.json --integration int.json"
echo ""
}
# Default values
UNIT_JSON=""
INTEGRATION_JSON=""
OUTPUT_CSV="test-results.csv"
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
-u|--unit)
UNIT_JSON="$2"
shift 2
;;
-i|--integration)
INTEGRATION_JSON="$2"
shift 2
;;
-o|--output)
OUTPUT_CSV="$2"
shift 2
;;
-h|--help)
show_usage
exit 0
;;
*)
log_error "Unknown option: $1"
show_usage
exit 1
;;
esac
done
# Validate inputs
if [[ -z "$UNIT_JSON" && -z "$INTEGRATION_JSON" ]]; then
log_error "At least one JSON file must be provided"
show_usage
exit 1
fi
# Check if jq is available
if ! command -v jq &> /dev/null; then
log_error "jq is required but not installed. Please install jq to parse JSON."
exit 1
fi
# Function to parse test JSON and extract results
parse_test_json() {
local json_file="$1"
local category="$2"
if [[ ! -f "$json_file" ]]; then
log_warning "JSON file not found: $json_file"
return 0
fi
log_info "Parsing $category tests from: $json_file"
# Parse JSON and extract test results
jq -r '
select(.Action == "run" or .Action == "pass" or .Action == "fail" or .Action == "skip") |
select(.Test != null) |
{
test: .Test,
action: .Action,
elapsed: (.Elapsed // 0),
output: (.Output // "")
}
' "$json_file" | while IFS= read -r line; do
if [[ -n "$line" && "$line" != "null" ]]; then
echo "$line"
fi
done
}
# Function to determine test status and warnings
get_test_status() {
local test_data="$1"
local test_name=$(echo "$test_data" | jq -r '.test')
local action=$(echo "$test_data" | jq -r '.action')
local output=$(echo "$test_data" | jq -r '.output // ""')
local status="UNKNOWN"
local warnings=""
case "$action" in
"pass")
status="PASS"
# Check for warnings in output
if echo "$output" | grep -qi "warning\|warn\|deprecated\|timeout"; then
status="PASS_WITH_WARNING"
warnings=$(echo "$output" | grep -i "warning\|warn\|deprecated\|timeout" | head -1 | tr -d '\n\r' | sed 's/"/""/g')
fi
;;
"fail")
status="FAIL"
# Extract error message
if [[ -n "$output" ]]; then
warnings=$(echo "$output" | head -1 | tr -d '\n\r' | sed 's/"/""/g')
fi
;;
"skip")
status="SKIP"
# Extract skip reason
if [[ -n "$output" ]]; then
warnings=$(echo "$output" | head -1 | tr -d '\n\r' | sed 's/"/""/g')
fi
;;
"run")
# Test is starting, we'll get the result later
return 0
;;
esac
echo "$status|$warnings"
}
# Function to generate CSV content
generate_csv() {
local csv_file="$1"
log_info "Generating CSV report: $csv_file"
# Create CSV header
echo "Category,Test Name,Status,Duration (s),Warnings/Notes" > "$csv_file"
local total_tests=0
local passed_tests=0
local failed_tests=0
local skipped_tests=0
local warning_tests=0
# Process unit tests
if [[ -n "$UNIT_JSON" && -f "$UNIT_JSON" ]]; then
log_info "Processing unit tests..."
# Group test results by test name
declare -A test_results
while IFS= read -r line; do
if [[ -n "$line" && "$line" != "null" ]]; then
local test_name=$(echo "$line" | jq -r '.test')
local action=$(echo "$line" | jq -r '.action')
local elapsed=$(echo "$line" | jq -r '.elapsed')
local output=$(echo "$line" | jq -r '.output // ""')
# Store the latest result for each test
test_results["$test_name"]="$action|$elapsed|$output"
fi
done < <(parse_test_json "$UNIT_JSON" "Unit")
# Write unit test results to CSV
for test_name in "${!test_results[@]}"; do
local result_data="${test_results[$test_name]}"
local action=$(echo "$result_data" | cut -d'|' -f1)
local elapsed=$(echo "$result_data" | cut -d'|' -f2)
local output=$(echo "$result_data" | cut -d'|' -f3-)
local status_info=$(get_test_status "{\"test\":\"$test_name\",\"action\":\"$action\",\"output\":\"$output\"}")
local status=$(echo "$status_info" | cut -d'|' -f1)
local warnings=$(echo "$status_info" | cut -d'|' -f2-)
# Escape CSV values
test_name=$(echo "$test_name" | sed 's/"/""/g')
warnings=$(echo "$warnings" | sed 's/"/""/g')
echo "Unit,\"$test_name\",$status,$elapsed,\"$warnings\"" >> "$csv_file"
# Update counters
total_tests=$((total_tests + 1))
case "$status" in
"PASS") passed_tests=$((passed_tests + 1)) ;;
"FAIL") failed_tests=$((failed_tests + 1)) ;;
"SKIP") skipped_tests=$((skipped_tests + 1)) ;;
"PASS_WITH_WARNING")
passed_tests=$((passed_tests + 1))
warning_tests=$((warning_tests + 1))
;;
esac
done
fi
# Process integration tests
if [[ -n "$INTEGRATION_JSON" && -f "$INTEGRATION_JSON" ]]; then
log_info "Processing integration tests..."
# Group test results by test name
declare -A test_results
while IFS= read -r line; do
if [[ -n "$line" && "$line" != "null" ]]; then
local test_name=$(echo "$line" | jq -r '.test')
local action=$(echo "$line" | jq -r '.action')
local elapsed=$(echo "$line" | jq -r '.elapsed')
local output=$(echo "$line" | jq -r '.output // ""')
# Store the latest result for each test
test_results["$test_name"]="$action|$elapsed|$output"
fi
done < <(parse_test_json "$INTEGRATION_JSON" "Integration")
# Write integration test results to CSV
for test_name in "${!test_results[@]}"; do
local result_data="${test_results[$test_name]}"
local action=$(echo "$result_data" | cut -d'|' -f1)
local elapsed=$(echo "$result_data" | cut -d'|' -f2)
local output=$(echo "$result_data" | cut -d'|' -f3-)
local status_info=$(get_test_status "{\"test\":\"$test_name\",\"action\":\"$action\",\"output\":\"$output\"}")
local status=$(echo "$status_info" | cut -d'|' -f1)
local warnings=$(echo "$status_info" | cut -d'|' -f2-)
# Escape CSV values
test_name=$(echo "$test_name" | sed 's/"/""/g')
warnings=$(echo "$warnings" | sed 's/"/""/g')
echo "Integration,\"$test_name\",$status,$elapsed,\"$warnings\"" >> "$csv_file"
# Update counters
total_tests=$((total_tests + 1))
case "$status" in
"PASS") passed_tests=$((passed_tests + 1)) ;;
"FAIL") failed_tests=$((failed_tests + 1)) ;;
"SKIP") skipped_tests=$((skipped_tests + 1)) ;;
"PASS_WITH_WARNING")
passed_tests=$((passed_tests + 1))
warning_tests=$((warning_tests + 1))
;;
esac
done
fi
# Add summary section
echo "" >> "$csv_file"
echo "SUMMARY" >> "$csv_file"
echo "Total Tests,$total_tests" >> "$csv_file"
echo "Passed,$passed_tests" >> "$csv_file"
echo "Failed,$failed_tests" >> "$csv_file"
echo "Skipped,$skipped_tests" >> "$csv_file"
echo "Passed with Warnings,$warning_tests" >> "$csv_file"
echo "Success Rate,$(echo "scale=2; $passed_tests * 100 / $total_tests" | bc -l)%" >> "$csv_file"
# Print summary to console
echo ""
log_success "CSV report generated: $csv_file"
echo "=========================================="
echo "TEST SUMMARY"
echo "=========================================="
echo "Total Tests: $total_tests"
echo "Passed: $passed_tests"
echo "Failed: $failed_tests"
echo "Skipped: $skipped_tests"
echo "Passed with Warnings: $warning_tests"
echo "Success Rate: $(echo "scale=2; $passed_tests * 100 / $total_tests" | bc -l)%"
echo "=========================================="
# Return exit code based on results
if [[ $failed_tests -gt 0 ]]; then
return 1
else
return 0
fi
}
# Main execution
main() {
log_info "Starting CSV report generation..."
# Check if bc is available for calculations
if ! command -v bc &> /dev/null; then
log_warning "bc not found, success rate calculation will be skipped"
fi
# Generate CSV
if generate_csv "$OUTPUT_CSV"; then
log_success "CSV report generation completed successfully"
exit 0
else
log_error "CSV report generation completed with failures"
exit 1
fi
}
# Run main function
main "$@"