227 lines
7.2 KiB
Bash
Executable File
227 lines
7.2 KiB
Bash
Executable File
#!/bin/bash
|
|
# 테스트 실패 재현 및 진단 스크립트
|
|
# 사용법: ./scripts/reproduce_test.sh "테스트이름" [옵션]
|
|
|
|
# 색상 정의
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[0;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# 기본 설정
|
|
TEST_NAME="$1"
|
|
VERBOSE=0
|
|
COLLECT_DIAGNOSTICS=1
|
|
RETRY_COUNT=3
|
|
TIMEOUT_MS=2000
|
|
ISOLATION_MODE="strict"
|
|
|
|
# 스크립트 경로 설정
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
DIAGNOSTICS_DIR="$PROJECT_ROOT/test_diagnostics"
|
|
|
|
# 사용법 출력
|
|
usage() {
|
|
echo -e "${BLUE}테스트 실패 재현 및 진단 스크립트${NC}"
|
|
echo "사용법: $0 \"테스트이름\" [옵션]"
|
|
echo ""
|
|
echo "옵션:"
|
|
echo " -v, --verbose 상세 로그 출력"
|
|
echo " -n, --no-diagnostics 진단 정보 수집 비활성화"
|
|
echo " -r, --retry=N 재시도 횟수 설정 (기본값: 3)"
|
|
echo " -t, --timeout=MS 타임아웃 설정 (밀리초, 기본값: 2000)"
|
|
echo " -i, --isolation=MODE 격리 모드 설정 (strict, normal, relaxed)"
|
|
echo " -h, --help 도움말 표시"
|
|
echo ""
|
|
echo "예시:"
|
|
echo " $0 \"MemberService 테스트\" --verbose --retry=5"
|
|
exit 1
|
|
}
|
|
|
|
# 매개변수 파싱
|
|
parse_params() {
|
|
if [ -z "$TEST_NAME" ]; then
|
|
echo -e "${RED}오류: 테스트 이름이 필요합니다.${NC}"
|
|
usage
|
|
fi
|
|
|
|
# 나머지 매개변수 처리
|
|
shift
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
-v|--verbose)
|
|
VERBOSE=1
|
|
;;
|
|
-n|--no-diagnostics)
|
|
COLLECT_DIAGNOSTICS=0
|
|
;;
|
|
-r=*|--retry=*)
|
|
RETRY_COUNT="${1#*=}"
|
|
;;
|
|
-t=*|--timeout=*)
|
|
TIMEOUT_MS="${1#*=}"
|
|
;;
|
|
-i=*|--isolation=*)
|
|
ISOLATION_MODE="${1#*=}"
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
;;
|
|
*)
|
|
echo -e "${RED}오류: 알 수 없는 옵션: $1${NC}"
|
|
usage
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
}
|
|
|
|
# 진단 디렉토리 생성
|
|
setup_diagnostics() {
|
|
if [ $COLLECT_DIAGNOSTICS -eq 1 ]; then
|
|
mkdir -p "$DIAGNOSTICS_DIR"
|
|
echo -e "${BLUE}진단 정보 수집 활성화: $DIAGNOSTICS_DIR${NC}"
|
|
fi
|
|
}
|
|
|
|
# 환경 정보 수집
|
|
collect_environment_info() {
|
|
if [ $COLLECT_DIAGNOSTICS -eq 1 ]; then
|
|
LOG_FILE="$DIAGNOSTICS_DIR/environment_$(date +%Y%m%d_%H%M%S).log"
|
|
|
|
echo "=== 환경 정보 ===" > "$LOG_FILE"
|
|
echo "날짜: $(date)" >> "$LOG_FILE"
|
|
echo "운영체제: $(uname -a)" >> "$LOG_FILE"
|
|
echo "Flutter 버전: $(flutter --version | head -n 1)" >> "$LOG_FILE"
|
|
echo "Dart 버전: $(dart --version)" >> "$LOG_FILE"
|
|
echo "CPU 정보: $(sysctl -n machdep.cpu.brand_string 2>/dev/null || echo 'N/A')" >> "$LOG_FILE"
|
|
echo "메모리 정보: $(vm_stat | grep 'Pages free' | awk '{print $3}' | sed 's/\.//')" >> "$LOG_FILE"
|
|
echo "테스트 설정:" >> "$LOG_FILE"
|
|
echo " - 테스트 이름: $TEST_NAME" >> "$LOG_FILE"
|
|
echo " - 재시도 횟수: $RETRY_COUNT" >> "$LOG_FILE"
|
|
echo " - 타임아웃: $TIMEOUT_MS ms" >> "$LOG_FILE"
|
|
echo " - 격리 모드: $ISOLATION_MODE" >> "$LOG_FILE"
|
|
echo " - 상세 로그: $VERBOSE" >> "$LOG_FILE"
|
|
|
|
echo -e "${GREEN}환경 정보 수집 완료: $LOG_FILE${NC}"
|
|
fi
|
|
}
|
|
|
|
# 테스트 실행
|
|
run_test() {
|
|
echo -e "${BLUE}테스트 실행: $TEST_NAME${NC}"
|
|
echo -e "${YELLOW}설정: 재시도=$RETRY_COUNT, 타임아웃=$TIMEOUT_MS ms, 격리=$ISOLATION_MODE${NC}"
|
|
|
|
# 환경 변수 설정
|
|
export FLUTTER_TEST_TIMEOUT_OVERRIDE="$TIMEOUT_MS"
|
|
export FLUTTER_TEST_RETRY_COUNT="$RETRY_COUNT"
|
|
export FLUTTER_TEST_ISOLATION_MODE="$ISOLATION_MODE"
|
|
export FLUTTER_TEST_DIAGNOSTICS="$COLLECT_DIAGNOSTICS"
|
|
|
|
# 테스트 명령 구성
|
|
TEST_CMD="flutter test --name=\"$TEST_NAME\""
|
|
|
|
if [ $VERBOSE -eq 1 ]; then
|
|
TEST_CMD="$TEST_CMD --verbose"
|
|
fi
|
|
|
|
# 테스트 실행 및 결과 저장
|
|
cd "$PROJECT_ROOT"
|
|
|
|
if [ $COLLECT_DIAGNOSTICS -eq 1 ]; then
|
|
LOG_FILE="$DIAGNOSTICS_DIR/test_run_$(date +%Y%m%d_%H%M%S).log"
|
|
echo -e "${YELLOW}테스트 로그 저장: $LOG_FILE${NC}"
|
|
|
|
# 테스트 실행 및 로그 저장
|
|
eval "$TEST_CMD" 2>&1 | tee "$LOG_FILE"
|
|
TEST_RESULT=${PIPESTATUS[0]}
|
|
else
|
|
# 진단 없이 테스트 실행
|
|
eval "$TEST_CMD"
|
|
TEST_RESULT=$?
|
|
fi
|
|
|
|
# 테스트 결과 처리
|
|
if [ $TEST_RESULT -eq 0 ]; then
|
|
echo -e "${GREEN}테스트 성공!${NC}"
|
|
else
|
|
echo -e "${RED}테스트 실패! (종료 코드: $TEST_RESULT)${NC}"
|
|
|
|
if [ $COLLECT_DIAGNOSTICS -eq 1 ]; then
|
|
echo -e "${YELLOW}진단 정보 분석 중...${NC}"
|
|
analyze_failure "$LOG_FILE"
|
|
fi
|
|
fi
|
|
|
|
return $TEST_RESULT
|
|
}
|
|
|
|
# 실패 분석
|
|
analyze_failure() {
|
|
local LOG_FILE="$1"
|
|
local ANALYSIS_FILE="$DIAGNOSTICS_DIR/analysis_$(date +%Y%m%d_%H%M%S).txt"
|
|
|
|
echo "=== 테스트 실패 분석 ===" > "$ANALYSIS_FILE"
|
|
echo "분석 시간: $(date)" >> "$ANALYSIS_FILE"
|
|
echo "테스트: $TEST_NAME" >> "$ANALYSIS_FILE"
|
|
echo "" >> "$ANALYSIS_FILE"
|
|
|
|
# 일반적인 실패 패턴 검색
|
|
echo "== 타임아웃 관련 오류 ==" >> "$ANALYSIS_FILE"
|
|
grep -i "timeout\|timed out" "$LOG_FILE" >> "$ANALYSIS_FILE" 2>/dev/null || echo "없음" >> "$ANALYSIS_FILE"
|
|
|
|
echo "" >> "$ANALYSIS_FILE"
|
|
echo "== 비동기 관련 오류 ==" >> "$ANALYSIS_FILE"
|
|
grep -i "async\|await\|future\|stream\|pending timer" "$LOG_FILE" >> "$ANALYSIS_FILE" 2>/dev/null || echo "없음" >> "$ANALYSIS_FILE"
|
|
|
|
echo "" >> "$ANALYSIS_FILE"
|
|
echo "== 이벤트 버스 관련 오류 ==" >> "$ANALYSIS_FILE"
|
|
grep -i "eventbus\|event bus\|subscription" "$LOG_FILE" >> "$ANALYSIS_FILE" 2>/dev/null || echo "없음" >> "$ANALYSIS_FILE"
|
|
|
|
echo "" >> "$ANALYSIS_FILE"
|
|
echo "== 메모리 관련 오류 ==" >> "$ANALYSIS_FILE"
|
|
grep -i "memory\|leak\|dispose\|resource" "$LOG_FILE" >> "$ANALYSIS_FILE" 2>/dev/null || echo "없음" >> "$ANALYSIS_FILE"
|
|
|
|
echo "" >> "$ANALYSIS_FILE"
|
|
echo "== 추천 조치 ==" >> "$ANALYSIS_FILE"
|
|
|
|
# 타임아웃 관련 오류 처리
|
|
if grep -qi "timeout\|timed out" "$LOG_FILE"; then
|
|
echo "- 타임아웃 값을 증가시켜 보세요 (현재: $TIMEOUT_MS ms, 추천: $((TIMEOUT_MS * 2)) ms)" >> "$ANALYSIS_FILE"
|
|
echo "- 비동기 작업 완료를 기다리는 코드를 검토하세요" >> "$ANALYSIS_FILE"
|
|
fi
|
|
|
|
# 이벤트 버스 관련 오류 처리
|
|
if grep -qi "eventbus\|event bus\|subscription" "$LOG_FILE"; then
|
|
echo "- EventBus 구독 해제 코드를 확인하세요" >> "$ANALYSIS_FILE"
|
|
echo "- dispose() 메서드에서 모든 리소스가 정리되는지 확인하세요" >> "$ANALYSIS_FILE"
|
|
echo "- 테스트 간 격리 모드를 'strict'로 설정해 보세요" >> "$ANALYSIS_FILE"
|
|
fi
|
|
|
|
# 메모리 관련 오류 처리
|
|
if grep -qi "memory\|leak\|dispose\|resource" "$LOG_FILE"; then
|
|
echo "- 메모리 누수 가능성이 있습니다. dispose() 메서드를 확인하세요" >> "$ANALYSIS_FILE"
|
|
echo "- 테스트 종료 후 모든 리소스가 정리되는지 확인하세요" >> "$ANALYSIS_FILE"
|
|
fi
|
|
|
|
echo -e "${GREEN}분석 완료: $ANALYSIS_FILE${NC}"
|
|
|
|
# 분석 결과 요약 출력
|
|
echo -e "${YELLOW}=== 분석 요약 ===${NC}"
|
|
cat "$ANALYSIS_FILE" | grep -v "없음" | head -n 20
|
|
}
|
|
|
|
# 메인 실행 흐름
|
|
main() {
|
|
parse_params "$@"
|
|
setup_diagnostics
|
|
collect_environment_info
|
|
run_test
|
|
exit $?
|
|
}
|
|
|
|
# 스크립트 실행
|
|
main "$@"
|