Slide 1

Slide 1 text

Unit Test부터 UI Test까지 부현식

Slide 2

Slide 2 text

Who am I?

Slide 3

Slide 3 text

부현식 컴퓨터 공학 전공 삼성전자 무선사업부 (2년차 개발자) Bixby2.0 Client 개발 안드로이드, TDD, 자동화, 블록체인 Github : boohyunsik Blog : boohyunsik.github.io

Slide 4

Slide 4 text

Contents 1. Unit test 와의 첫 만남? 2. Unit test 의 진가 3. UI Testing 까지!

Slide 5

Slide 5 text

Unit test 에 대한 편견?

Slide 6

Slide 6 text

귀찮다. 그거 짤 시간이 어디있냐. 빌드할 때 자꾸 남의 TC가 죽어서 싫다. TC 짜는 법 배우기 귀찮다.

Slide 7

Slide 7 text

대학생때의 나 객체 지향 프로그래밍..? 그거 먹는건가요.. 프로그램은 돌아가기만 하면 되지~ 어차피 과제내면 안 볼 코드들이야~ 대기업 가려면 알고리즘 문제 푸는게 우선이야!

Slide 8

Slide 8 text

Unit testing과의 첫 만남? 소프트웨어 공학 시간…

Slide 9

Slide 9 text

Example

Slide 10

Slide 10 text

Example

Slide 11

Slide 11 text

이걸 굳이 왜…?

Slide 12

Slide 12 text

Unit testing의 진가 공모전

Slide 13

Slide 13 text

Retrofit 따릉이정보를 보여주는 Android app 제작 식당 정보를 받아오기 위해 Retrofit을 이용

Slide 14

Slide 14 text

But… Retrofit을 처음 써보는 상황 Rest API? 뭐지 그게…

Slide 15

Slide 15 text

But… Unit test는 머릿속에 존재도 하지 않음… 안드로이드 개발도 해본 경험이 별로..

Slide 16

Slide 16 text

How to test? Retrofit을 이용해서 축제 정보 받아오는 로직 구현 로그로 받아온 정보를 다 찍고

Slide 17

Slide 17 text

How to test? APK를 설치해서 데이터를 실제로 받아오는 곳까지 직접 들어가서 로그를 확인!

Slide 18

Slide 18 text

How to test? 또한 Rest API는 Postman을 이용하거나 Retrofit은 새로운 Java 프로젝트를 만들어서 테스트!

Slide 19

Slide 19 text

매우 매우 귀찮고 비효율적인 것 같다…

Slide 20

Slide 20 text

Unit test를 활용해보자!

Slide 21

Slide 21 text

간단한 배경지식… Mocking : 테스트용 가짜 객체를 만드는 것 Assert : 조건에 부합하지 않으면 프로그램을 종료함

Slide 22

Slide 22 text

Unit test를 활용해보자! Retrofit을 이용하여 따릉이 정보를 가져오는 메소드

Slide 23

Slide 23 text

결과! 간단하게 유닛 테스트 작성

Slide 24

Slide 24 text

메소드 단위로 실행 즉석에서 메소드 단위로 실행 가능!

Slide 25

Slide 25 text

뭐가 좋은가? 굳이 App을 실행하여 테스트 할 필요가 없음 메소드 단위로 실행하여 따릉이 api를 잘 쓰고 있는지 간단하게 테스트 가능!

Slide 26

Slide 26 text

이거 좀 쓸만한데…? (감이 오기 시작…)

Slide 27

Slide 27 text

다른 부분에도 Unit test를 적용해보자!

Slide 28

Slide 28 text

그러나 이미 프로젝트는 산으로…

Slide 29

Slide 29 text

Refactoring for Test Code !

Slide 30

Slide 30 text

테스트를 방해하는 요소들 1. 복잡한 의존과 강한 결합 2. 덩치가 큰 메소드

Slide 31

Slide 31 text

복잡한 의존과 강한 결합 객체끼리 직접 결합하고 있는 경우!

Slide 32

Slide 32 text

복잡한 의존과 강한 결합 ToggleButton이 하나 있는 액티비티

Slide 33

Slide 33 text

