AssertJ란?

AssertJ란 테스트 코드를 작성할 때 사용하며 많은 기능을 통해 유용한 오류 메시지를 제공하고 테스트 코드의 가독성을 향상시키는 Java 라이브러리입니다.

Junit을 사용할 때 AssertJ를 통해 좀 더 가독성을 높이고 쉽게 이해할 수 있으며, 오늘 이 글에서는 적용 방법과 간단한 사용 예제 몇개를 다뤄보겠습니다.

 

우선 mvnrepository의 해당 링크를 통해 AssertJ를 검색합니다.

https://mvnrepository.com/

이후 사진에 보이는 AssertJ Core에 들어가 사용할 버젼을 클릭하면, 각 빌드 툴에 따른 적용 소스가 나와있습니다. 저는 gradle용을 가져가겠습니다.

버젼 선택
빌드 툴에 따른 선택지

자신에게 맞는 빌드 툴을 선택하시면 나오는 내용을 모두 복사해도 상관없으나, 사실상 적용하는 부분은 빨간 줄이 쳐져있는 부분이기 때문에 저는 빨간줄 부분만 복사해서 넣겠습니다.

build.gradle에 삽입한 장면

위 사진처럼 적용 후 gradle을 업데이트하면 라이브러리에 AssertJ가 포함됩니다. 그러면 AssertJ를 사용할 준비를 마친 것입니다.

라이브러리에 AssertJ가 포함됬습니다.

이제 테스트 코드에서 사용해보겠습니다.

우선 테스트 클래스에 AssertJ를 임포트할때, 다음 사진과 같이 Import해줍니다.

import문

이러면 이제 모든 Assertions아래의 메서드를 사용할 수 있습니다.

우선 간단한 예제를 보겠습니다

예제 1

AssertJ 공식 홈페이지 : AssertJ - 유창한 어설션 자바 라이브러리 에 나와있는 예제입니다. AssertJ는 인자에 객체를 넣은 후 .메소드를 통해 필요한 조건을 점검합니다.

- isNotNull() : 값이 Null이 아닌지

- startWith("The") : The로 시작하는 값인지

- contains("Lord") : 값에 Lord라는 값이 포함되어있는지

- endsWith("Rings") : Rings라는 값으로 끝나는지

이처럼 The Lord of the Rings라는 값이 위 네 가지 조건에 부합하는지 점검하는 테스트라고 보시면 되겠습니다.

 

다음은 어설션이 실패하는 예시입니다.

실패 예시

우선 이름은 Frodo, 나이는 33살인 객체 Frodo를 선언하고, 그 객체의 나이를 가져왔습니다.

as 메소드는 해당 assert문에 이름을 붙이는 메서드입니다. 마지막에 다루겠지만 이 메서드는 항상 다른 조건부메서드보다 앞에 존재해야합니다.

그리고 isEqualTo메소드를 통해 frodo객체 안의 나이 요소가 100과 동일한지 확인하고 있습니다. 하지만 위에서 33으로 값을 초기화 했기때문에 아래와 같이 에러가 발생합니다.

 

에러 발생

