반응형

Unit Testing

  • [Unit Testing] 어떤 클래스에 테스트가 필요할까? data class 도 테스트가 필요한가?

    [Unit Testing] 어떤 클래스에 테스트가 필요할까? data class 도 테스트가 필요한가?

    테스트는 어떤 클래스에 필요할까? 객체 지향 언어에서 클래스는 데이터만을 저장하는 클래스, 동작을 포함하는 클래스 두가지 종류로 나뉜다. 예를 들어 Java의 경우는 일반적인 클래스와 POJO 클래스가 있다. Kotlin의 경우는 데이터만을 저장하는 클래스와 동작이 포함된 클래스가 있다. 프로그래밍에서는 데이터만을 저장하는 클래스를 '데이터 구조' 라 부르고 동작을 포함하는 클래스를 '객체'라 부른다. Unit Testing에서의 Unit은 특정한 책임을 가지고, 명확히 정의된 역할을 가진 것이다. 이는 바로 '객체'를 뜻한다. 즉, Unit Testing의 대상은 객체이지 데이터 구조가 아니다. 따라서 테스트가 필요한 클래스는 동작을 포함하는 클래스인 객체이다. Kotlin의 data class는 테스..

  • [JUnit] Unit Testing을 깔끔하게 작성하는 방법 : 테스트 이름 작성 방법, 코드 순서 작성 방법

    [JUnit] Unit Testing을 깔끔하게 작성하는 방법 : 테스트 이름 작성 방법, 코드 순서 작성 방법

    Unit Testing 깔끔하게 작성하기 Unit Testing을 깔끔하게 작성하기 위해서는 Unit Test의 이름, 테스트 내부의 작성 순서가 중요하다. 이름 작성 방법 가독성을 좋게 만들려면 [메서드명][결과][환경 설명] 순서로 작성한다. 예를 들어 LoginRepository에서 Login이 Success했을 때, LoginUseCase의 login이 Success 해야 한다면 [login][Success][WhenLoginRepositoryLoginSuccess]와 같이 같이 테스트 이름이 작성될 수 있다. @Test fun loginSuccessWhenLoginRepositoryLoginSuccess() { val repositorySuccessResult = LoginRepositoryRe..

  • [Unit Testing] Android의 정적 메서드를 사용하거나 Android 전용 클래스를 사용하면 테스트에 실패하는 이유 알아보기

    [Unit Testing] Android의 정적 메서드를 사용하거나 Android 전용 클래스를 사용하면 테스트에 실패하는 이유 알아보기

    Unit Test와 Android Framework Android 개발자들에게 Test가 어렵게 다가오는 이유 중 하나는 안드로이드에서는 조금만 잘못해도 테스트가 실패하기 때문이다. 이번 글에서는 대부분의 안드로이드 개발자들이 겪는 안드로이드에서 테스트가 실패하는 이유 두가지와 해결 방법에 대해 알아볼 것이다. 안드로이드에서 테스트가 실패하는 케이스 안드로이드에서 안드로이드로 인해 테스트가 실패하는 케이스는 두가지이다. 바로 안드로이드에서 제공하는 정적 메서드를 사용하는 경우와, 안드로이드 전용 클래스를 사용하는 경우이다. 이들 각각에 대한 테스트를 작성해보고 왜 실패하는지 이유와 해결책을 알아보자. 안드로이드에서 제공하는 정적 메서드 테스트 해보기 예를 들어 유저가 가입할 때 id가 유효한지를 확인하는..

  • [Unit Testing] Android Context 객체를 사용하는 클래스 테스트하기

    [Unit Testing] Android Context 객체를 사용하는 클래스 테스트하기

    Android와 Context 객체 Android에서 Context 객체는 God Object(신 객체)이다. Context 내에는 무수히 많은 책임과 메서드가 있다. 이 때문에 많은 개발들이 만약 context 객체가 있다면 테스트 하기 어렵다고 생각한다. 하지만 이는 틀렸다. Context 자체를 테스트 하는건 어렵지만, Context를 포함하는 객체를 테스트 하는 것은 가능하다. 아래에서 리소스를 가져오는 클래스인 ResourceRetriever 클래스를 사용해 Context를 테스트 하는 방법에 대해 살펴보도록 하자. 테스트 환경 설정 예를 들어 아래와 같은 ResourceRetriever 클래스가 있다고 해보자. 이 클래스는 안드로이드에서 리소스를 가져오는 역할을 한다. class Resourc..

  • 코드 작성 시 정적 변수와 정적 메서드 사용을 지양해야 하는 이유 알아보기

    코드 작성 시 정적 변수와 정적 메서드 사용을 지양해야 하는 이유 알아보기

    Static Variable과 Static Method 정적인 변수와 메서드는 한 번 선언 해놓으면 이곳 저곳에서 모두 사용할 수 있기 때문에 매우 편리하게 사용될 수 있다. 하지만, 시스템적으로 보았을 때 정적인 변수와 메서드는 최대한 지양하는 것이 좋다. 정적인 변수와 메서드를 참조 하는 클래스가 늘어난다는 것은 정적 변수와 메서드에 의존성이 생긴다는 것을 뜻한다. 이는 프로그램이 작을 때는 문제가 없지만 프로그램이 커지면 커질 수록 큰 문제로 번진다. 특히 정적 변수는 해당 변수가 여러 클래스에서 공유되게 될 경우 해당 클래스들이 서로가 서로에게 의존성이 생기는 것을 의미한다. 정적 메서드의 경우 정적 변수를 참조하지 않으면 그나마 낫지만, 정적 변수를 참조하지 않더라도 테스트 시에 문제가 생길 가..

  • MockitoJUnitRunner 사용해 Mockito 코드 깔끔하게 만들기 : @Mock

    MockitoJUnitRunner 사용해 Mockito 코드 깔끔하게 만들기 : @Mock

    이전 테스트 이전 시간에 다음과 같은 테스트를 작성했다. setUp에서 Mockito.mock 메서드를 사용해 loginRepository를 Mock 객체로 초기화 시켰는데, 여기서는 LoginUseCase에 대한 의존성이 하나만 있어서 한 줄로 Mocking이 끝났다. class LoginUseCaseTest { private lateinit var loginUseCase: LoginUseCase private lateinit var loginRepository: LoginRepository @Before fun setUp() { loginRepository = Mockito.mock(LoginRepository::class.java) loginUseCase = LoginUseCase(loginRepo..

Coroutines 공식 문서 번역

  • Coroutines와 Channels 튜토리얼 - 2. Blocking Requests

    Coroutines와 Channels 튜토리얼 - 2. Blocking Requests

    Blocking 요청들 GitHub에 HTTP 요청을 하기 위해 Retrofit 라이브러리를 사용할 것이다. 주어진 조직에 속한 저장소 목록과 각 저장소의 기여자 목록을 요청할 수 있다. interface GitHubService { @GET("orgs/{org}/repos?per_page=100") fun getOrgReposCall( @Path("org") org: String ): Call @GET("repos/{owner}/{repo}/contributors?per_page=100") fun getRepoContributorsCall( @Path("owner") owner: String, @Path("repo") repo: String ): Call } 이 API는 주어진 조직의 기여자 목록을 가..

  • Coroutines와 Channels 튜토리얼 - 1. 시작하기 전 준비하기

    Coroutines와 Channels 튜토리얼 - 1. 시작하기 전 준비하기

    이 튜토리얼에서는 IntelliJ IDEA를 사용해, 실행중인 Thread나 Callback을 블록하지 않고 코루틴을 사용하여 네트워크 요청을 수행하는 방법을 살펴볼 것이다. 📖 당신은 Kotlin 기초 구문에 익숙해야 하지만, Coroutines에 대한 사전 지식은 필요하지 않습니다. 당신은 다음의 사항들에 대해 배울 것입니다. 네트워크 요청을 하기 위해 일시 중단 함수를 왜 그리고 어떻게 사용해야 하는지 Coroutines을 사용하여 요청을 동시에 보낼 수 있는 방법 서로 다른 Coroutines 간에 Channels를 이용하여 정보를 공유하는 방법 네트워크 요청들을 위해서 Retrofit 라이브러리를 필요로 하지만, 이 튜토리얼에서 보여지는 접근 방식은 보편적이고 Coroutines를 지원하는 다른..

  • IntelliJ IDEA 사용해 Kotlin Flow 디버깅 하기

    IntelliJ IDEA 사용해 Kotlin Flow 디버깅 하기

    이 튜토리얼은 IntelliJ IDEA를 사용해 Kotlin Flow를 생성하고 디버깅 하는 방법에 대해 설명한다. 이 튜토리얼에서는 독자들이 Coroutine 개념에 대한 사전 지식이 있다고 가정한다. Kotlin Flow 생성하기 느린 방출기와 느린 수집기를 가진 Kotlin flow를 생성한다: 1. Intellij IDEA에서 Kotlin 프로젝트를 연다. 만약 프로젝트가 없다면 하나를 새로 만든다. 2. kotlinx.coroutines 라이브러리를 Gradle 프로젝트에서 사용하기 위해서 다음 종속성을 build.gradle(.kts)에 추가한다. Kotlin Gradle dependencies { implementation("org.jetbrains.kotlinx:kotlinx-corouti..

  • IntelliJ IDEA 사용해서 Coroutine 디버깅 하기

    IntelliJ IDEA 사용해서 Coroutine 디버깅 하기

    이 튜토리얼은 IntelliJ IDEA를 사용해 Kotlin Coroutine을 만들고 디버깅하는 방법을 설명한다. 이 튜토리얼에서는 독자들이 Coroutine 개념에 대한 사전 지식이 있다고 가정한다. Coroutine 생성하기 1. Intellij IDEA에서 Kotlin 프로젝트를 연다. 만약 프로젝트가 없다면 하나를 새로 만든다. 2. kotlinx.coroutines 라이브러리를 Gradle 프로젝트에서 사용하기 위해서 다음 종속성을 build.gradle(.kts)에 추가한다. Kotlin Gradle dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4") } Groovy Gradle depende..

  • Coroutine 공유 상태와 동시성 3편 - Mutex 사용하기, Actors 사용하기

    Mutex 사용하기 문제에 대한 상호 배제 솔루션은 모든 모든 공유 상태에 대한 변경을 절대로 동시에 실행되지 않는 critical section*1으로 만들어 보호하는 것이다. 블로킹을 수행하기 위해서는 일반적으로 synchronized나 ReentrantLock을 사용한다. Coroutine의 대체제는 Mutex*2라 불린다. 이는 critical section을 구분하기 위한 lock과 unlock 함수를 가진다. 중요한 차이점은 Mutext.lock()이 일시중단 함수라는 것이다. 이는 Thread를 블록하지 않는다. mutex.lock(); try { ... } finally { mutex.unlock() } 패턴을 나타내는 withLock 확장함수 또한 있다. val mutex = Mutex(..

  • Coroutine 공유 상태와 동시성 2편 - Thread-safe한 데이터 구조, 세밀하게 Thread 제한하기, 굵게 Thread 제어하기

    Thread-safe한 데이터 구조 Threads과 Coroutines에 모두 작동하는 일반적인 해결 방법은 공유 상태에 수행되어야하는 모든 동작에 대한 필수적인 동기화를 제공하는 스레드 안전한(동기화된, 선형성, 원자성 이라고도 부름) 데이터 구조를 사용하는 것이다. 간단한 카운터에 대해서는 incrementAndGet 이라 불리는 원자적인 동작을 제공하는 AtomicInteger 클래스를 사용할 수 있다. val counter = AtomicInteger() fun main() = runBlocking { withContext(Dispatchers.Default) { massiveRun { counter.incrementAndGet() } } println("Counter = $counter") } ..

Android를 위한 Coroutines

  • [안드로이드를 위한 Coroutines] 책 소개

    들어가며 Kotlin Coroutines는 Kotlin을 위한 강력한 비동기 솔루션이다. 안드로이드 실무에서 한동안 높은 점유율을 자랑한 RxJava가 Coroutines로 대체 되었고, 새로 시작하는 안드로이드 프로젝트들은 대부분 Coroutines를 사용하고 있다. 안드로이드의 공식언어가 Kotlin인데, Kotlin의 비동기 솔루션으로 Coroutines가 채택되었으므로 이후의 동시성 프로그래밍은 Coroutines를 기반으로 만들어질 것임을 알 수 있다. Coroutines의 강점 Coroutines가 Kotlin의 주요한 비동기 솔루션이 될 수 있던 이유는 Coroutines의 성능, 안정성 때문이다. Coroutines는 기존 비동기 라이브러리들이 채택한 스레드와 스레드풀 기반 비동기 프로그래..

  • [안드로이드를 위한 Coroutines] 안드로이드의 멀티스레드 프로그래밍 : 기존의 Thread 기반 멀티스레드 프로그래밍 방식과 한계점

    [안드로이드를 위한 Coroutines] 안드로이드의 멀티스레드 프로그래밍 : 기존의 Thread 기반 멀티스레드 프로그래밍 방식과 한계점

    안드로이드와 멀티스레드 프로그래밍 안드로이드는 메인 스레드라 불리는 UI 스레드에서 모든 UI 관련 작업들을 처리한다. 만약 메인 스레드가 서버와의 네트워크 통신이나 데이터베이스 읽기/쓰기 작업들에 의해 길게 점유된다면 안드로이드 앱은 버벅이거나 멈추게 된다. 안드로이드를 개발하는 사람이라면 누구나 겪어보는 오류인 ANR(Application Not Responding)은 앱이 입력된 이벤트에 5초 이내에 응답하지 않는 경우에 일어나는데, 이 또한 메인 스레드를 길게 점유하는 작업이 원인이다. 이를 해결하기 위해 개발자들은 메인스레드 외에 새로운 스레드를 만들어 해당 스레드에서 길게 걸리는 작업을 처리한다. 이를 여러개의 스레드를 사용한다 해서 멀티스레드 프로그래밍이라 한다. 멀티 스레드 프로그래밍을 사..

반응형