Spring Boot & 테스트 코드 작성 (1) - JUnit
테스트 코드
이제는 어딜가나 빼놓을 수 없는게 바로 테스트 코드이다.
이번엔 Spring Boot 와 함께 Gradle 환경에서 테스트 코드를 작성하고 결과를 확인해보도록 하자.
단위 테스트(Unit Test)
단위 테스트에 대한 개념은 대부분의 블로그에서 다루고 있기에 여기서는 단순한 개념만 얘기하도록 하겠다.
단위 테스트는 프로그램내의 함수나 객체들을 검사하여 코드 변경으로부터 자유롭게 개발 할 수 있도록 하는 절차이다.
단위 테스트의 각 테스트는 모두 독립적이여야 하며 하나의 테스트는 하나의 시나리오만을 검사한다.
단위 테스트는 버그를 찾기 위한 것이 아닌 개별 단위의 적합성 혹은 정확성을 확인하기 위한 방법이다.
JUnit
단위 테스트 Framework 중 하나로 JAVA 의 단위 테스트 프레임워크 표준이다.
JUnit 은 xUnit 계열의 단위 테스팅 프레임워크로 각 언어별 다음과 같은 xUnit 들이 있다.
xUnit Name | Lang | 관련 사이트 |
---|---|---|
CUnit | C | http://cunit.sourceforge.net/ |
CppUnit | C++ | https://sourceforge.net/projects/cppunit/ |
PHPUnit | PHP | https://phpunit.de/ |
PyUnit | Python | http://pyunit.sourceforge.net/ |
JUnit | Java | http://junit.org/ |
많이쓰이는 버전은 JUnit4 와 5 버전이다.
스프링부트 프레임워크에 포함되어 있을 정도로 많이 쓰이고 있다.
단정문으로 테스트 케이스의 수행 결과를 판별한다.
ex) assertEquals(예상 값, 실제 값)
어노테이션으로 간결하게 적용할 수 있다.
결과는 성공(녹색), 실패(붉은색) 중 하나로 표시된다.
테스트 러너
테스트를 실행하여 그 결과를 보여주는 것이 테스트 러너이다.
JUnit 사용
JUnit assert관련 Method 는 아래와 같이 있다.
Method | 내용 |
---|---|
assertArrayEquals(a,b) | 배열 a와b가 일치함을 확인한다. |
assertEquals(a,b) | 객체 a와b의 값이 같은지 확인한다. |
assertSame(a,b) | 객체 a와b가 같은 객체임을 확인한다. |
assertTrue(a) | a가 참인지 확인한다. |
assertFalse(a) | a가 거짓인기 확인한다. |
assertNotNull(a) | a객체가 Null이 아님을 확인한다. |
JUnit 설치
앞선 Spring Boot 예제를 이용하여 Test 를 진행한다.
Spring Boot 예제는 [이곳] 에서 볼 수 있다.
JUnit 설치를 위해서 의존성(dependency)를 추가해 주어야 하는데 Spring Boot Framework에 포함되어있어 다음과 같이 불러올 수 있다.
중요한 점은 Spring Boot 버전에 따라 JUnit 버전이 달라지는데 Gradle 에서 버그가 있다고 한다.
혹시 ClassNotFoundException: org.junit.platform.engine.EngineDiscoveryListener
에러가 발생한다면 아래 블로그를 참고 바란다.
결론은 JUnit platform launcher 버전 문제인데 Spring boot 프레임워크는 최신버전이지만 Launcher 버전이 구버전이여서 다음과 같이 최신버전 받도록 의존성을 추가해주면 해결된다. (1.6 이상 버전을 직접 추가해 주어도 된다)
...
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
testImplementation 'org.junit.platform:junit-platform-launcher'
}
...
이후 어노테이션을 이용하여 JUnit 의 기능들을 사용하면 된다.
테스트 실행은 VSCode 의 경우 Test 탭에서 실행할 수 있으며
CodeLens 기능을 이용해 소스에서 직접 실행도 가능하다.
Test 탭은 IDE 좌측 시약 아이콘을 누르면 나타나고
CodeLens는 소스코드에 바로 나와있어 클릭만 하면된다.
이렇게 테스트를 실행하면 하단에 DEBUG CONSOLE 을 통해 테스트 실행 내역을 확인할 수 있다.
Test 예제
실제 JUnit 을 사용해보자
JUnit 을 테스트 하기위한 제품 할인율 계산용 class를 만들 것이다.
제품 객체는 가격과 할인율을 가지고 원가와 할인가격을 알려준다.
// (Product.java)
package com.example3.demo.entity;
public class Product {
int prodPrice;
int prodSaleRate;
public int getProdPrice() {
return this.prodPrice;
}
public void setProdPrice(int prodPrice) {
this.prodPrice = prodPrice;
}
public int getProdSaleRate() {
return this.prodSaleRate;
}
public void setProdSaleRate(int prodSaleRate) {
if (prodSaleRate > 100) prodSaleRate = 100;
if (prodSaleRate < 0) prodSaleRate = 0;
this.prodSaleRate = prodSaleRate;
}
public int getProdSalePrice() {
return (int)(this.prodPrice - this.prodPrice * (0.01 * this.prodSaleRate));
}
}
이제 할인율을 테스트 하기위한 테스트 객체를 생성한다.
우리가 사용하는 JUnit 은 5버전이기때문에 @BeforeEach
를 사용했다.
(JUnit4 에서는 @Before
사용)
// (ProductTest.java)
package com.example3.demo.entity;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
public class ProductTest {
Product prod = new Product();
int price = 4500;
int saleRate = 30;
@BeforeEach
public void setup() {
prod.setProdPrice(price);
prod.setProdSaleRate(saleRate);
}
@Test
@DisplayName("Orininal product price")
public void originalPrice() throws Exception {
assertTrue(
price == prod.getProdPrice(), "This is a original price");
}
@Test
public void failPrice() throws Exception {
assertTrue(
price == prod.getProdSalePrice(), "It will be fail");
}
@Test
public void salePrice() throws Exception {
assertTrue(
(int) price - price * (0.01 * saleRate)
== prod.getProdSalePrice(), "This is a sale price");
}
}
이제 Test를 돌리면 다음과 같은 결과가 나온다.
총 세개의 테스트가 나오는데 앞서 미리 설정한대로 failPrice
, originalPrice
, salePrice
가 실행되었고
@DisplayName
어노테이션을 통해 originalPrice
는 Original product price
로 이름이 변경되었다.
이번엔 실패 내역을 살펴보자
assertX 메소드에 미리 넣어둔 It will be fail
이라는 메세지와 함께 true 가 아닌 false 가 반환되었다고 나온다.
이번엔 assertEquals 메소드를 통해 결과를 다시 확인해보자
다음과같이 Equals 메소드로 변경한 후 CodeLens를 이용해 아래 테스트만 실행하면
@Test
public void failPrice() throws Exception {
assertEquals(
price,
prod.getProdSalePrice(),
"It will be fail");
}
다음과 같은 메세지로 바뀌어 나온다.
지금까지 기본적인 JUnit 의 사용법과 디버깅 방법에 대해서 설명했다.
조금더 합리적인 테스트 코드 작성하기 위해서 단위 테스트와 TDD 관련 내용을 더 찾아보길 추천한다.
2부에서는 Mock 객체를 이용한 Spring Boot 에서의 테스트 방법에 대해 알아보도록 하자
엮인글
Spring Boot & 테스트 코드 작성 (1) - JUnit
Spring Boot & 테스트 코드 작성 (2) - Mock, Mockito
Spring Boot & 테스트 코드 작성 (3) - MockMvc
Spring Boot & Rest API (1)
Spring Boot & Rest API (2) - JPA, MySQL
참고
https://www.slideshare.net/gyumee/ss-90206560
https://martinfowler.com/bliki/UnitTest.html
https://code.visualstudio.com/docs/java/java-testing
'java' 카테고리의 다른 글
[Spring] Spring Boot & Rest API (1) (0) | 2020.05.14 |
---|---|
[Spring] Spring Boot & 테스트 코드 작성 (3) - MockMvc (0) | 2020.05.13 |
[Spring] Spring Boot & 테스트 코드 작성 (2) - Mock, Mockito (1) | 2020.05.11 |
[Spring] VSCode & Spring Boot (0) | 2020.05.08 |
[Java] String, StringBuffer, StringBuilder (0) | 2017.07.17 |