DevJong12

[JUnit] JUnit을 활용한 다양한 테스트방법 본문

Java,Spring/Java

[JUnit] JUnit을 활용한 다양한 테스트방법

Jong12 2024. 9. 26. 15:32
728x90

목차

     

    글을 작성하기에 앞서서... 이 JUni이란게 뭔지에 대해서 앞의 아티클에 설명을 해놓았다. 

    해당글을 먼저 읽으면 좋을 듯하여 링크를 남겨놓는다..

     

    https://devjong12.tistory.com/123

     

    [JUnit] JUnit 이란?

    목차 1️⃣ 글을 작성하기에 앞서..사실 글을 적을까 말까 고민했는데, 회사에서 JUnit에 대해서 교육을 하게 될 계기가 생겨서 작성을 하다 보니 너무 많은 지식을 망각했다는 것을 깨닫게 되었

    devjong12.tistory.com

     

    추가적으로 모든 코드는 아래의 Repository에서 확인이 가능합니다.

    https://github.com/donsonioc2010/my-junit-example

     

    GitHub - donsonioc2010/my-junit-example

    Contribute to donsonioc2010/my-junit-example development by creating an account on GitHub.

    github.com

     

    1️⃣ JUnit, 유닛테스트를 위한게 아니야?

    맞다. 기본적으로는 유닛테스트에 목표를 두고 있기 때문에 테스트의 주된 목적은 제목그대로 유닛테스트를 위한 도구다.

     

    하지만 필자의 경우에는 Java를 베이스로 해서 Spring을 사용하는 Java + Spring(일명 자프링) 생태계를 활용한 개발을 하고 있다.

    그러다 보니 특정 외부 API에 대한 타임체크나, DB에 대한 세션변경 등등의 다양한 설정의 테스트 또는 특정환경에서만의 테스트등이 필요할 수도 있다. 

     

    그런 특정환경 또는 특정 설정에 대한 테스트를 지원하고 있으며, 이 아티클은 어떠한 상황에서 활용이 가능한지를 기록해 보고자 한다.


    2️⃣ Unit Test

    JUnit이 존재하는 기본적인 이유인 유닛테스트부터 방법에 대해서 코드로 기록해보고자 합니다.

    유닛테스트는 간단하게 메소드의 기능에 대한 테스트를 하는 것입니다.

     

    테스트타겟 코드는 간단한 계산 기능으로, 아래의 코드를 참조하시기 바랍니다.

     

    위와 같은 코드를 테스트를 해보고자 합니다. 간단하게 2개의 숫자를 더하고 더한 결과를 반환하는 코드입니다.

     

     

    위의 코드는 이제 Calculator의 add메소드에 대한 테스트를 진행하는 테스트케이스 입니다.

     

    Calculator객체를 생성하고, 숫자 두개를 add메소드에 제공하여 결과물을 받고, 이 받은 결과물이 개발자가 의도한 결과와 동일하게 작동하는 가를 확인하는 검증단계로 흐름이 이뤄집니다.

     

    이처럼 단위테스트 자체는 간단하게 제작이 가능합니다.

     

    단 위와같이 간단한 경우는 간단한 로직뿐이고... 실제 작업을 하면서 저런 케이스는 많이 없겠지만요 🤣


    3️⃣ 다양한 OS환경에서의 테스트

    저도 자료들을 준비하면서 알게 된 방법중 하나입니다.

    간단하게 Annotation만 추가하면 Jupiter에서는 OS별로 테스트를 실행할 수 있도록 환경을 제공해 주고 있습니다.

     

    어노테이션은 @EnableOnOSorg.junit.jupiter.api.condition패키지에 해당 어노테이션이 존재하고 있습니다.

    해당 어노테이션은 아래처럼 이뤄져 있으며, 클래스 또는 메소드에 선언이 가능합니다.

    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @ExtendWith({EnabledOnOsCondition.class})
    @API(
        status = Status.STABLE,
        since = "5.1"
    )
    public @interface EnabledOnOs {
        OS[] value() default {};
    
        @API(
            status = Status.STABLE,
            since = "5.9"
        )
        String[] architectures() default {};
    
        @API(
            status = Status.STABLE,
            since = "5.7"
        )
        String disabledReason() default "";
    }

     

    실제 사용 방법은 아래의 코드를 보면 직관적으로 확인이 가능합니다.

     

    필자의 경우 메소드에 모든 케이스를 기록하였으나, 클래스에 기록할 경우 전체 메소드에 동일하게 적용 됩니다.

     

    위의 케이스를 실행하게 되면, 필자는 Mac을 사용하기 떄문에 Mac의 환경만 테스트가 진행됩니다.

     

     

    테스트를 구현해 보면서 현재 컨테이너, 리눅스기반의 자프링 개발이 아닌 특정 어플리케이션 같은 부분들 즉 OS를 고려한 개발을 하게 될 경우에 유용한 테스트 방식이라고 생각을 할 수 있었습니다.


    4️⃣ 반복테스트

    여러번 동일한 테스트가 필요한 경우 사용할 수 있는 RepeatedTest입니다.

    코드를 보면 바로 이해가 가능합니다.

    위와 같이 명시가 가능하며, @RepeatedTest어노테이션을 통하여 테스트가 가능합니다.

    DisplayName은 제가 수정을 안했으나, 실제 10회 테스트를 하며 반복테스트 하위로 10개의 테스트가 @RepeatedTest의 name Format에 맞게 표시 됩니다.

     

    아래의 결과처럼요.

     

    하지만, 이런 단순 반복테스트라면 저는 부하테스트를 할 것 같습니다. 성능을 확인해야 하는 경우도 많기 때문에요.


    5️⃣ 가정기반 테스트

    AssumptionsTest라고 하며, 특정 조건이 만족해야 테스트를 진행하도록 할 때, 사용하는 테스트입니다.

    org.junit.jupiter.apiAssumptions를 사용해서 조건을 만족시키는 경우 테스트를 진행합니다. 간단한 예제는 아래 코드를 확인 가능합니다.

     

    위의 코드처럼 최초에 Property를 부여하고, 해당 값이 Test인경우, Test가 아닌 경우로 테스트 케이스를 진행합니다.

     

    실제 그러면 실행이 되어야 하는 테스트케이스는 두건이 됩니다. 또한, 아래의 이미지처럼 

     

    위처럼 특정 Value나 상황이 필요한 경우에만 Test를 진행하게 하는법이 필요하면 재고해 보면 좋을 듯 합니다.


    6️⃣ 타임아웃 테스트

    특정 시간내에 기능이 실행되어야 하는 경우 테스트를 통과하게 하는 것 또한 가능합니다.

     

    방법은 크게 두가지로, @Timeout어노테이션을 사용하거나 Jupiter의 Assertions의 assertTimeout통해 검증이 가능하며, 샘플코드는 아래와 같습니다.

     

    위처럼 assertTimeout의 경우에는 Duration을 인자로 받아, 특정 로직이 실행시 테스트시간의 검증이 가능합니다.

     

    반면에 @Timeout어노테이션의 경우에는 희망하는 시간, 시간의 단위를 기록하여 로직의 검증이 가능합니다.

    만약 시간의 단위를 기록하지 않으면 기본적으로 초단위로 지정이 되며, 실제 외부 API를 검증 테스트해야 하는 경우 또는 MSA환경에서 API콜을 통한 테스팅이 필요한 경우 유용하지 않을까 넌지시 생각이 들었던 방법입니다.


    7️⃣ 글을 마치며..

    사실 필자 역시도 유닛테스트를 제외하고 거의 하고 있지는 않습니다만, 자주 활용이 가능할만한 것들도 많이 있다고 생각합니다.

    해당 챕터에서는 어떠한 방식의 테스트 종류가 있고, 어떻게 활용해 볼 수 있을까에 대한 주관만 가져가면 좋지 않을까 합니다.

     

    그 뒤에 자신에게 맞는 방법을 적용하는 것은 글을 읽는 독자들의 판단에 맡길 뿐이라고 저는 생각합니다.

     

    또한 해당 포스트에서는 다루지 않은 방법이 많이 존재하는데요, TestContainers를 통한 특정환경 테스트라든가, @Tag어노테이션을 바탕으로 특정 빌드환경에서 특정 테스트만 실행되도록 하는 환경등 방식은 많이 존재합니다. 아니면 문서를 자동화 하기 위한 SpringRestDocs등의 환경등에 대해서도 추가가 가능합니다. 

     

    해당 아티클에는 제기준에서 활용이 가능할만한 항목들에 대해서만 기록을 해뒀기 때문에, 다른 기능들에 대해 더 설명이 필요하면 Third Party에 대해서 알아보시길 바랍니다. 😀

     

    다음 글은 JUnit의 유닛테스트에서 자주 사용하는 Jupiter의 Assertions와 AssertJ의 Assertions에 대해 기록하고자 합니다.

     

    읽어주셔서 감사합니다.

     

    728x90
    Comments