홈 › CI/CD › 03 / 7

자동 테스트와 품질 게이트

섹션 7진행 0 / 7

3. 코드 예제

예제 1: 테스트 준비와 성공 실행 — 01_test_quality.sh 발췌

bash
cat > CalcTest.java <<'JAVA'
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class CalcTest {
    @Test void addWorks() { assertEquals(5, Calc.add(2, 3)); }
    @Test void divideWorks() { assertEquals(2, Calc.divide(6, 3)); }
    @Test void isEvenWorks() { assertTrue(Calc.isEven(4)); }
}
JAVA
"$JAVA_BIN/javac" -encoding UTF-8 -d out -cp "$JUNIT_JAR" Calc.java CalcTest.java
run_junit   # execute --class-path out --scan-class-path --details=summary
text
컴파일 완료: out/Calc.class out/CalcTest.class

[         4 containers found      ]
[         4 containers successful ]
# (중략: skipped·started·aborted 는 모두 0)
[         3 tests found           ]
[         3 tests successful      ]
[         0 tests failed          ]

게이트 통과: 테스트 종료 코드 0

run_junit 은 tty 잡음과 실행 시간(ms) 줄을 걸러 내는 함수입니다. 컨테이너 4개는 플랫폼·Jupiter 엔진·테스트 클래스·스위트를 합친 개수입니다.

예제 2: 실패와 종료 코드 — 01_test_quality.sh 발췌

bash
cat > Calc.java <<'JAVA'
public class Calc {
    public static int add(int a, int b) { return a - b; } // 버그: 뺄셈으로 잘못 구현
    public static int divide(int a, int b) { return a / b; }
    public static boolean isEven(int n) { return n % 2 == 0; }
}
JAVA
"$JAVA_BIN/javac" -encoding UTF-8 -d out -cp "$JUNIT_JAR" Calc.java CalcTest.java
if run_junit; then
  echo "게이트 통과: 테스트 종료 코드 0"
else
  echo "게이트 실패: 테스트 종료 코드 1 -> 파이프라인 다음 단계로 진행하지 않습니다."
fi
text
Failures (1):
  JUnit Jupiter:CalcTest:addWorks()
    => org.opentest4j.AssertionFailedError: expected: <5> but was: <-1>
       CalcTest.addWorks(CalcTest.java:5)

# (중략: MethodSource 줄, containers 요약 4줄)
[         3 tests found           ]
[         2 tests successful      ]
[         1 tests failed          ]

게이트 실패: 테스트 종료 코드 1 -> 파이프라인 다음 단계로 진행하지 않습니다.

add 를 뺄셈으로 바꾸자 addWorks 만 실패하고, 실패 원인과 위치(CalcTest.java:5)가 그대로 나옵니다.

예제 3: 테스트 리포트 XML — 01_test_quality.sh 발췌

bash
run_junit --reports-dir=reports > /dev/null
find reports -type f | sort
grep -oE '<testsuite name="[^"]*" tests="[0-9]*" skipped="[0-9]*" failures="[0-9]*" errors="[0-9]*"' \
  reports/TEST-junit-jupiter.xml
text
reports/TEST-junit-jupiter.xml
reports/TEST-junit-platform-suite.xml
reports/TEST-junit-vintage.xml
요약(시간·호스트 제외):
<testsuite name="JUnit Jupiter" tests="3" skipped="0" failures="0" errors="0"

세 XML 은 각각 Jupiter 엔진·스위트·빈티지(JUnit 4 호환) 결과입니다. 실제 파일에는 time·hostname 속성도 있지만 실행마다 값이 달라 예제에서는 뺐습니다.

예제 4: 정적 검사와 품질 게이트 — 01_test_quality.sh 발췌

bash
"$JAVA_BIN/javac" -encoding UTF-8 -Xlint:all -d out2 Raw.java 2>&1
echo "종료 코드: $?"
"$JAVA_BIN/javac" -encoding UTF-8 -Xlint:all -Werror -d out2 Raw.java 2>&1 | tail -n 2

quality_gate() {
  local ok=0
  "$JAVA_BIN/javac" -encoding UTF-8 -d out -cp "$JUNIT_JAR" Calc.java CalcTest.java || ok=1
  run_junit > /dev/null || ok=1
  "$JAVA_BIN/javac" -encoding UTF-8 -Xlint:all -Werror -d out2 Calc.java > /dev/null 2>&1 || ok=1
  return "$ok"
}
text
Raw.java:5: warning: [rawtypes] found raw type: List
    static List values() {
           ^
  missing type arguments for generic class List<E>
2 warnings
종료 코드: 0
1 error
2 warnings
종료 코드: 1

품질 게이트 통과 -> 다음 단계(패키징)로 진행합니다.

같은 코드가 -Xlint:all 만으로는 경고(종료 0), -Werror 를 더하면 에러(종료 1)입니다. quality_gate 는 컴파일·테스트·정적 검사 중 하나라도 실패하면 ok=1 을 반환합니다.