일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- NPM
- k for k
- Python
- JS
- 타입스크립트
- 코딩테스트
- stdin vs input
- 안드로이드
- 최적화
- TS
- 알고리즘
- typescript
- CSS
- Android
- firebase
- kotlin
- 자바스크립트
- nodejs
- 백준 스택
- next Link
- 백준 스택 시간초과 python
- HTML
- C++
- 리액트
- 파이썬
- 스택
- 파이어베이스
- 프론트엔드
- react
- javascript
- Today
- Total
sooleeandtomas
안드로이드 코틀린 아키텍쳐와 테스트 (1) 본문
## 아키텍처가 필요한 이유
➖ 유지보수
➖ 개발자와의 협업 (컨벤션이 있기 때문에 이해하기 쉽다)
➖ 테스트에 용이 (의존성이 레이어 별로 분리되어 있다. "안드로이드에 의존하는 코드"는 단위 테스트가 힘들어진다)
➖ 책임의 격리로 인해 개발 시 설계 및 구현의 용이함
➖ 멀티모듈로 나누기에 적절하다. (빌드 속도 향상, TDD 사이클 속도 향상, 가독성 향상, 재사용성 향상...등의 장점이 많다)
➖ 변경에 유연하게 대응
## 단위 테스트
➖ 기능을 개발하는 당장에는 필요 없을 수 있지만, 테스트 코드가 없다면 추후 코드를 수정해야 하는 개발자가 기존 요구 사항을 지키면서 코드를 작성하기 힘들다.
➖ 협업 시 테스트 코드를 보고 요구사항을 빠르게 캐치할 수 있다.
## 안드로이드의 단위 테스트
➖ 도메인 로직은 domain 모듈로 분리 (또는 feature 모듈로 분리한다.)
✖️ 무엇이 도메인 로직인가 고민하기 (UI 로직과 분리)
✖️ 객체지향적으로 생각하기
➖ JUnit5 or JUnit4 (안드로이드에서는 공식적으로 JUnit4만 지원한다.)
프로젝트를 생성하면 총 3개의 Source Set이 생성됩니다.
[main, androidTest, test]
main : 프로덕션 코드
androidTest: UI 테스트 (안드로이드에 의존적인 테스트 espresso, UI automator)
test: 주로 단위 테스트, 통합 테스트도 가능 (안드로이드에 의존성이 없는 테스트 Robolectric, HTTP 요청)
(integrationTest 라는 것도 있음)
## 안드로이드의 UI 테스트
➖ espresso
➖ white box 테스트 내부 구현을 알아야 작성 가능
➖ black box 테스트 내부 구현을 몰라도 작성 가능
➖ 프로덕션 코드를 참조하여 테스트 가능
## 안드로이드의 단위 test 예제
app/java/com.soolee.androidtest1(test)/CounterTest.kt
package com.soolee.androidtest1
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
class CounterTest {
private lateinit var counter: Counter
@Before
fun setUp() {
counter = Counter()
}
@Test
fun 숫자는_0부터_시작한다() {
//when
var actual: String = counter.value.toString();
//then
assertThat(actual).isEqualTo("0");
}
@Test
fun 숫자가_1_증가한다() {
//when
counter.increment()
var actual: String = counter.value.toString();
//then
assertThat(actual).isEqualTo("1");
}
@Test
fun 숫자가_1_감소한다() {
//when
counter.decrement()
var actual: String = counter.value.toString();
//then
assertThat(actual).isEqualTo("-1");
}
}
app/java/com.soolee.androidtest1/MainAcitivity.kt
package com.soolee.androidtest1
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
class MainActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val buttonUp = findViewById<Button>(R.id.buttonUp)
val buttonDown = findViewById<Button>(R.id.buttonDown)
val text = findViewById<TextView>(R.id.textView)
val counter = Counter()
buttonUp.setOnClickListener{
counter.increment();
}
buttonDown.setOnClickListener{
counter.decrement()
text.text = counter.value.toString()
}
}
}
app/java/com.soolee.androidtest1/Counter.kt
package com.soolee.androidtest1
public class Counter {
var value: Int = 0
fun increment(){
value += 1
}
fun decrement(){
value -= 1
}
}
## 안드로이드의 UI test 예제
app/java/com.soolee.androidtest1(androidTest)/MainAcitivityTest.kt
class MainActivityTest {
@get:Rule
var activityScenarioRule = ActivityScenarioRule(MainActivity::class.java)
//사용자가 피연산자 0~9 버튼을 누르면 화면에 해당 숫자가 화면에 보여야 한다.
@Test
fun 버튼_0을_누르면_화면에_0이_보여야_한다() {
//when
onView(withId(R.id.button0)).perform(click())
//then
onView(withId(R.id.textView)).check(matches(withText("0")))
}
}
app/java/com.soolee.androidtest1/MainAcitivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button0 = findViewById<Button>(R.id.button0)
val text = findViewById<TextView>(R.id.textView)
button0.setOnClickListener {
text.text = "0"
}
}
'코틀린 > kotlin' 카테고리의 다른 글
안드로이드스튜디오에서 domain 모듈 분리하는 방법 (0) | 2022.07.13 |
---|---|
코틀린 화면 구성하기 (0) | 2021.09.18 |
android studio를 M1에서 사용하기 (0) | 2021.09.13 |
코틀린 문법 (0) | 2021.09.07 |