1.What is Room?
애플리케이션에서 사용될 데이터를 Local Database에 저장할때 사용되는 라이브러리이다.
안드로이드는 기본으로 SQLite를 사용하여 Persistence data를 보관하는데, Room을 사용하면 SQLite를 쉽게 다룰 수 있다.
원시 SQL 쿼리의 사용을 지양하고 Dao라는 인터페이스를 통해 앱 내부에서 사용되는 객체를 사용하여 쉽게 데이터 입출력을 할 수 있게 도와준다.
구글에서 지원하는 Architecture Components의 핵심 라이브러리 중에 하나로 LiveData, ViewModel 등과 함께 적극적으로 사용이 권장되고 있다.
- Entity : 데이터 모델 클래스에 해당한다. Database 내에서 테이블이 되는 단위이다.
- Dao : Database Access Object의 줄임말로 insert, update, delete 등 작업을 수행하는 메소드를 정의한 인터페이스이다.
- Database : 위의 Entitiy와 Dao를 포함시켜 데이터베이스를 정의하는 클래스이다. SQLite와 연결하는 창구역할을 하며 실제 우리는 RoomDatabase를 상속한 데이터베이스의 인스턴스만으로 SQLite에 데이터를 관리할 수 있다.
2.What do we want to achieve in this test?
다른 파트의 개입을 차단한채(고립된 상태로) 순수히 Database의 동작만을 검증하는 테스트를 진행할 수 있다.
이번에 작성할 테스트에스 Task 인스턴스를 데이터베이스에 CRUD(Create / Read / Update / Delete) 하는 기본 기능을 점검하고자 한다.
- 테스트는 androidTest 패키지에서 진행한다.
테스트는 AppDatabase의 인스턴스를 통해 실제 데이터베이스의 오퍼레이션을 수행한다. AppDatabase의 인스턴스를 초기화하기 위해서는 ApplicationContext가 필수적으로 제공되어야하리 때문에 Instrumentation Test로 진행해야한다. 이때 실제 안드로이드 개발환경에 맞는 실제 디바이스를 연결하여 테스트하는 것이 동일한 환경을 조성하고 빠른 테스트를 하는데 유리하다.
Tesing할 컴포넌트는 AppDatabase 인스턴스를 통해 taskDao의 사용을 얻어서 실제 데이터베이스 오퍼레이션을 수행한다. 이는 Android의 SQLite가 있어야 진행할 수 있는 테스트이므로 androidTest에서 진행되어야한다.
3.단계별 테스트 진행과정
3-1.ApplicatoinContext 얻어오기
AppDatabase의 인스턴스를 얻기 위해서는 ApplicationContext가 필요하다.
기존에 AppContext를 얻기 위해서는 InstrumentationRegistry
를 사용했다. 하지만 현재 Studio에서는 Deprecated 되었다는 알람이 발생한다.
구글에서 새롭게 권장하는 방식은 ApplicationProvider
를 사용하는 방식이다.
Context context = ApplicationProvider.getApplicationContext();
3-2.@Before 메소드 만들기
@Before 어노테이션을 가지고 있는 메소드는 전처리 메소드로써 각 @Test 메소드를 실행하기전에 무조건 실행되는 메소드이다.
실제 테스트하고 싶은 Test메소드를 진행하기 앞서 초기화하고 싶은 값이나 준비작업을 진행하는데 사용된다.
위에서는 ApplicationProvider를 통해 AppContext를 얻은 뒤 AppDatabase의 인스턴스를 얻는다.
그 후 실제 테스트할 메소드를 가지고 있는 TaskDao를 얻는다.
3-3.@Test 메소드 만들기
각 @Test 메소드를 통해서 데이터베이스 동작이 올바르게 수행되는지 검증한다.
- INSERT 테스트 : 새로운 Task를 만든다 -> Insert한다. -> DB의 Table에는 삽입한 Task 데이터가 존재해야한다.
- READ 테스트 : DB를 초기화한다 -> Test용 Dummy Data 3개를 삽입한다. -> 전체 데이터 LOAD 한다 -> LOAD 된 데이터는 총 3개여야한다.
- UPDATE 테스트 : DB에 존재하던 Task 데이터를 가져온다. -> Task의 Title 값을 갱신한다. -> DB 속에 Task는 갱신된 Title 값을 가지고 있어야 한다.
- DELETE 테스트 : DB에 존재하던 Task 데이터를 가져온다 -> 식별자인 UUID를 통해 해당 TASK를 삭제한다 -> 실제 DB에 해당 Task는 삭제되어야한다.
위 처럼 테스트는 기본적으로 Given / When / Then 3 단계로 진행된다.
- Given : 테스트가 진행될 기반환경에 대해 설명하고 세팅한다.
- When : 실제 테스트를 원하는 작업이 실행되는 시점이다.
- Then : 메소드가 실행되고 난 결과가 우리가 예상한 결과와 같아야 테스트가 성공이다.
여기서 검증단계인 Then에서는 검증을 돕는 Assert 메소드
를 사용해서 예측값과 실제값이 동일한지 체크한다.
3-4.테스트가 실패한 경우
테스트가 실패한 경우 어떤 Assert에서 검증에 통과하지 못했는지 알려준다.
위 사진에서는 Null이 반환되는 것을 예측했지만 실제 리턴값은 Null이 아니었기 때문에 테스트가 실패했다.
3-5.테스트가 성공한 경우
테스트가 성공한 경우 Success라는 결과를 확인할 수 있다.
Summary
데이터베이스를 사용하기 위해 Room 라이브러리를 사용했다.
이때 Room을 사용해서 데이터베이스에 데이터가 올바르게 삽입, 수정, 삭제 되는지 검증하기 위해서 테스트 코드를 작성했다.
여기서 테스팅한 컴포넌트는 AppDatabase, TaskDao이며, 테스트가 진행되기 위해서는 실제 물리Database의 연결이 필요했다.(Instrumentation Test)
앞으로 Entity나 TaskDao의 코드가 수정될 경우 해당 테스트는 성공할 수도 실패할 수도 있을 것이다.
만약 실패한다면 개발하는 도중 수정으로 인해 데이터베이스의 입출력에서 문제가 발생했음을 신속하게 확인할 수 있으며 다시 테스트 코드를 검증하는 방식으로 빠르게 문제를 해결할 수 있도록 도움 받을 수 있다.
구글에 검색해보면 TDD 개발 방식을 적용함에 있어서도 사람들의 의견이 많이 나뉘는 것 같다.
테스트 코드를 작성할 때 반드시 Given / When / Then을 지켜서 작성해야 의미가 있다고 생각하는 강력한 TDD개발론자들이 있고,
쓸데없이 자세한 테스트 코드 작성에 더 많은 시간을 뺏기게 되므로 중요한 코드만 선별해서 테스트 코드를 작성하는 느슨한 TDD개발론을 주정하는 사람들도 많았다.
실제 어떤 방식이 더 효과적인지는 사용하면서 조금 더 생각해봐야겠다.
'Android' 카테고리의 다른 글
Fragment에 리스트 출력하기 Part.1 (0) | 2019.09.29 |
---|---|
ViewModel Testing 코드 작성하기 (0) | 2019.09.18 |
실제로 앱을 개발하면서 안드로이드 프로그래밍 배우자. (0) | 2019.08.08 |
최소 기능 제품, Minimum Viable Product(MVP) (0) | 2019.08.08 |
CoffeeMaker 예제로 알아보는 Dagger (0) | 2019.08.05 |