728x90
반응형
테스트는 소프트웨어 개발 생명주기에서 매우 중요한 부분을 차지한다. 테스트를 잘 하면 버그 감소와 유지보수 용이성, 코드 문서화, 개발 생산성 향상 등의 측면에서 유리하다.
White Box Test (구조 기반 테스트)
- 소프트웨어의 내부 구조와 동작을 검증하는 테스트로 개발자가 코드의 내부 로직, 제어 흐름, 데이터 흐름 등을 이해하고 테스트 케이스를 작성하는 방법이다.
- 코드의 모든 경로와 조건을 확인할 수 있어 Code Coverage가 높지만, 개발자의 시각에 의존하므로 완전한 테스트는 힘들다.
Black Box Test (기능 기반 테스트)
- 소프트웨어의 내부 구현을 알지 못하고 기능에만 초점을 맞춘 테스트로 시스템이 요구 사항을 만족하는지 여부를 확인하는 것이 목표이다.
- 사용자의 관점에서 테스트하기 때문에 완전한 기능 검증이 가능하지만, 코드의 모든 경로를 테스트하지 못할 수 있고 특정한 버그나 예외 상황을 놓칠 수 있다.
주로, 개발자는 White Box Test를 수행하고, QA(Quality Assurance) 팀은 Black Box Test를 수행하여 다양한 시각에서 소프트웨어를 검증한다.
White Box (Unit) Test - 종류
Junit을 사용하여 Test Case를 작성할 때 주로 사용하는 테스트 방법.
1. Method Test
Unitils 3.4
@Test
public void testAddNumbers() {
// given
MyService myService = new MyService();
// when
int result = myService.addNumbers(2, 3);
// then
ReflectionAssert.assertReflectionEquals(5, result);
}
2. API Test
RestAssured 4.5.0
@Test
public void testGetUser() {
// given
RestAssured.baseURI = "https://jsonplaceholder.typicode.com";
// when
Response response = given()
.when()
.get("/users/1")
.then()
.statusCode(200)
.extract()
.response();
// then
String username = response.path("username");
given()
.when()
.get("/users/1")
.then()
.body("username", equalTo(username));
}
3. Database Test
Unitils 3.4
@Test
public void testFindUserById() {
// given
UserDao userDao = new UserDao(entityManager);
// when
User user = userDao.findUserById(1L);
// then
assertEquals("John", user.getName());
assertEquals("Doe", user.getSurname());
assertEquals("john@example.com", user.getEmail());
}
4. Integration Test
MockMvc
@Test
public void testGetHello() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/hello"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string("Hello, World!"));
}
5. Suite Test
@RunWith(Suite.class)
@Suite.SuiteClasses({
TestClass1.class,
TestClass2.class,
TestClass3.class
})
public class TestSuite {
}
코드 검증 방법
전자정부 프레임워크 샘플
Constructor Test
단순한 로직의 경우 테스트 하지 않아도 되지만, 값을 초기화 하거나 로드하는 경우에는 테스트를 수행한다.
Setter / Getter Test
단순한 Set/Get은 테스트 하지 않아도 되지만, 로직이 있는 경우 별도의 메서드로 분리하고 테스트 한다.
Boundary Test
Null 체크, Default 값 확인, 범위가 있는 경우 MIN/MAX 값에 대한 확인을 목적으로 테스트 한다.
*결국 NPE가 발생하지 않도록 보완하는 것이 좋다.
Exception Test
예상하는 예외가 실제로 발생하는지 확인한다.
@Test (expected = IndexOutOfBoundsException.class)
public void testException() {
throw new IndexOutOfBoundsException();
}
Equality Test
결과 값이 예상한 값과 일치하는지 비교한다.
// Value
@Test
public void testReferenceEqual() {
String string1 = new String("somevalue");
String string2 = string1;
assertEquals("두 객체의 값이 같음", string1, string2);
assertSame("두 객체의 주소값이 같음", string1, string2);
}
// Number
@Test
public void testDoubleEqual() {
double value1 = 10 / 3;
double value2 = 3.33;
assertEquals("소수 둘째자리까지 같음", value1, value2, 2);
}
// List / Array
@Test
public void testReflectionEqualLenientOrder() {
List<Integer> myList = Arrays.asList(3, 2, 1);
assertReflectionEquals(Arrays.asList(3, 2, 1), myList);
assertReflectionEquals("순서 무시하고 값이 같은지 비교", Arrays.asList(1, 2, 3), myList, LENIENT_ORDER);
}
@Test
public void testAssertReflectionEqualsIgnoringDefault() {
assertReflectionEquals("디폴트 값 무시하고 같은지 비교",
new UserVo(1, "name", null), new UserVo(1, "name", "description1"), IGNORE_DEFAULTS);
}
// Value Object
@Test
public void testAssertReflectionEqualsFieldByField() {
UserVo user1 = new UserVo(100, "name", "description");
UserVo user2 = new UserVo(100, "name", "description");
assertReflectionEquals("객체를 구성하는 attribute를 하나하나 자동으로 비교", user1, user2);
}
Parameterized Test
파라미터 값만 바꿔가면서 동일한 테스트를 반복해서 수행한다.
@RunWith(Parameterized.class)
public class ParameterizedTest {
private String password;
private boolean isValid;
private static PasswordValidator validator;
@BeforeClass
public static void setUp() {
validator = new PasswordValidator();
}
public ParameterizedTest(String password, boolean isValid) {
this.password = password;
this.isValid = isValid;
}
@Parameters
public static Collection passwords() {
return Arrays.asList(new Object[][] { { "1234qwer", true }, {"12345678", false}, {"1q2w3e4r", true} });
}
@Test
public void isValidPasswordWithParams() {
assertEquals(validator.isValid(this.password), this.isValid);
}
}
Timeout Test
테스트에 소요되는 시간을 지정하여, 해당 시간이 넘은 경우 Fail 처리한다.
@Test (timeout = 1)
public void testTimeout() {
}
Test Ignore
테스트를 Skip 하고 싶을 때 사용한다. (Class / Method에 적용 가능)
@Ignore ("테스트 수행하지 않도록 설정 함 (실제론 상세 원인을 표시)")
@Test
public void testIgnore() {
assertTrue("이 테스트 메소드는 실행이 되지 않음", true);
}
※ 테스트에 사용되는 라이브러리들은 해당 URL참조.
https://inbeom.tistory.com/entry/API-%ED%85%8C%EC%8A%A4%ED%8A%B8-junit4-AssertJ
- 끝 -
reference.
https://www.egovframe.go.kr/wiki/doku.php?id=egovframework:dev:tst:test_case
728x90
반응형
'📚Framework & Library > JUnit' 카테고리의 다른 글
[Junit] Jasper Report PDF 문서 검증하기 (feat. JpdfUnit) (2) | 2024.01.23 |
---|---|
[Junit] Elasticsearch Unit(Integration) Test Code 작성하기 (0) | 2024.01.23 |
[Junit] TypeReference, JsonPath - Json 다루기 (feat. ObjectMapper) (3) | 2023.11.17 |
[Junit] Junit4 다양한 라이브러리 활용 (feat. AssertJ, Unitils, RestAssured) (2) | 2023.11.17 |
[JUnit] junit5 간단한 테스트 코드 작성 (0) | 2023.09.10 |