API 테스트 코드를 작성하게 된 주요 이유
- 개발 도중 기획 변경으로 인해 API가 자주 수정되고 있습니다.
- API의 변경에 따라 안드로이드 코드도 연쇄적으로 수정해야 합니다.
- 서버의 소소한 변경사항에 대한 정보가 누락될 때가 있습니다.
- 서버가 재배포될 때마다 API 변경으로 인해 발생할 수 있는 오류를 확인하고자 합니다.
주요 JUnit 어노테이션
- @Test: 이 어노테이션이 붙은 메소드는 JUnit에 의해 테스트로 인식되고 실행됩니다.
- @Before: 각 테스트 메소드가 실행되기 전에 실행되어야 할 코드를 포함하는 메소드에 이 어노테이션을 사용합니다. 예를 들어, 테스트에 필요한 객체를 초기화하거나 테스트 환경을 설정하는 데 사용됩니다.
- @After: 각 테스트 메소드의 실행이 끝난 후에 실행되어야 할 코드를 담고 있습니다. 주로 리소스 해제, 테스트 후 정리 작업 등을 수행합니다.
- @BeforeClass: 해당 클래스의 모든 테스트가 실행되기 전에 단 한 번만 실행되어야 할 코드를 담습니다. static 메소드로 선언되어야 합니다.
- @AfterClass: 모든 테스트 메소드의 실행이 완료된 후에 단 한 번 실행되어야 하는 코드를 포함합니다. 이 역시 static 메소드로 선언되어야 합니다.
- @Ignore: 테스트를 일시적으로 비활성화할 때 사용합니다. 이 어노테이션이 붙은 테스트 메소드는 실행되지 않습니다.
class ApiServiceTest {
companion object {
lateinit var apiService: ApiService
private lateinit var accessToken: String
@BeforeClass
@JvmStatic
fun setUpClass() {
val loggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
val httpClient = OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.addInterceptor { chain ->
val originalRequest = chain.request()
val builder = originalRequest.newBuilder()
// Check if accessToken is initialized and not empty
if (this::accessToken.isInitialized && accessToken.isNotEmpty()) {
builder.addHeader("Authorization", "Bearer $accessToken")
}
chain.proceed(builder.build())
}
.build()
apiService = Retrofit.Builder()
.baseUrl(BASE_URL)
.client(httpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApiService::class.java)
val signInResponse = apiService.signIn("five2week@five2week.com", "five2week1234").execute()
assertTrue(signInResponse.isSuccessful)
assertNotNull("Response body should not be null", signInResponse.body())
accessToken = signInResponse.body()?.accessToken ?: "
}
}
@Test
fun `test findUserId with valid data returns userId`() {
val findIdRequest = FindIdRequest(
username = "five2week",
birthdate = "20240418",
phone = "01012345678"
)
val response = apiService.findUserId(findIdRequest).execute()
assertTrue("Response should be successful", response.isSuccessful)
assertNotNull("Response body should not be null", response.body())
assertEquals("Expected user ID", "five2week@five2week.com", response.body())
}
...
}
해당 테스트를 통한 이점
- 자동화된 검증: API가 변경될 때마다 수동으로 테스트하는 것은 시간 소모적이고 에러를 발견하기 어려울 수 있습니다. 자동화된 테스트를 구현함으로써, 새롭게 배포된 API에 대한 신속하고 일관된 검증이 가능합니다.
- 버그 식별: 서버 측 변경사항이 안드로이드 애플리케이션에 영향을 주는 경우, 테스트 코드는 새로운 버그나 이슈를 초기 단계에서 발견하는 데 도움을 줄 수 있습니다.
- 소통의 부재 극복: 서버 개발자와의 소통이 원활하지 않을 때, 테스트 코드는 API의 스펙이 기대한 대로 동작하는지 확인하는 데 도움을 줍니다. 또한, 변경사항이 있을 때 테스트 실패를 통해 즉각적인 피드백을 받을 수 있습니다.
- 변경 관리: 서버의 재배포가 자주 일어나는 경우, 각 배포에서 API의 변화를 추적하고 관리하는 것이 중요합니다. 테스트 코드는 이러한 변경사항을 문서화하고 검증하는 효과적인 방법을 제공합니다.
앞으로 보완할 사항
- 요청을 하면 비용이 발생하는 Call은 테스트하고 있지 않습니다.
- 현재 성공하는 경우의 수에 대해서만 테스트하고 있습니다. 실패하는 경우에도 적절히 대응하는지 테스트를 추가해야합니다.
'질문 정리' 카테고리의 다른 글
안드로이드 컴포즈 구글 로그인 연동 정리 (0) | 2024.04.28 |
---|---|
연속된 버튼 클릭, api 요청 처리법 (1) | 2024.04.24 |
_username과 username 왜 나누는 것일까?(백킹 프로퍼티) (0) | 2024.04.16 |
Retrofit의 Call과 Response 공부하기 (1) | 2024.04.07 |
깔끔한 코드를 위해서 Ktlint 사용 (0) | 2024.01.30 |