Activity에 있는 ToggleButton이 눌려있는지 반환하는 기능을 제공하는 Example 클래스

Slide 34

Slide 34 text

간단하게 만들어본 테스트 코드

Slide 35

Slide 35 text

@Before annotation이 붙은 함수는 각 테스트 함수 실행 전에 실행됩니다.

Slide 36

Slide 36 text

이 테스트 함수는 isToggleSelectedInActivity가 반환하는 값을 출력합니다.

Slide 37

Slide 37 text

테스트 실패입니다 ㅠ.ㅠ

Slide 38

Slide 38 text

왜 실패할까…?

Slide 39

Slide 39 text

강하게 결합하는 구조는 테스트하기 어렵다!

Slide 40

Slide 40 text

이유는 많더라.. 1. 안드로이드 디바이스에 엮인 객체라던가 2. 의존하는 클래스가 또 다른 컴포넌트에 의존 한다던가 3. 서버 통신이나 인증 과정이 필요한 경우나…

Slide 41

Slide 41 text

Android Device Activity JVM Activity? 액티비티는 안드로이드 OS가 만들어줘야 의미를 갖지, 내 컴퓨터의 JVM 위에서는 의미가 없다!

Slide 42

Slide 42 text

그리고 어찌어찌 안드로이드 의존을 잘 해결했더라도 이 함수는 정해진 값 만을 return하게 됨

Slide 43

Slide 43 text

결합을 약하게!

Slide 44

Slide 44 text

테스트 코드 상에서 실행하기 힘들었던 MainActivity를, 테스트용 View로 바꿀수 있다

Slide 45

Slide 45 text

인터페이스로 구현

Slide 46

Slide 46 text

Example이 MainActivity를 MainView 인터페이스를 통해 의존하도록 변경!

Slide 47

Slide 47 text

상황에 맞는 객체를 내 마음대로 주입할 수 있다. isToggleSelectedActivity가 true인 경우 isToggleSelectedActivity가 false인 경우

Slide 48

Slide 48 text

interface MainView 테스트 코드 상에서 실행하기 힘들었던 MainActivity를, 테스트용 View로 바꿀수 있다 True를 반환하는 Activity Example False를 반환하는 Activity Constructor

Slide 49

Slide 49 text

이렇게 가짜 객체를 만드는 걸 Mocking 이라고 이해하면 될 것 같다!

Slide 50

Slide 50 text

이런 경우… 메소드 안에서 Intent 객체를 새로 생성하는 상황

Slide 51

Slide 51 text

마찬가지로 에러를 맛보게 됩니다…

Slide 52

Slide 52 text

Context, Intent, Bundle 처럼 안드로이드에 의존하는 객체들은 Mocking을 해주던지, build option을 바꿔줘야 함

Slide 53

Slide 53 text

빌드 옵션을 바꾸어도 내가 원하는 대로 동작하지 않음!

Slide 54

Slide 54 text

Mockito등을 이용해 Mocking을 하더라도 활용할 수가 없다. (객체가 메소드 안에서 만들어지기 때문)

Slide 55

Slide 55 text

어떻게 해결할까?

Slide 56

Slide 56 text

의존성 주입(DI)를 적극적으로 활용하거나 Factory pattern 비스무리한 모양을 이용해보자!

Slide 57

Slide 57 text

함수 Parameter로 주입 받는 경우

Slide 58

Slide 58 text

Factory 패턴을 흉내내서 만든 Injector (PowerMock을 이용하여 static class mocking 가능)

Slide 59

Slide 59 text

그 외 Dagger나 Koin같은 DI library 사용도 고려할 수 있습니다.

Slide 60

Slide 60 text

내가 만든 mock 객체를 주입해서 테스트 할 수 있다.

Slide 61

Slide 61 text

1. 인터페이스와 추상이 어떤 효과를 갖는지 알겠다! 2. 다형성에서 말하는 갈아 끼운다가 어떤 뜻인지 알겠다! 3. 의존성 주입이 테스트에 어떤 영향을 미치는지 알겠다!

Slide 62

Slide 62 text

덩치가 큰 메소드

Slide 63

Slide 63 text

Slide 64

Slide 64 text

뭘 테스트 해야 하지…?

