1#!/usr/bin/env bash
2set -euo pipefail
3
4# Test Runner Script
5# Runs Bats tests and ShellCheck validation with summary reporting
6
7# ============================================================================
8# Configuration
9# ============================================================================
10
11SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12TOTAL_TESTS=0
13PASSED_TESTS=0
14FAILED_TESTS=0
15SHELLCHECK_ERRORS=0
16
17# Colors for output
18RED='\033[0;31m'
19GREEN='\033[0;32m'
20YELLOW='\033[1;33m'
21BLUE='\033[0;34m'
22NC='\033[0m' # No Color
23
24# ============================================================================
25# Utility Functions
26# ============================================================================
27
28print_header() {
29 echo -e "\n${BLUE}============================================${NC}"
30 echo -e "${BLUE}$1${NC}"
31 echo -e "${BLUE}============================================${NC}\n"
32}
33
34print_success() {
35 echo -e "${GREEN}✓ $1${NC}"
36}
37
38print_error() {
39 echo -e "${RED}✗ $1${NC}"
40}
41
42print_warning() {
43 echo -e "${YELLOW}⚠ $1${NC}"
44}
45
46# ============================================================================
47# Check Dependencies
48# ============================================================================
49
50check_dependencies() {
51 print_header "Checking Dependencies"
52
53 local all_deps_ok=true
54
55 # Check for bats
56 if command -v bats &> /dev/null; then
57 local bats_version
58 bats_version=$(bats --version | head -n1)
59 print_success "Bats found: $bats_version"
60 else
61 print_error "Bats not found"
62 echo " Install: npm install -g bats"
63 echo " Or: brew install bats-core (macOS)"
64 echo " Or: apt install bats (Ubuntu/Debian)"
65 all_deps_ok=false
66 fi
67
68 # Check for shellcheck
69 if command -v shellcheck &> /dev/null; then
70 local shellcheck_version
71 shellcheck_version=$(shellcheck --version | grep version: | awk '{print $2}')
72 print_success "ShellCheck found: version $shellcheck_version"
73 else
74 print_warning "ShellCheck not found (optional)"
75 echo " Install: brew install shellcheck (macOS)"
76 echo " Or: apt install shellcheck (Ubuntu/Debian)"
77 fi
78
79 if [[ "$all_deps_ok" == false ]]; then
80 echo
81 print_error "Missing required dependencies"
82 exit 1
83 fi
84
85 echo
86}
87
88# ============================================================================
89# Run Bats Tests
90# ============================================================================
91
92run_bats_tests() {
93 print_header "Running Bats Tests"
94
95 local test_files=("$SCRIPT_DIR"/*.bats)
96
97 if [[ ${#test_files[@]} -eq 0 ]] || [[ ! -f "${test_files[0]}" ]]; then
98 print_warning "No .bats test files found"
99 return
100 fi
101
102 # Run bats with TAP output
103 local bats_output
104 local bats_exit_code=0
105
106 for test_file in "${test_files[@]}"; do
107 echo -e "${BLUE}Running: $(basename "$test_file")${NC}"
108 echo
109
110 # Capture output and exit code
111 if bats_output=$(bats --tap "$test_file" 2>&1); then
112 echo "$bats_output"
113 else
114 bats_exit_code=$?
115 echo "$bats_output"
116 fi
117
118 # Parse TAP output for statistics
119 local tests_in_file
120 local passed_in_file
121 local failed_in_file
122
123 tests_in_file=$(echo "$bats_output" | grep -c "^ok\|^not ok" || true)
124 passed_in_file=$(echo "$bats_output" | grep -c "^ok" || true)
125 failed_in_file=$(echo "$bats_output" | grep -c "^not ok" || true)
126
127 TOTAL_TESTS=$((TOTAL_TESTS + tests_in_file))
128 PASSED_TESTS=$((PASSED_TESTS + passed_in_file))
129 FAILED_TESTS=$((FAILED_TESTS + failed_in_file))
130
131 echo
132 done
133
134 # Print summary
135 if [[ $FAILED_TESTS -eq 0 ]]; then
136 print_success "All Bats tests passed: $PASSED_TESTS/$TOTAL_TESTS"
137 else
138 print_error "Some Bats tests failed: $PASSED_TESTS passed, $FAILED_TESTS failed"
139 fi
140
141 echo
142}
143
144# ============================================================================
145# Run ShellCheck
146# ============================================================================
147
148run_shellcheck() {
149 print_header "Running ShellCheck"
150
151 if ! command -v shellcheck &> /dev/null; then
152 print_warning "ShellCheck not installed, skipping"
153 return
154 fi
155
156 local shell_files
157 shell_files=$(find "$SCRIPT_DIR" -name "*.sh" -type f)
158
159 if [[ -z "$shell_files" ]]; then
160 print_warning "No .sh files found"
161 return
162 fi
163
164 local has_errors=false
165
166 while IFS= read -r file; do
167 echo -e "${BLUE}Checking: $(basename "$file")${NC}"
168
169 if shellcheck_output=$(shellcheck "$file" 2>&1); then
170 print_success "No issues found"
171 else
172 has_errors=true
173 SHELLCHECK_ERRORS=$((SHELLCHECK_ERRORS + 1))
174 print_error "Issues found:"
175 echo "$shellcheck_output" | sed 's/^/ /'
176 fi
177
178 echo
179 done <<< "$shell_files"
180
181 # Summary
182 if [[ "$has_errors" == false ]]; then
183 print_success "All ShellCheck tests passed"
184 else
185 print_error "ShellCheck found issues in $SHELLCHECK_ERRORS file(s)"
186 fi
187
188 echo
189}
190
191# ============================================================================
192# Print Final Summary
193# ============================================================================
194
195print_summary() {
196 print_header "Test Summary"
197
198 echo "Bats Tests:"
199 echo " Total: $TOTAL_TESTS"
200 echo " Passed: $PASSED_TESTS"
201 echo " Failed: $FAILED_TESTS"
202 echo
203
204 if command -v shellcheck &> /dev/null; then
205 echo "ShellCheck:"
206 if [[ $SHELLCHECK_ERRORS -eq 0 ]]; then
207 echo " Status: All files passed"
208 else
209 echo " Status: $SHELLCHECK_ERRORS file(s) with issues"
210 fi
211 echo
212 fi
213
214 # Overall status
215 if [[ $FAILED_TESTS -eq 0 ]] && [[ $SHELLCHECK_ERRORS -eq 0 ]]; then
216 print_success "All tests passed!"
217 return 0
218 else
219 print_error "Some tests failed"
220 return 1
221 fi
222}
223
224# ============================================================================
225# Main Execution
226# ============================================================================
227
228main() {
229 echo "Test Runner for Math Library"
230 echo "============================="
231
232 check_dependencies
233 run_bats_tests
234 run_shellcheck
235 print_summary
236}
237
238# Run main and exit with appropriate code
239if main; then
240 exit 0
241else
242 exit 1
243fi