1. JUnit이란?
어느 정도 개발이 진행되면 프로그램에 대한 단위 테스트는 반드시 수행해야 하는데, JUnit은 보이지 않고 숨겨진 단위 테스트를 끌어내어 정형화시켜 단위 테스트를 쉽게 해주는 테스트용 Framework다.
JUnit이 비록 유닛 테스트로 유명하긴 하지만 instrumentation testing 또한 완벽하게 지원해준다. 따라서, 이런 JUnit을 이용하여 UI테스트 도구인 Espresso testing library또한 구동된다.
JDK 1.4에서 추가된 assert...를 사용하여 Test를 진행 할 수있다.
JUnit은 테스트 결과를 단순한 텍스트로 남기는 것이 아니라 Test클래스로 남긴다.
따라서 개발자에게 테스트 방법 및 클래스의 History를 넘겨줄 수도 있다.
2. 특징
- 단위 테스트 Framework 중 하나
- 문자 혹은 GUI 기반으로 실행됨
- 단정문으로 테스트 케이스의 수행 결과를 판별함(assertEquals(예상 값, 실제 값))
- 어노테이션으로 간결하게 지원함
- 결과는 성공(녹색), 실패(붉은색) 중 하나로 표시
3. Android Studio에서 JUnit 사용 방법(기본)
우선 프로젝트를 하나 생성하면 프로젝트에 자동으로 1,2번 두개의 폴더도 생성된다.
1번 androidTest 파일이 Ui 테스트를 진행하는 파일들이 있는 곳이고
2번 test 파일이 Unit 테스트를 진행하는 파일들이 있는 곳이다.
4. 단정문(Assertion)
Assertion은 테스트를 할 때 예상되는 값을 체크하기위해 사용되는 메서드이다. 이는 직관적이므로 아래 내용을 보고 참고하자.
assertArrayEquals(a,b) : 배열 a와b가 일치함을 확인
assertEquals(a,b) : 객체 a와b의 값이 같은지 확인
assertSame(a,b) : 객체 a와b가 같은 객체임을 확인
assertTrue(a) : a가 참인지 확인
assertNotNull(a) : a객체가 null이 아님을 확인
이외에도 다양한 단정문이 존재한다.
http://junit.sourceforge.net/javadoc/org/junit/Assert.html
5. 어노테이션 활용하기
@BeforeClass, @Rule, @Before, @Test, @After, @AfterClass
다섯개의 annotation을 알아보고자 하고 실제로 클래스에서 이 순서가 어노테이션의 플로우다.
(1) 테스트 메소드 지정하기
@Test가 메소드 위에 선언되면 이 메소드는 테스트 대상 메소드임을 의미한다.
@Test는 JUnit framework에서 가장 중요한 annotation이다.
@Test는 테스트 케이스 메서드임을 표시하고 일반 메서드와 다름을 명시하는데 사용한다.
메서드가 @Test annotation을 사용하면 이러한 특정 메서드는 테스트 케이스로 간주되고 JUnit Runner에 의해 실행된다.
JUnit Runner는 Java 클래스 내부에서 사용가능한 JUnit test case를 찾아 실행하는데 사용되는 특수한 클래스이다.
아래 코드는 @Test annotation을 이용한 JUnit test case이다.
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class ComputationUnitTest {
@Test
public void multiply_isCorrect() {
Computation computation = new Computation();
assertEquals(4, computation.Multiply(2,2));
}
}
(2) 테스트 메소드 수행시간 제한하기
@Test(timeout=5000)를 메소드 위에 선언합니다. 시간단위는 밀리 초 입니다. 이 테스트 메소드가 결과를 반환하는데 5,000밀리 초를 넘긴다면 이 테스트는 실패하는 것이다.
@Test(timeout=5000) public void testSum() { } |
(3) 테스트 메소드 Exception 지정하기
@Test(expected=RuntimeException.class)가 메소드 위에 선언되면 이 테스트 메소드는 RuntimeException이 발생해야 테스트가 성공, 그렇지 않으면 실패하는 것이다.
@Test(expected=RuntimeException.class) public void testSum() { } |
(4) 초기화 및 해제
@Before
@Before annotation은 어떤 테스트 메서드를 실행하기 전에 호출되도록 하는 annotation이다.
아래 코드를 보면 알수있듯이, Computation 객체는 @Before annotation에서 생성된다.
즉, @Before은 @Test 메서드가 실행되기 전에 실행되는 annotation임을 알 수 있다.
이때 중요한 것은 @Before는 각 @Test가 진행될때마다 실행되므로 아래에서 총 2번 실행된다.
( ** Before 어노테이션을 여러개 둔 경우 어떤 @Before가 먼저 실행될지는 보장 받을 수 없다.)
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class ComputationUnitTest {
Computation computation = null;
@Before
public void CreateComputationObject() {
this.computation = new Computation();
}
@Test
public void sum_isCorrect() {
assertEquals(4, this.computation.Sum(2,2));
}
@Test
public void multiply_isCorrect() {
assertEquals(4, this.computation.Multiply(2,2));
}
}
@After
@After annotation은 @Before와 유사하다.
보면 바로 알수 있듯이, @Test가 끝난 후 실행되는 annotation 역할을 한다.
( ** After 어노테이션은 테스트가 실패하더라도 실행된다.)
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class ComputationUnitTest {
Computation computation = null;
@Before
public void CreateComputationObject() {
this.computation = new Computation();
}
@After
public void DestroyComputationObject() {
this.computation = null;
}
@Test
public void sum_isCorrect() {
assertEquals(4, this.computation.Sum(2,2));
}
@Test
public void multiply_isCorrect() {
assertEquals(4, this.computation.Multiply(2,2));
}
}
@BeforeClass
@BeforeClass는 @Before와 유사하지만 이는 특정 클래스에서 모든 테스트 케이스를 실행하기 전에 한번만 실행된다.
이는 데이터베이스 연결 개체와 같은 리소스 객체를 생성하는데 유용하다.
이것은 테스트 케이스의 실행 시간을 줄여준다. 그리고 이 메서드는 적절하게 사용되기 위해서는 static이어야만 한다.
이때 중요한 것은 @BeforeClass는 @Test 수와 관계없이 딱 한번만 실행된다.
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class ComputationUnitTest {
private static Computation computation = null;
@BeforeClass
public static void CreateComputationObject() {
computation = new Computation();
}
@Test
public void sum_isCorrect() {
assertEquals(4, computation.Sum(2,2));
}
@Test
public void multiply_isCorrect() {
assertEquals(4, computation.Multiply(2,2));
}
}
@AfterClass
@AfterClass는 @BeforeClass와 유사하다.
@AfterClass annotation도 마지막 딱 한번만 실행되는 것이기에 static으로 두어야한다.
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class ComputationUnitTest {
private static Computation computation = null;
@BeforeClass
public static void CreateComputationObject() {
computation = new Computation();
}
@AfterClass
public static void DestroyComputationObject() {
computation = null;
}
@Test
public void sum_isCorrect() {
assertEquals(4, computation.Sum(2,2));
}
@Test
public void multiply_isCorrect() {
assertEquals(4, computation.Multiply(2,2));
}
}
@Rule
@Rule annotation은 JUnit에서 가장 중요한 특징중 하나이다.
이것은 test case들에게 행동을 부여하는데 사용된다. 이 annotation은 오직 TestRule 타입의 필드에서만 사용할 수 있다. 실제로 @Before 및 @After annotation이 제공하는 기능을 효율적이고 재사용이 가능한 방식으로 제공해준다.
예를들어 보자. test case에서 어떤 데이터를 저장하기 위해 임시 폴더를 필요로 할때 일반적으로 우리는 임시 폴더를 test case를 실행하기 전에 생성해두고(@Before 또는 @BeforeClass에서) test case가 끝나면 삭제할 것이다.(@After 또는 @AfterClass에서)
이러한 것 대신에 우리는 TemporaryFolder이라는 클래스를 JUnit framework로부터 제공받아 모든 테스트케이스에 대한 임시 폴더로 사용할 수 있다.
이러한 것을 사용하기 위해 우리는 @Rule라는 annotation을 사용한다.
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.io.IOException;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertEquals;
public class ComputationUnitTest {
private static Computation computation = null;
@Rule
public TemporaryFolder folder = new TemporaryFolder();
@Test
public void file_isCreated() throws IOException {
folder.newFolder("MyTestFolder");
File testFile = folder.newFile("MyTestFile.txt");
assertTrue(testFile.exists());
}
@BeforeClass
public static void CreateComputationObject() {
computation = new Computation();
}
@AfterClass
public static void DestroyComputationObject() {
computation = null;
}
@Test
public void sum_isCorrect() {
assertEquals(4, computation.Sum(2,2));
}
@Test
public void multiply_isCorrect() {
assertEquals(4, computation.Multiply(2,2));
}
}
아래 그림과 같이 표현할 수 있다.
출처
[JUnit] Android UnitTest, JUnit을 이용한 유닛 테스트
1. JUnit이란? 어느 정도 개발이 진행되면 프로그램에 대한 단위 테스트는 반드시 수행해야 하는데, JUnit은 보이지 않고 숨겨진 단위 테스트를 끌어내어 정형화시켜 단위 테스트를 쉽게 해주는 테
www.crocus.co.kr
'Android > Testing' 카테고리의 다른 글
[Android] UI 테스트 (2) - Espresso (ViewMatcher, ViewAction, ViewAssertion) (1) | 2024.02.09 |
---|---|
[Android] UI 테스트 (1) - Espresso란? (0) | 2024.02.09 |
[Android] Unit 테스트 (2) - Mockito를 이용한 Unit Test (0) | 2024.02.09 |
[Android] Unit 테스트 (1) - Mock 개념(Mockito) (1) | 2024.02.09 |
[Android] 테스트 코드 (1) - 왜 작성해야 할까? (0) | 2024.02.09 |