Language/Java

[우테코 프리코스] NsTest가 무엇

i-m-okay 2024. 10. 17. 13:06

우테코 프리코스를 수행하고 있다.

효과적인 테스트 코드 작성을 위해 기본적으로 제공된 테스트 코드 속 NsTest를 톺아보는 시간을 가져보도록 하겠다.

 

제공된 소스코드

class ApplicationTest extends NsTest {
    @Test
    void 커스텀_구분자_사용() {
        assertSimpleTest(() -> {
            run("//;\\n1");
            assertThat(output()).contains("결과 : 1");
        });
    }

    @Test
    void 예외_테스트() {
        assertSimpleTest(() ->
            assertThatThrownBy(() -> runException("-1,2,3"))
                .isInstanceOf(IllegalArgumentException.class)
        );
    }

    @Override
    public void runMain() {
        Application.main(new String[]{});
    }
}

위에 run()메서드로 파라미터 받는 법도 모르는 심각한 상태이다
하나씩 뜯어보자...~!

NsTest

NsTest는 우테코에서 제공해주는 테스트 라이브러리이다. 구글에 검색해보았을 때 공식 document가 없는 것도 그런 이유인 것 같다.

NsTest 톺아보기

  • PrintStream : 텍스트를 출력할 때 주로 쓰는 바이트 기반 스트림 추상 클래스이다.
  • OutputStream : 데이터를 바이트 단위로 출력하는 바이트 기반 스트림 추상 클래스이다.

init()과 printOutput()

  • @BeforeEach : 각 테스트를 시작하기 전에 해당 메서드를 실행해준다는 의미이다. 생성자의 개념처럼 보면 될 것 같다.
  • protected : 해당 클래스 내에서만 접근 가능, 상속된 클래스에서 재정의 불가

각 라인에 대한 설명은 주석으로 달아 놓았다.

public abstract class NsTest {
    private PrintStream standardOut;
    private OutputStream captor;

    public NsTest() {
    }

    // 테스트 시작 전 실행
    @BeforeEach
    protected final void init() {

        // this.standardOut을 System.out 으로 쓰고 싶다
        this.standardOut = System.out;

        // 동적인 바이트 배열 생성
        this.captor = new ByteArrayOutputStream();

        // this.captor에 저장된 값을 바이트 단위로 출력
        System.setOut(new PrintStream(this.captor));
    }

    // 테스트 후 실행 
    @AfterEach
    protected final void printOutput() {

        // System.out 을 this.stardardOut으로 설정
        System.setOut(this.standardOut);

        // this.output()의 반환 값을 출력
        System.out.println(this.output());
    }

command()

run 함수에서 사용하고 있어서 command메서드에 대해 먼저 알아보자.

    private void command(String... args) {

        // 받은 문자열을 줄바꿈 문자를 넣어 연결 -> 바이트 배열로 변환하여 저장
        byte[] buf = String.join("\n", args).getBytes();

        // 시스템 표준 입출력을 ByteArrayInputStream으로 설정
        // => 이후 입력받는 것들은 바이트 배열로 처리할 수 있도록 함
        System.setIn(new ByteArrayInputStream(buf));
    }

output(), run(), runException()


    protected final String output() {
        // this.captor 를 문자열로 바꾸고 좌우 공백문자를 제거한 후 반환
        return this.captor.toString().trim();
    }

    protected final void run(String... args) {
        try {
            // 바이트 배열로 처리하도록 설정
            this.command(args);
            // 메인 테스트 코드를 실행
            this.runMain();
        } finally {
            // 예외발생과 상관없이 Scanner 할당한 공간 release
            Console.close();
        }

    }

    // 예외처리
    protected final void runException(String... args) {
        // run 메서드 실행 시 예외를 만나면
        try {
            this.run(args);
        } catch (NoSuchElementException var3) {
            // NoSuchElementException 발생시키기
        }

    }



    protected abstract void runMain();
}

여기까지 우테코에서 제공하는 코드 속 test 파일을 살펴보는 시간을 가졌다.
생각보다 코드가 복잡하지 않고 단순해서 놀랐다.

왜 바이트 배열로 읽고 쓰나?

결과적으론 바이트 배열로 읽고 쓰고자 구현한 것으로 보이는데, 그 이유도 궁금해서 검색해보았다.

메모리에서 바이트 배열로 데이터를 다루는 것은 디스크나 네트워크에서의 속도보다 훨씬 빠르다고 한다. 바이트 배열로 모든 종류의 데이터를 저장할 수 있다는 점, 메모리 내에 데이터를 모아 한 번에 파일이나 다른 곳으로 보낼 수 있다는 점 등을 장점으로 꼽을 수 있을 것 같다.

 

소감 ) 막막함에서 한 줄기 빛으로

run을 통해서 어떻게 입력을 받겠다는거야? 라고 생각했던 나...
단순하지만 명확한 코드를 통해 내가 정말 아무것도 모른다는 것을 깨달았다.

막막했지만 어차피 물러설 곳은 없다는 생각에 나의 무지를 정면으로 마주하고 알아가는 과정을 게시글로 작성했다.

글자로 적어보려고 하는 과정에서 개념에 대해 추상적으로만 알고 있었다는 것을 깨닫고, 더 구체적으로 생각해보게 되었다.
이래서 정리가 참 중요하다.

 

다음 시간에는 기본으로 제공하는 Console 클래스도 알아보는 시간을 가져야겠다.

참고

Seongwon97
Update Test코드에 있는 NsTest & Assertion 분석.md