ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Assertion API
    테스트/Junit5 2021. 1. 28. 15:09

     

    Assertion API는 테스를 실행할 때, 여러 상황을 검사하기 위해 사용된다.

    Assertion을 사용하기 위해선 다음과 같이 import문을 추가해야 한다.

    import static org.junit.jupiter.api.Assertions.*;

    자주 사용되는 메서드

    assertEquals(기대값, 실제값, 메세지) 실제 값이 기대한 값과 같은지 확인한다. 거짓인 경우 메세지를 출력한다.
    assertNotNull(값) 값이 null이 아닌지 확인한다.
    assertTrue(boolean) 값이 참인지 확인한다.
    assertAll(executables) 매개변수를 모두 확인하는 구문
    assertThrows(expectedType, executable) 예외 발생 확인
    assertTimeout(duration, excutable) 특정 시간 안에 실행이 완료되는지 확인

    출처 : www.inflearn.com/course/the-java-application-test

     

    더 자바, 애플리케이션을 테스트하는 다양한 방법 - 인프런

    자바 프로그래밍 언어를 사용하고 있거나 공부하고 있는 학생 또는 개발자라면 반드시 알아야 하는 애플리케이션을 테스트하는 다양한 방법을 학습합니다. 초급 프로그래밍 언어 프레임워크

    www.inflearn.com

     


    예제코드1. assertEqual 실습

     

    Study 클레스 객체를 생성하고, getStatus()메소드를 통해 상태값을 반환해 enum에 존재하는 값과 같은지 확인해보는 테스트 코드를 작성해보자.

    package com.example.junittest;
    
    import org.junit.jupiter.api.*;
    
    import static org.junit.jupiter.api.Assertions.*;
    @DisplayName("스터디 클레스")
    class StudyTest {
    
        @Test
        @DisplayName("스터디 만들기☺️")
        void create_new_study_test() {
            Study study = new Study();
            assertNotNull(study);
            assertEquals(Studystatus.DRAFT,study.getStatus());
        }
    }
    public enum Studystatus {
        DRAFT, STARTED, ENDED
    }
    
    public class Study {
        private Studystatus status;
        public Studystatus getStatus() {
            return this.status;
        }
    }

    [결과] 당연히 같지 않다.

    이때 테스트를 실패하면 메세지를 출력 할 수 있다.

    void create_new_study_test() {
            Study study = new Study();
            assertNotNull(study);
            assertEquals(Studystatus.DRAFT,study.getStatus(),"같지 않습니다.");
        }

     

    이제 getStatus메서드에서 기대값을 반환해보자.

     

      private Studystatus status = Studystatus.DRAFT;
        public Studystatus getStatus() {
            return this.status;
        }

    정상이다.

     

    ※message 작성시 효율적인 측면에서 고려할 점

    assertEquals는 String을 매개변수로 받으면, 비교 값들이 같던 같지 않던 문자열을 계산하게 된다. 

    하지만 supplier 객체를 이용해 작성해주면 실패 했을때만 문자열을 계산해준다.

    void create_new_study_test() {
            Study study = new Study();
            assertNotNull(study);
            assertEquals(Studystatus.DRAFT, study.getStatus(), new Supplier<String>() {
                @Override
                public String get() {
                    return "실패했습니다.";
                }
            });

    람다식으로 작성하면 다음과 같다.

        void create_new_study_test() {
            Study study = new Study();
            assertNotNull(study);
            assertEquals(Studystatus.DRAFT, study.getStatus(), ()->"실패했습니다." );
        }

    예제코드2. 테스트 실패일 경우 다음 테스트 실행여부

    public class Study {
        private Studystatus status ;
        public Studystatus getStatus() {
            return this.status;
        }
    }
    public enum Studystatus {
        DRAFT, STARTED, ENDED
    }
    
    import org.junit.jupiter.api.*;
    
    import java.util.function.Supplier;
    
    import static org.junit.jupiter.api.Assertions.*;
    @DisplayName("스터디 클레스")
    class StudyTest {
    
        @Test
        @DisplayName("스터디 만들기☺️")
        void create_new_study_test() {
            Study study = new Study();
            assertNotNull(study);
            assertEquals(Studystatus.DRAFT, study.getStatus(), ()->"실패했습니다." );
            assertTrue(1<2,()->"asserTrue 실패입니다.");
        }
    }

    만약 assert조건 문이 틀린 케이스인 경우, 다음 assert문은 실행되지 않는다. -> 소스 코드에서 assertTrue 테스트를 실행하지 않는다.

    즉, 위에 소스코드에 assertEquals값이 같다는것을 고쳐주어야 asserTrue테스트를 실시한다.

     


    예제코드3. assertEquals 조건 만족시키는 코드

    public class Study {
        private Studystatus status  = Studystatus.DRAFT;
        public Studystatus getStatus() {
            return this.status;
        }
    }
    
    import static org.junit.jupiter.api.Assertions.*;
    @DisplayName("스터디 클레스")
    class StudyTest {
    
        @Test
        @DisplayName("스터디 만들기☺️")
        void create_new_study_test() {
            Study study = new Study();
            assertNotNull(study);
            assertEquals(Studystatus.DRAFT, study.getStatus(), ()->"실패했습니다." );
            assertTrue(1>2,()->"asserTrue 실패입니다.");
        }
    }

     

    asserTrue 테스트를 실행 할 수 있다. -> 하지만 애초에 이렇게 assertation이 맞을 경우에 다음 테스트를 실시하는 것 말고 다른 방법이 존재한다. -> 연간된 테스트를 한 번에 실시하는 방법 -> assertAll()


    예제코드4. assertAll

    assertAll은 연관된 테스트를 한 번에 실시하는 메서드이다.

    각 테스트는 람다식을 활용하여 작성한다. 예를 들면 다음과 같다.

    public class Study {
        private Studystatus status  = Studystatus.DRAFT;
        public Studystatus getStatus() {
            return this.status;
        }
    }
    @DisplayName("스터디 클레스")
    class StudyTest {
    
        @Test
        @DisplayName("스터디 만들기☺️")
        void create_new_study_test() {
            Study study = new Study();
            assertAll(
                    () -> assertNotNull(study),
                    () -> assertEquals(Studystatus.ENDED, study.getStatus(),
                            () -> "asertEquals 실패"),
                    () -> assertTrue(study.getStatus() == Studystatus.ENDED,
                            () -> "asserTrue 실패")
            );
        }
    }


    예제코드5. assertThrows

    public class Study {
        private int init_value;
        private Studystatus status  = Studystatus.DRAFT;
        public Study(int limlit) {
            if(limlit < 0){
                throw new IllegalArgumentException("음수는 올 수 없어요.");
            }
            this.init_value = limlit;
        }
    @DisplayName("스터디 클레스")
    class StudyTest {
    
        @Test
        @DisplayName("스터디 만들기☺️")
        void create_new_study_test() {
            assertThrows(IllegalArgumentException.class , ()->new Study(-10));
        }
    }

    assertThrows는 예상되는 예외처리를 확인하는 목적으로 사용되며 첫 번째 매개 변수에는 예외발생 타입 클레스를,  그 다음은 실행할 코드를 람다식으로 작성한다.


    예제코드6. assertTimeout

    package com.example.junittest;
    
    import org.junit.jupiter.api.*;
    import java.time.Duration;
    
    import static org.junit.jupiter.api.Assertions.*;
    
    @DisplayName("스터디 클레스")
    class StudyTest {
    
        @Test
        @DisplayName("스터디 만들기☺️")
        void create_new_study_test() {
            assertTimeout(Duration.ofMillis(100), () -> {
                        new Study(10);
                        Thread.sleep(300);
                    }
            );
    
        }
    }

    Duration 클레스의 메서드를 사용해 기대하는 시간과 실제 테스트할 코드를 사용한다.

    주의할 점은 예제코드6번 코드와 같이 테스트를 실시했을때 걸리는 시간이 전체 테스트시간에 영향을 끼치기 때문에 이 부분을 고려해야한다. 만약, 예측한 시간 근처값이 아닌 시간이 걸릴경우, 해당 테스트를 실패로 끝나게 해주는 메서드가 있는데 바로 assertTimeoutPreemptively이다. 이 메서드 또한 주의할 점이 있는데 바로 Spring에서 트렌젝션 전략을 사용할때 별도의 로컬 쓰레드를 사용하는데 이 부분과 assertTimeoutPreemotively가 사용하는 스레드가 달라 트렌젝션 전략이 제대로 수행되지 않을 수도 있다는 점이다.(롤백을 했음에도 결과가 적용된다는 현상같은 위험한 사항)

    @DisplayName("스터디 클레스")
    class StudyTest {
    
        @Test
        @DisplayName("스터디 만들기☺️")
        void create_new_study_test() {
            assertTimeoutPreemptively(Duration.ofMillis(100), () -> {
                        new Study(10);
                        Thread.sleep(300);
                    }
            );
    
        }
    }

    '테스트 > Junit5' 카테고리의 다른 글

    태깅과 필터링  (0) 2021.02.02
    조건에 따라 테스트 실행하기  (0) 2021.02.02
    테스트 이름 표시하기  (0) 2021.01.28
    Junit 기본 어노테이션  (0) 2021.01.27
    Junit5 시작하기  (0) 2021.01.27
Designed by Tistory.