어제 오늘 내일

[JUnit] run() 메소드 – 테스트 실행 흐름 따라가기 본문

IT/JUnit

[JUnit] run() 메소드 – 테스트 실행 흐름 따라가기

hi.anna 2026. 1. 12. 08:09

JUnit에서 테스트가 어떻게 실행되는지 이해하려면 run() 메소드가 수행하는 역할을 알아야 합니다.
특히 JUnit3·4 기반의 테스트 러너 구조에서는 run() 메소드가 테스트 실행의 중심이었으며,
JUnit5에서도 내부적으로는 비슷한 개념을 유지하고 있습니다.

이번 글에서는 초보자도 이해할 수 있도록 run() 메소드가 어떤 흐름으로 테스트를 실행하는지 예제와 함께 설명합니다.

 

1. run() 메소드란 무엇인가?

JUnit은 테스트 실행 과정을 다음과 같은 흐름으로 처리합니다.

  • 테스트 준비
  • 테스트 메소드 실행
  • 결과 수집
  • 실패/성공 여부 반환

이 전체 과정을 하나의 메소드가 대표하는데, 그것이 바로 **run()**입니다.

JUnit3·4에서는 다음과 같은 형태로 구성됩니다.

  • TestCase.run()
  • TestSuite.run()
  • JUnitCore.run()

즉, 테스트 단위든 스위트든 실행 시작점은 run() 메소드입니다.

 

2. TestCase 수준의 run() 실행 흐름

JUnit3 스타일의 단일 테스트 실행 구조를 통해 run() 흐름을 이해해보겠습니다.

내부 실행 흐름(개념)

  1. setUp() 실행
  2. 테스트 메소드 실행
  3. 결과(성공/실패) 기록
  4. tearDown() 실행

예제 코드(JUnit3 스타일)

public class MyTest extends TestCase {

    @Override
    protected void setUp() {
        System.out.println("테스트 준비");
    }

    public void testAdd() {
        assertEquals(5, 2 + 3);
    }

    @Override
    protected void tearDown() {
        System.out.println("테스트 정리");
    }
}

이 테스트가 실행되면 내부적으로 다음 흐름을 거칩니다.

setUp() → testAdd() → tearDown() → 결과 반환

즉, run() 메소드는 이 전체 흐름을 감싸서 조율하는 역할을 합니다.

 

3. TestSuite 수준의 run() 실행 흐름

여러 테스트 클래스를 묶어 실행하는 경우도 run()이 처리합니다.

흐름 구조

  1. Suite 초기화
  2. 포함된 테스트들을 순서대로 run() 호출
  3. 전체 결과 집계

예제 코드

TestSuite suite = new TestSuite();
suite.addTestSuite(UserTest.class);
suite.addTestSuite(OrderTest.class);

Result result = new JUnitCore().run(suite);

여기서 JUnitCore.run()은 내부적으로 다음을 수행합니다.

UserTest.run() → OrderTest.run() → 결과 집계

즉, run()은 개별 테스트뿐 아니라 스위트 레벨 실행도 관리합니다.

 

4. JUnitCore.run() – JUnit4의 실행 진입점

JUnit4에서는 JUnitCore가 러너 역할을 하며, 그 중심이 되는 메소드가 run()입니다.

실행 예제

import org.junit.runner.JUnitCore;
import org.junit.runner.Result;

public class RunTests {
    public static void main(String[] args) {
        Result result = JUnitCore.runClasses(UserTest.class, OrderTest.class);
        System.out.println("실패 수: " + result.getFailureCount());
    }
}

내부 흐름

  1. 테스트 클래스 로딩
  2. 리플렉션으로 테스트 메소드 탐색
  3. 각 테스트에 대해 Before → Test → After 실행
  4. 결과를 Result 객체로 반환

즉, run() 메소드는 테스트 실행의 엔트리 포인트이자 전체 제어자입니다.

 

5. JUnit5의 run() 개념은 어디로 갔을까?

JUnit5는 구조가 완전히 바뀌었기 때문에 run() 메소드를 직접 사용하지 않습니다.
하지만 내부 구조는 동일하게 다음과 같은 흐름으로 동작합니다.

  • Launcher가 테스트 디스커버리
  • Executor가 테스트 실행
  • 결과 리스너가 결과 수집

즉, 직접 run()을 호출하지 않아도, 내부적으로는 Launcher API가 run 역할을 수행하고 있습니다.

그래서 JUnit5에서도 테스트 흐름은 동일합니다.

BeforeAll → BeforeEach → Test → AfterEach → AfterAll → 결과 수집

결국 run()이라는 이름만 사라졌을 뿐, 역할은 완전히 유지됩니다.

 

6. 정리: run() 메소드가 중요한 이유

  1. 테스트 실행의 시작점이자 전체 흐름 제어자
  2. 단일 테스트, 스위트 테스트 모두 run()을 기반으로 실행
  3. 결과 생성(Result)과 실패 처리(Failure)를 담당
  4. JUnit 버전이 달라져도 개념적 역할은 동일

테스트가 어떻게 실행되는지 이해하면

  • Before/After 구조
  • 스위트 구성
  • 실행 순서 관리
    등을 자연스럽게 파악할 수 있습니다.

run() 메소드는 그 흐름을 가장 직관적으로 보여주는 핵심 개념입니다.

 

 

반응형
Comments