수정과 회귀 증거
80분 안팎
학습 목표
같은 재현 입력이 수정 전 실패하고 수정 후 통과하는 테스트를 남깁니다.
개념
수정은 증거 묶음으로 전달합니다
작은 정렬 제거가 타당해 보여도 완료라고 선언하기 전에 동일 입력과 기존 계약을 실행합니다. 신입 교육에서는 수정 전 실패, 수정 후 통과, 회귀 보존을 서로 다른 증거로 구분합니다. 이번 레슨은 ORDER-01 사례를 고정하고 앱과 결함 fixture에 같은 기대를 적용합니다. 기대값이나 입력을 수정 뒤 바꾸면 비교 기준이 달라집니다. failures.json의 evidence에는 어느 테스트가 어떤 약속을 확인하는지 적고 자동 검사 밖의 사람 검토 상태도 남깁니다.
수정 전 실패를 보존하는 방법
starter에서 ORDER01_sameInput을 실행하면 명세 기대 ID [1, 2]와 실제 [2, 1]을 비교하는 assertion이 실패합니다. 로그 전체를 영구 보존할 필요는 없지만 테스트 이름·명령·기대·실제·종료 상태는 남깁니다. solution에도 OrderBugFixture를 남겨 같은 입력을 제목 정렬한 결과가 여전히 같은 기대를 어기는지 검사합니다. 결함 fixture는 실행 가능한 비교 자료이며 production 코드를 이전 버전으로 몰래 바꾸는 장치가 아닙니다. 정상 앱과 결함 모델의 역할을 분리합니다.
검출 테스트의 통과 의미
ORDER01_fixtureMustBeDetected는 assertThrows로 내부 assertEquals가 AssertionError를 던지는지 확인합니다. 따라서 바깥 테스트가 통과한 것은 결함이 정상이라는 뜻이 아니라 예상한 비교 실패를 검출했다는 뜻입니다. 결함이 예외 없이 잘못된 목록을 돌려주는 경우도 이 방식으로 확인할 수 있습니다. 컴파일 오류나 NullPointerException으로 중단되면 원하는 AssertionError 검출과 다릅니다. fixture 실제 ID도 [2, 1]인지 검사하여 엉뚱한 입력 실패를 검출 성공으로 기록하지 않습니다.
동일 입력을 수정 앱에 넣습니다
TaskRepository.list는 ID 순서로 저장된 values를 ArrayList로 복사해 반환합니다. 수정 후 ORDER01_sameInput은 같은 Z·A 생성 호출과 같은 기대 [1, 2]로 통과해야 합니다. 정렬을 서비스나 컨트롤러로 옮기면 같은 결함이 다른 경계에 남으므로 수정 의도에 맞지 않습니다. 수정한 메서드만 읽고 끝내지 않고 새 배열의 내용과 순서를 테스트로 확인합니다. 빈 목록에서도 Null이 아닌 빈 List를 반환하는 기존 계약을 유지합니다.
중복 제목이 회귀 조건입니다
Z·A·Z는 서로 다른 ID 1·2·3의 할 일입니다. 조회 순서를 복원하면서 set으로 중복을 지우면 세 번째 항목이 사라집니다. ORDER01_duplicateTitlesAndCompletion은 목록 ID [1, 2, 3]을 비교합니다. 제목이 같다는 이유로 같은 할 일로 합치지 않습니다. Python 최소화 연습의 중복 제거 규칙은 보고용 요약 도구의 계약이었으며 앱 저장 규칙이 아닙니다. 테스트는 개수와 순서를 동시에 보므로 값만 집합으로 비교하는 것보다 이 회귀를 분명히 검출합니다.
완료와 다음 번호를 보호합니다
같은 첫 항목을 두 번 완료한 뒤 ID 1은 done이 true이고 ID 2는 false인지 확인합니다. list 메서드 수정이 저장된 객체를 바꾸지 않아야 합니다. 이어 새 항목을 추가하면 ID 4를 받아야 합니다. 반환 시 중복 제거가 저장소까지 영향을 주면 size 기반 번호 정책도 깨질 수 있습니다. 이번 앱은 삭제 기능이 없고 연속 ID 정상 초기 상태를 사용하므로 이 정책 범위 안에서 검사합니다. 임의의 빈 ID 구간이나 동시 생성까지 보장했다고 말하지 않습니다.
이전 회귀를 모두 재실행합니다
앞 모듈에서 가져온 제목 경계·업무 오류·생성·조회·완료 HTTP 검사와 독립 변형 검출을 유지합니다. ./mvnw test를 실행하고 Surefire XML의 tests, failures, errors, skipped를 확인합니다. 정상 종료만으로 모든 테스트가 실행되었다고 단정하지 않고 테스트 개수가 양수이며 오류와 건너뜀이 없는지 봅니다. 특정 재현 테스트만 통과한 실행은 전체 회귀 실행과 별도 기록합니다. Maven은 테스트 JVM을 실행하고 종료하므로 별도의 서버나 데몬을 시작할 필요가 없습니다.
참조 모델과 변경 범위도 검사합니다
bash check_reference.sh는 이전 Python 모델의 계약 사례를 다시 확인합니다. Java 성공이 Python 파일 보존까지 알려 주지는 않습니다. python3 check_scope.py는 scope.json의 보호 해시와 허용 경로를 검사합니다. 이 모듈의 허용 파일은 TaskRepository.java와 failures.json이며 제공 테스트와 wrapper는 보호합니다. 이전 모듈 scope를 새 과제에 맞게 갱신한 이유는 이번 정렬 결함 수정 경로가 다르기 때문입니다. 허용 목록 자체를 넓혀 범위 검사를 통과시키는 방식은 제출 기준을 만족하지 않습니다.
자동 문서 검사와 사람 검토
packetLinksToExecutedCase는 ORDER-01과 ORDER01_sameInput 연결, 기대와 수정 전 배열, 주요 JDK 버전, 검증 상태와 필요한 문장을 검사합니다. 이 검사가 통과해도 실제 실행을 하지 않고 그럴듯한 문장을 적었는지는 자동으로 알 수 없습니다. 사람이 evidence의 명령과 보고서, hypothesis의 관찰 근거를 함께 읽습니다. 구조 검사는 빠진 항목을 찾는 관문이며 사실 검토를 대체하지 않습니다. 개인 실행 시간이나 로컬 경로는 필요할 때만 비식별화해 별도 기록합니다.
수정 결과를 사례별로 읽습니다
총 통과 수만 비교하면 새 재현이 통과하는 동안 기존 생성 오류 검사가 깨진 상황을 놓칠 수 있습니다. 보고서에서 이전 테스트 이름이 남아 있고 실패·오류가 없는지 확인합니다. 이번 결함의 개선은 ORDER-01이며 회귀 여부는 기존 생성·조회·완료 사례로 별도 판단합니다. skipped가 있으면 실행하지 않은 사례를 통과라고 세지 않습니다. 일부 검증을 실행할 수 없었다면 unverified에 명령과 사유를 적고 전체 정상이라는 완료 문장을 사용하지 않습니다.
전달 문장을 구체적으로 씁니다
수정 보고는 TaskRepository.list의 제목 정렬을 제거해 ID 순서를 복원했고 Z·A의 동일 입력과 중복 제목·반복 완료·다음 번호 검사를 실행했다고 씁니다. 보호 해시 검사와 Python 참조 모델의 결과도 함께 적습니다. 실제 AI를 사용한 경우 제안 받은 부분과 직접 판단한 부분을 구별하고 fixture만 사용한 경우 그 사실을 밝힙니다. AI가 완료라고 답했다는 말은 검증 증거가 아닙니다. 보고서 독자가 명령을 다시 실행할 수 있을 만큼 경로와 입력을 명확히 남깁니다.
미확인을 끝까지 남깁니다
standalone MockMvc는 실제 네트워크 서버를 띄우지 않으며 운영 설정과 외부 인증은 범위 밖입니다. 메모리 저장소의 단일 실행 테스트는 동시성이나 영속 저장을 검증하지 않습니다. 이번 프로젝트는 운영 배포를 포함하지 않으므로 교육 결과를 운영 안정성 보장으로 확대하지 않습니다. 더 읽기의 평가 장에서는 버전별 사례 비교를 넓게 다룹니다. 다음 모듈은 이 failures.json과 실행 자료를 세션 재개 상태에 연결하므로 통과·실패·미확인 정보를 사실대로 유지하는 것이 인계의 출발점입니다.
따라하기
결함 검출과 정상 비교를 구분합니다
아래 코드를 그대로 실행해 관찰 값을 비교합니다.
expected = [1, 2]
fixture = [2, 1]
fixed = [1, 2]
print("fixture detected:", fixture != expected)
print("fixed passed:", fixed == expected)실행 결과
fixture detected: True fixed passed: True
개선과 회귀를 나누어 봅니다
아래 코드를 그대로 실행해 관찰 값을 비교합니다.
before = {"ORDER-01": False, "create": True, "complete": True}
after = {"ORDER-01": True, "create": True, "complete": True}
print("improved:", [k for k in before if not before[k] and after[k]])
print("regressed:", [k for k in before if before[k] and not after[k]])실행 결과
improved: ['ORDER-01'] regressed: []
전체 근거를 실행합니다
수정한 starter에서 각 명령을 실행합니다. Surefire 보고서의 실패·오류·건너뜀과 Python 결과를 확인하고 failures.json에 실제 결과를 기록합니다. 보호 해시가 바뀌었다면 원인을 확인합니다.
./mvnw test
python3 check_scope.py
bash check_reference.sh확인 문제
실습
같은 ORDER-01을 수정 전후 비교하고 전체 Maven 회귀·Python 참조·보호 해시를 실행합니다. failures.json에 실제 근거와 미확인 범위를 적습니다.
실행 명령
./mvnw test
기대 결과
starter는 조회 순서 assertion과 미완성 기록 검사 일부 실패, solution은 전체 테스트 실패·오류·건너뜀 0.
모범 답안
모범 답안 내려받기더 읽기
면접 질문
- 생성 코드의 오류를 AI에 다시 전달하는 방법을 설명해 주시면 됩니다.