보시면 as메서드로 붙인 [check Frodo's age]부분이 먼저 출력되고, 100과 동일한지 테스트했으나 값이 33이었다는 구문이 에러로 발생합니다. 이렇게 보기 쉽게 에러가 발생하면 좀 더 테스트할 때 디버깅이 쉬워지겠죠?

 

이제 사용시 주의점입니다. 주의점은 크게 세 가지입니다.

1. 객체를 먼저 선언하고 조건부메서드를 걸어 둘것.

주의점 1

나쁘다부분을 보시면 객체와 동시에 테스트를 진행하였으며, 어떤 어썰트문도 사용되지 않음을 볼 수 있습니다. 이렇게 사용하면 안되고 아래와 같이 객체를 먼저 선언한 후 추가 메서드를 통해 조건을 걸거나, 위와 같이 사용한 뒤 isTrue를 추가로 사용하여 assert문을 작동하여야합니다.

 

2.as() 호출은 어설션 전에 해야한다!

위에 잠시 다뤘던 부분입니다. as메소드는 해당 어설션을 설명하는 부분으로, 가장 먼저사용하지 않으면 여러조건 중간에 조건이 맞지않아 중단시 호출되지않기때문에 항상 as메소드는 가장 먼저 사용해야합니다.

 

3. withFailMessage/overridingErrorMessage는 어설션 전에 호출해야한다.

이 부분도 as()의 호출 방식과 똑같은 이유입니다. 어설션 중간이나 마지막에 있을 시에는 에러가 발생하면 호출이 되지 않기 때문에 반드시 어설션 전에 사용합니다.

 

오늘은 간단하게 AssertJ를 적용하고 사용하는 예시를 다뤄보았습니다. 부족한 내용이 많았을텐데 봐주셔서 감사합니다.

 

참고 사이트 : AssertJ - 유창한 어설션 자바 라이브러리

'JAVA' 카테고리의 다른 글

[JAVA, JS]프로그램 변수란?  (0) 2023.07.05
[JAVA] JAVA와 객체지향 언어의 특징  (0) 2023.07.04
[TESTCode] AssertJ 빌드툴 추가 및 적용법  (0) 2023.07.03
Junit에 대하여  (0) 2023.04.24
[JAVA] 숫자열 분리하기  (0) 2023.01.31

Junit에 대하여

Junit이란건 현업에 계시는 분들은 많이 아시겠지만, 저같이 아직 현업에 뛰어들지 않았거나 혹은 학원 등에서 배우고 계시지만 사용하지 못하는분들이 많으실겁니다. 그래서 이 내용에 대한 것을 오늘 강의에 대한 내용과 합하여 알아보고자 합니다.

 

Junit이란?

Junit이란 JAVA를 위한 단위 테스트 도구이며 테스트를 System.out을 통하거나 log4j로 디버깅하여 만드는 것이 아니라, 코드의 국부적인 부분을 테스트해봄으로서 해당부분이 정상 작동되는지, 혹은 정상작동이 되지않고 어느곳이 문제인지를 알아낼 때 주로 사용하는 테스터 프레임워크입니다.

 

Junit을 사용할 때 얻을 수 있는 장점은 다음과 같습니다.

 

- @DisplayName 태그등을 이용하여 무슨내용을 테스트했는지 등 문서화 작업이 용이해집니다.

- 코드의 일정 부분을 테스트 함으로서 코드의 결함을 더 쉽게 발견할 수 있습니다.

- 코드를 리팩토링할 때 테스트 코드를 통하여 더 안정성을 확보할 수 있습니다.

 

지금부터 적용하는 방법과 그에대한 특징을 하나씩 자세히 설명드리겠습니다.

우선 제가 사용하는 IntelliJ에서는 JAVA프로젝트를 생성하면 기본적으로 적용이 되어있습니다.

라이브러리를 다운받아오는 build.gradle의 코드입니다.

보시면 위 사진에 Jnit과 관련된 testImplementation이 두개 들어가있습니다.

나머지 하나 assertJ는 Junit을 사용한 테스트코드의 가독성과 간결성을 위한 라이브러리로, 다음시간에 다시 다루겠습니다. 어쨌든 저 두개가 없다면 Junit과 관련된 라이브러리를 불러올 수 없으므로, 없으시다면 MVNrepository를 통하여 소스를 받아오시면 됩니다.

 

잘 적용이 되었다면 다음 사진과 같이 External Libraries에 Junit과 관련된 라이브러리들이 있는 것을 확인하실 수 있습니다.

External Libraries

 

 

 

본 프로그램과 테스트 디렉터리

이제 해당 프레임워크를 이용하려면 따로 파일을 만들어야합니다. 하지만 본 프로그램 디렉터리에 만들면 나중에 파일을 관리하기 힘들어지므로, 따로 만들도록합니다. eclipse와 intelliJ 모두 프로젝트 생성시 main과 test용 디렉터리를 구분하여 생성됩니다.

 

test디렉터리는 비어있지만 보통 테스트 클래스를 생성할 때에는 아래 사진과 같이 테스트할 클래스와 동일하게 패키지

경로를 잡아줍니다.

저는 강의에서 비밀번호 생성과정 검증에 대한 내용을 테스트했기 때문에, PasswordValidator클래스와 동일하게 패키지명을 생성했습니다.

테스트 클래스와 테스트할 클래스 경로비교

이제는 테스트할 차례입니다.

테스트할 메소드는 비밀번호가 정해진 범위에 적합한지 검증하는 메소드이며, 8자 이상 12자 이하가 아닐경우는 예외를 발생시키게되어있습니다.

테스트할 메서드

이에 대한 테스트 클래스를 생성했습니다.

테스트 클래스

보시면 어노테이션이 두개가 붙어있습니다.

@Test는 해당 메서드가 테스트 코드임을 나타냅니다. 해당 메서드는 실행되면 테스트 코드로서 작동됩니다.

@DisplayName은 테스트 클래스나 테스트 메서드에 대한 사용자 지정이름을 나타냅니다. 위 사진과 같이 테스트할 내용을 적어놓음으로서, 누가 보아도 무슨의도로 테스트를 하는 것인지 알 수 있게 문서화 작업을 하는 것입니다.

또한 위 사진에 있는 메서드 처럼 테스트할 클래스에서 하나의 메서드만 가져와 정상적인 실행을 하는지 테스트함으로서 결함이 있는 부분의 범위를 보다 좁히고, 편하게 찾을 수 있습니다.

마지막으로 리팩토링을 해당 테스트 코드에 적용시켜 먼저 제대로 작동되는지 테스트함으로서 원 코드와 관계없이 안정성 있는 리팩토링이 가능해집니다.

 

주석묘사

@Test 메서드가 테스트 메서드임을 나타냅니다. JUnit 4의 어노테이션과 달리, JUnit Jupiter의 테스트 확장은 자체 전용 어노테이션을 기반으로 작동하기 때문에 이 어노테이션은 어떠한 속성도 선언하지 않습니다. 이러한 메서드는 재정의되지 않는 한 상속됩니다.@Test
@ParameterizedTest 메서드가 매개 변수가 있는 테스트임을 나타냅니다. 이러한 메서드는 재정의되지 않는 한 상속됩니다.
@RepeatedTest 메서드가 반복 테스트에 대한 테스트 템플릿임을 나타냅니다. 이러한 메서드는 재정의되지 않는 한 상속됩니다.
@TestFactory 메서드가 동적 테스트를 위한 테스트 팩터리임을 나타냅니다. 이러한 메서드는 재정의되지 않는 한 상속됩니다.
@TestTemplate 메서드는 등록된 공급자가 반환한 호출 컨텍스트의 수에 따라 여러 번 호출되도록 설계된 테스트 사례의 템플릿임을 나타냅니다. 이러한 메서드는 재정의되지 않는 한 상속됩니다.
@TestClassOrder 어노테이션이 있는 테스트 클래스의 테스트 클래스에 대한 테스트 클래스 실행 순서를 구성하는 데 사용됩니다. 이러한 주석은 상속됩니다.@Nested
@TestMethodOrder 주석이 달린 테스트 클래스에 대한 테스트 메서드 실행 순서를 구성하는 데 사용됩니다. JUnit 4와 유사합니다. 이러한 주석은 상속됩니다.@FixMethodOrder
@TestInstance 주석이 추가된 테스트 클래스에 대한 테스트 인스턴스 수명 주기를 구성하는 데 사용됩니다. 이러한 주석은 상속됩니다.
@DisplayName 테스트 클래스 또는 테스트 메서드에 대한 사용자 지정 표시 이름을 선언합니다. 이러한 주석은 상속되지 않습니다.
@DisplayNameGeneration 테스트 클래스에 대한 사용자 지정 표시 이름 생성기를 선언합니다. 이러한 주석은 상속됩니다.
@BeforeEach 주석이 달린 메서드는 현재 클래스의  , , , 또는 메서드 앞에 실행되어야 함을 나타냅니다. JUnit 4와 유사합니다. 이러한 메소드는 재정의되거나 대체되지 않는 한 상속됩니다 (즉, Java의 가시성 규칙에 관계없이 서명에 의해서만 대체됨).@Test@RepeatedTest@ParameterizedTest@TestFactory@Before
@AfterEach 주석이 달린 메서드는 현재 클래스의  , , , 또는 메서드 다음에 실행되어야 함을 나타냅니다. JUnit 4와 유사합니다. 이러한 메소드는 재정의되거나 대체되지 않는 한 상속됩니다 (즉, Java의 가시성 규칙에 관계없이 서명에 의해서만 대체됨).@Test@RepeatedTest@ParameterizedTest@TestFactory@After
@BeforeAll 주석이 달린 메서드는 현재 클래스의 모든 , , , 및 메서드보다 먼저 실행되어야 함을 나타냅니다. JUnit 4와 유사합니다. 이러한 메소드는 숨겨지거나, 재정의되거나, 대체되지 않는 한(즉, Java의 가시성 규칙에 관계없이 서명에 의해서만 대체되지 않는 한) 상속되며, "클래스별" 테스트 인스턴스 수명 주기가 사용되지 않는 한 상속되어야 합니다.@Test@RepeatedTest@ParameterizedTest@TestFactory@BeforeClassstatic
@AfterAll 주석이 달린 메서드는 현재 클래스의 모든 , , , 및 메서드 후에 실행되어야 함을 나타냅니다. JUnit 4와 유사합니다. 이러한 메소드는 숨겨지거나, 재정의되거나, 대체되지 않는 한(즉, Java의 가시성 규칙에 관계없이 서명에 의해서만 대체되지 않는 한) 상속되며, "클래스별" 테스트 인스턴스 수명 주기가 사용되지 않는 한 상속되어야 합니다.@Test@RepeatedTest@ParameterizedTest@TestFactory@AfterClassstatic
@Nested 주석이 추가된 클래스가 비정적 중첩 테스트 클래스임을 나타냅니다. Java 8부터 Java 15까지, "클래스별" 테스트 인스턴스 수명 주기를 사용하지 않는 한 테스트 클래스에서 메서드를 직접 사용할 수 없습니다. Java 16부터는 테스트 인스턴스 수명 주기 모드를 사용하여 테스트 클래스에서와 같이 메소드를 선언할 수 있습니다. 이러한 주석은 상속되지 않습니다.@BeforeAll@AfterAll@Nested@BeforeAll@AfterAllstatic@Nested
@Tag 클래스 또는 메서드 수준에서 테스트를 필터링하기 위한 태그를 선언하는 데 사용됩니다. TestNG의 테스트 그룹 또는 JUnit 4의 범주와 유사합니다. 이러한 주석은 클래스 수준에서는 상속되지만 메서드 수준에서는 상속되지 않습니다.
@Disabled 테스트 클래스 또는 테스트 메서드를 비활성화하는 데 사용됩니다. JUnit 4와 유사합니다. 이러한 주석은 상속되지 않습니다.@Ignore
@Timeout 테스트, 테스트 팩토리, 테스트 템플릿 또는 라이프사이클 메서드의 실행이 지정된 기간을 초과하는 경우 해당 메서드에 실패하는 데 사용됩니다. 이러한 주석은 상속됩니다.
@ExtendWith 확장을 선언적으로 등록하는 데 사용됩니다. 이러한 주석은 상속됩니다.
@RegisterExtension 필드를 통해 프로그래밍 방식으로 확장을 등록하는 데 사용됩니다. 이러한 필드는 섀도우 처리되지 않는 한 상속됩니다.
@TempDir 라이프 사이클 방법 또는 테스트 방법에서 필드 주입 또는 매개 변수 주입을 통해 임시 디렉토리를 제공하는 데 사용됩니다. 패키지에 있습니다.org.junit.jupiter.api.io

이렇게 제가 작문한 것 말고도 수많은 Junit에 대한 어노테이션이 Junit의 문서에 나와있으며, 적용예시 역시 모두 나와있어 사용할 때 테스트해보시면 좋을 것 같습니다. 부족한내용이 있다면 지적 부탁드립니다. 감사합니다.

 

참고사이트 : JUnit 5 사용자 가이드

'JAVA' 카테고리의 다른 글

[JAVA, JS]프로그램 변수란?  (0) 2023.07.05
[JAVA] JAVA와 객체지향 언어의 특징  (0) 2023.07.04
[TESTCode] AssertJ 빌드툴 추가 및 적용법  (0) 2023.07.03
AssertJ에 대하여  (0) 2023.04.24
[JAVA] 숫자열 분리하기  (0) 2023.01.31

+ Recent posts