Slide 65

Slide 65 text

쓰레드 시작하면서 토큰 정의

Slide 66

Slide 66 text

Connection 정의하면서 파라미터 추가 버퍼 생성

Slide 67

Slide 67 text

받아온 데이터 Json 파싱

Slide 68

Slide 68 text

액티비티 전환

Slide 69

Slide 69 text

Firebase 데이터 전송 및 Toast 띄우기

Slide 70

Slide 70 text

이 메소드가 하는 일이 너무 많아서 테스트 해야 할 게 너무 많다!!

Slide 71

Slide 71 text

메소드 크기를 작게 유지해야 테스트 하기 편하겠다!

Slide 72

Slide 72 text

Connection 생성해서 데이터 받아오는 메소드 -> 제대로 받아오는지 테스트

Slide 73

Slide 73 text

받아온 Json 데이터를 파싱하는 메소드 -> 예제 데이터를 넣고 제대로 파싱하는지 테스트

Slide 74

Slide 74 text

액티비티 전환 및 Toast 실행 메소드 -> 내가 의도한 인터페이스가 실행되는지 테스트

Slide 75

Slide 75 text

앞서 설명한 것들을 전부 묶어서 Integration Test!

Slide 76

Slide 76 text

Unit test의 효과

Slide 77

Slide 77 text

애매했던 객체 지향 프로그래밍의 개념들에 대한 이해 인터페이스와 다형성, DI에 대해!

Slide 78

Slide 78 text

테스트 하기 좋은 코드에 대해 고민하기 시작

Slide 79

Slide 79 text

TDD, 개발 방법론, 소프트웨어 아키텍처

Slide 80

Slide 80 text

CI에서의 Test case 빌드 시 테스트 케이스를 모두 실행 내 수정사항으로 인해 다른 테스트 케이스가 실패한다면? 프로그램에 버그가 발생할 가능성이 있다는 것!

Slide 81

Slide 81 text

Open Source 에서의 Test case 코드를 보는 것 vs 테스트 코드를 보는 것

Slide 82

Slide 82 text

유닛 테스트를 작성함으로써 코드의 품질을 높일 수 있다! (시작이 반이라고..)

Slide 83

Slide 83 text

UI Test 까지!

Slide 84

Slide 84 text

Bixby UI Test 많은 종류의 사용자 명령 … 어떻게 테스트 하지?

Slide 85

Slide 85 text

UI Automator2 외부에서 앱을 조작해주는 테스트 라이브러리 (Android Accessibility 이용)

Slide 86

Slide 86 text

이렇게 컴포넌트를 쉽게 찾고

Slide 87

Slide 87 text

이벤트도 쉽게 발생시킬 수 있다!

Slide 88

Slide 88 text

또한 하드웨어 버튼 이벤트도 발생시킬 수 있다!

Slide 89

Slide 89 text

Device 객체를 만들고

Slide 90

Slide 90 text

Home 버튼을 누르고

Slide 91

Slide 91 text

Package 이름을 통해 앱을 찾는다.

Slide 92

Slide 92 text

또한 패키지 이름을 통해 앱을 실행시킨다.

Slide 93

Slide 93 text

앱이 실행될 때 까지 기다린다.

Slide 94

Slide 94 text

Resource ID를 기준으로 View를 찾고, 텍스트를 넣어준다.

Slide 95

Slide 95 text

Resource ID 기준으로 View를 찾고 클릭한다.

Slide 96

Slide 96 text

Resource ID가 “testToBeChanged” 인 View가 나타날 때 까지 기다린다.

Slide 97

Slide 97 text

View에 text가 의도한 결과와 같은지 비교한다.

Slide 98

Slide 98 text

기계적으로 반복해야 하는 검증을 자동화 할 수 있다.

Slide 99

Slide 99 text

날씨 알려줘, 맛집 알려줘, 알람 맞춰줘, …

Slide 100

Slide 100 text

하드웨어 이벤트, 다양한 기준으로 View를 찾고 이벤트를 발생시킬 수 있는 강력한 라이브러리!

Slide 101

Slide 101 text

꼭 한번 사용해보세요 :)

Slide 102

Slide 102 text

감사합니다.