내가 있던 SI 프로젝트는 규모가 너무 커서 JUnit을 활용한 단위 테스트를 적용할 수 없었다.
그래서 난 JUnit을 사용해본적이 없다. 대부분 Logger.debug를 이용하여 파라미터만 콘솔에 출력했다.
JUnit을 활용한 테스트 코드 작성이 목표였기 때문에 관련 내용을 정리해보고자 한다.
1. JUnit이란?
자바용 단위 테스트 도구이다.
2. 단위테스트(Unit Test)란?
- 소스코드의 특정 모듈이 의도된 대로 정확히 작동하는지 검증하는 절차
- 모든 함수와 메소드에 대한 테스트 케이스(Test case)를 작성하는 절차
3. JUnit 특징
- @Test 메소드가 호출할 때마다 새로운 인스턴스를 생성하여 독립적인 테스트가 이루어지게 함
- 단정(assert)메소드로 테스트 케이스의 수행 결과를 판별할 수 있음.
- 패턴(given/when/then)
given (준비) : 어떤 데이터가 준비됐을 때
when (실행) : 어떤 메소드를 실행하면
then (검증) : 어떤 결과가 나와야 한다.
4. Assert클래스 정리
assertArrayEquals(a, b) : 배열 a, b가 일치함을 확인한다.
assertEquals(a, b) : 객체 a와 b가 같은 값을 가지는지 확인한다.
assertEquals(a, b, c) : 객체 a와 b가 값이 일치함을 확인한다. (a : 예상 값, b : 결괏값, c : 오차범위)
assertSame(a, b) : 객체 a와 b가 같은 객체임을 확인한다. (a와 b가 같은 객체를 참조하면 테스트 통과)
assertNotSame(a, b) : 객체 a와 b가 같은 객체를 참조하고 있지 않으면 통과
assertTrue(a) : a가 True인지 확인한다.
assertFalse(a) : a가 False인지 확인한다.
assertTrue(message, condition) : condition이 True면 message표시
assertNull(a) : 객체 a가 null인지 확인한다.
assertNotNull(a) : 객체 a가 null이 아닌지 확인한다.
assertfail() : 테스트 실패 처리
5. 어노테이션
1. 테스트 메소드를 지정하기
@Test // @Test 어노테이션이 메소드 위에 선언되면 이 메소드는 테스트 대상 메소드임을 의미
public void testA() {
// TODO
}
2. 테스트 메소드 수행시간 지정하기
@Test(timeout=5000) // timeout을 지정 (단위 : 밀리 초) 5,000밀리 초를 넘기면 테스트 실패
public void testA() {
// TODO
}
3. 테스트 메소드 Exception 지정하기
@Test(expected=RuntimeException.class) // 이 테스트는 RuntimeException이 발생해야 테스트 성공
public void testA() {
// TODO
}
4. @BeforeClass, @AfterClass, @before, @After
@BeforeClass -> 테스트 클래스 테스트 시작시 1번만 호출
@Before -> 테스트 케이스 시작전 각각 호출
@After -> 테스트 케이스 종료시 각각 호출
@AfterClass -> 테스트 클래스 모든 테스트 종료시 1번만 호출
// 순서를 적어보자면
EX)
@BeforeClass
@Before
케이스1
@After
@before
케이스2
@After
@AfterClass
지금부터는 위의 정보를 바탕으로 어떤 클래스에 대해 테스트 코드를 작성해 볼 것이다.
TESTDOME이라는 코딩테스트 사이트에서 발췌한 문제이다.
https://www.testdome.com/questions/java/account-test/38495
Account 클래스
public class Account {
private double balance;
private double overdraftLimit;
public Account(double overdraftLimit) {
this.balance = 0;
this.overdraftLimit = overdraftLimit > 0 ? overdraftLimit : 0;
}
public boolean deposit(double amount) {
if(amount >= 0) {
this.balance += amount;
return true;
}
return false;
}
public boolean withdraw(double amount) {
if(this.balance - amount >= -this.overdraftLimit && amount >= 0) {
this.balance -= amount;
return true;
}
return false;
}
public double getBalance() {
return balance;
}
public double getOverdraftLimit() {
return overdraftLimit;
}
}
AccountTest 클래스 (실제 내가 구현해야하는 클래스)
import org.junit.Assert;
import org.junit.Test;
public class AccountTest {
private double epsilon = 1e-6;
@Test
public void accountCannotHaveNegativeOverdraftLimit() {
Account account = new Account(-20);
Assert.assertEquals(0d, account.getOverdraftLimit(), epsilon);
}
/* The deposit and withdraw methods will not accept negative numbers */
/* deposit, withdraw 메소드는 음수를 허용하지 않는다. */
/* 그래서 두 개의 메소드에 음수를 넣어 볼 것이다. */
@Test
public void negativeDeposit() { // deposit 메소드 테스트
// given
Account account = new Account(20);
// when
boolean result = account.deposit(-10); // 음수를 넣으면 return은 false이다.
// then
Assert.assertFalse(result); // assertFalse(result) fasle 이므로 통과.
}
@Test
public void negativeWithDraw() { // withdraw 메소드 테스트
// given
Account account = new Account(20);
// when
boolean result = account.withdraw(-10); // 음수를 넣으면 return은 false이다.
// then
Assert.assertFalse(result);// assertFalse(result) fasle 이므로 통과.
}
/* Account cannot overstep its overdraft limit. */
/* Account는 overdraftlimit을 초과할 수 없다. */
/* Account를 초과하는 수를 넣어볼 것이다. */
@Test
public void overstepWithdraw() {
// given
Account account = new Account(20); // 생성자에 의해 balance = 0, overdraftlimit = 20;
// when
boolean result = account.withdraw(30); // false를 리턴
// then
Assert.assertFalse(result); // assertFalse(result) false 이므로 통과.
}
/* The deposit and withdraw methods will deposit or withdraw the correct amount, respectively */
/* deposit, withdraw메소드가 각각 올바른 금액을 입출금 한다. */
/* getBalance() 메소드를 활용해 deposit, withdraw에 대해 assertEquals을 해본다 */
@Test
public void correctAmount() {
Account account = new Account(0);
account.deposit(20); // deposit(20) --> balance = 20
boolean result = account.withdraw(10); --> balance = 10
// 20을 deposit 하고 10을 withdraw 했으니 balance는 10
Assert.assertEquals(10, account.getBalance(), epsilon); // , assertEquals(10, account.getBalance()) true 이므로 통과
}
/* The withdraw and deposit methods return the correct results */
/* withdraw와 deposit 메소드는 올바른 결과를 반환한다. */
/* depsoit메소드와 withdraw가 true를 리턴하도록 유도해보자. */
@Test
public void correctDeposit() {
// given
Account account = new Account(0);
// when
boolean result = account.deposit(20); // true를 리턴
// then
Assert.assertTrue(result); // assertTrue(result) true 이므로 통과.
}
@Test
public void correctWithdraw() {
Account account = new Account(0);
account.deposit(20);
boolean result = account.withdraw(10); // true를 리턴
Assert.assertTrue(result); // assertTrue(result) true 이므로 통과.
}
}
이상 간단한 JUnit 사용법을 알아보았습니다만 찾아보니 JUnit 관련 내용은 더 많은게 있다....
그만 알아보자..
참고
https://beomseok95.tistory.com/302
https://in-the-garden.tistory.com/9
'공부 > Java' 카테고리의 다른 글
가변인자(varargs)와 오버로딩 (0) | 2022.06.12 |
---|---|
클래스 메소드(static 메소드)와 인스턴스 메소드 (0) | 2022.06.12 |
인스턴스 변수와 클래스 변수 (0) | 2022.06.12 |