90
? 王王王 , Terry Wang 2015/ November/ 14 Unit test 101 Confidential. Wang Terry, Chuan Yun, all rights reserved.

Unit test and singleton

Embed Size (px)

Citation preview

Page 1: Unit test and singleton

?王泰瑞 , Terry Wang 2015/ November/ 14

Unit test 101

Confidential. Wang Terry, Chuan Yun, all rights reserved.

Page 2: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• How to write unit test cases?• Unit test tools

• 請大家先下載 scrum poker App

這次不會講到什麼東西?

Page 3: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• How to write testable code?• Testable code = OO + dependency injection• 閒聊一下 singleton

• 請大家先下載 scrum poker App

這次會講到什麼東西?

Page 4: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

先來聊聊 singleton

Page 5: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

隨堂考

Page 6: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• Singleton 好不好?singleton

Page 7: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• Singleton 好不好?• Global 變數是好還是不好?

singleton

Page 8: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• Singleton 其實是一種 Global 變數• 同意嗎?

singleton

Page 9: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 幾個 global variable?singleton

Page 10: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 其實,理論上,可以有無限個• WHY?

singleton

Page 11: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• singleton 很麻煩的是,當 getInstance() 被呼叫的時候,就生成了一整個真的 instance 出來

• 無法 dependency injection• 所以很難測試• 到底什麼是 dependency injection??• 來估計一下吧!

singleton

Page 12: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

先喘一下

Page 13: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

來拿 Emma 的 code 當例子

Page 14: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• Emma 下層是 Smack ,處理把”安安您好幾歲住哪“變成 Xmpp 格式的訊息的收送

• Smack 上層有個 XmppSdkAdapterLevel1 的 class

Emma 長怎樣

Page 15: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 下面接一堆網路的東西 , library 等等 ... 很肥 der

• 我挑了這個 Method:

• 它吃一個 Packet 物件當作參數,回傳 boolean ,或是丟出例外

我想測 XmppSdkAdapterLevel1

Page 16: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 先丟一個 null 進去看看• paranoid coding?

於是我寫了 unit test code

Page 17: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• NPE ,但不是傳進去的參數的問題,而是 init 的時候錯了

unit test 跑出來的結果是 ...?

Page 18: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• init 出 XmppSdkAdapterLevel1 的時候,需要context 物件

我們遇到了什麼問題?

Page 19: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• init 出 XmppSdkAdapterLevel1 的時候,需要context 物件

• XmppSdkAdapterLevel1 一千多行,你好大,我好怕

我們遇到了什麼問題?

Page 20: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• init 出 XmppSdkAdapterLevel1 的時候,需要context 物件

• XmppSdkAdapterLevel1 一千多行,你好大,我好怕• XmppSdkAdapterLevel1 是個 singleton

我們遇到了什麼問題?

Page 21: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• init 出 XmppSdkAdapterLevel1 的時候,需要context 物件

• XmppSdkAdapterLevel1 一千多行,你好大,我好怕• XmppSdkAdapterLevel1是個 singleton

• 這才是最核心的問題

我們遇到了什麼問題?

Page 22: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• “Tests trump Encapsulation.”• from “The Little Singleton” by Uncle Bob, • clean code, clean coder 的作者

• 原本 singleton 的 instance 長這樣:

• WTF? XmppManager?

XmppSdkAdapterLevel1 是個 singleton

Page 23: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 我們改成這樣

• 改名+破壞了封裝

XmppSdkAdapterLevel1 是個 singleton

Page 24: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 來改寫 unit test code 吧!

• 我們用 Mock 物件覆寫了 sInstance• 下一步是… ? 處理紅字 and 想辦法拿到 unit test 的

Context 物件

XmppSdkAdapterLevel1 是個 singleton

Page 25: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 處理紅字 • 用 inner class

• 想辦法拿到 unit test 的 Context 物件• 用 AndroidTestCase

XmppSdkAdapterLevel1 是個 singleton

Page 26: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 發現建構子哭哭了XmppSdkAdapterLevel1 是個 singleton

Page 27: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 發現建構子哭哭了• and 要想辦法把

Context 塞進去啊!

XmppSdkAdapterLevel1 是個 singleton

Page 28: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 要想辦法把 Context 塞進去啊!• 來寫一個新的建構子:XmppSdkAdapterLevel1 是個 singleton

Page 29: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 再回來寫 unit test code :XmppSdkAdapterLevel1 是個 singleton

Page 30: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 終於可以開始測試了 !!XmppSdkAdapterLevel1 是個 singleton

Page 31: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• test 結果是綠燈XmppSdkAdapterLevel1 是個 singleton

Page 32: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

喘一下想一下

我們解決了什麼問題?

Page 33: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• init 出 XmppSdkAdapterLevel1 的時候,需要context 物件

• XmppSdkAdapterLevel1 一千多行,你好大,我好怕• XmppSdkAdapterLevel1 是個 singleton

我們解決了什麼問題?

Page 34: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 透過 AndroidTestCase 拿 Context 物件• 適度的破壞封裝• 使用 Mock 物件• 把 Context 放在 Constructor 的參數傳進去• 這就是 Dependency Injection其中的一招

我們怎麼解決的?

Page 35: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

剛剛傳了一個 Null現在來傳一個 Mock 的 Packet 吧

Page 36: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 一樣, Mock 出一個 MockPacket class傳假的 Packet 物件

Page 37: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 寫一個新的 test function傳假的 Packet 物件

Page 38: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 結果是紅燈

• 因為 sendPacket() 回傳值為 false• 為什麼是 false?? 進去看看囉~

傳假的 Packet 物件

Page 39: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 好像是還沒 connected• 那怎麼辦?

進來看看 sendPacket()

Page 40: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 好像是還沒 connected• 那怎麼辦?• 解法 A: 進去看 isConnected() ,並且想辦法把他弄到

變成 true

• 會很麻煩,但看起來,專心搞個三個小時是有機會的

進來看看 sendPacket()

Page 41: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 好像是還沒 connected• 那怎麼辦?• 解法 B: MockXmppAdapterLevel1 覆寫

isConnected()

進來看看 sendPacket()

Page 42: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 幹,兩個都爆了再跑一次 unit test

Page 43: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 先來解 Null 的那個• 一看錯誤訊息,原來是 NPE ,真的是因為傳了 Null

進去造成的

再跑一次 unit test

Page 44: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 怎麼處理比較好?• 解法 A: 繼續往外拋出例外• 解法 B: 用個 if 判斷, null 的話回傳 false• 解法 C: 默默自己 catch 起來

• 因為這個 method 會開給上層用,我決定解法 A

Null Pointer Exception 是個有深度的問題

Page 45: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

繼續往外拋出例外

Page 46: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 剩另外一個

• 居然又是 NPE• 沒道理啊,我傳的不是 Null 啊• 進去看看

再跑一次 unit test

Page 47: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 原來是 mConnection 為 null• 那怎麼辦?

再進來看看 sendPacket

Page 48: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 一樣用 Dependency Injection 的技巧, Mock 一個connection ,並把它當作新的參數傳進 Mock 的XmppAdapterLevel1 的 constructor

mConnection 為 null

Page 49: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

在 Unit test code 裡 Mock 出一個 XmppConnection 物件

Page 50: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• MockXmppAdapterLevel1 要塞進 connection 到新的 constructor

把 XmppConnection 放進 XmppSdkAdapterLevel1 的 constructor

Page 51: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• XmppSdkAdapterLevel1把 XmppConnection 放進 XmppSdkAdapterLevel1 的 constructor

Page 52: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• unit test code

• 使用 Setup()• Member

variables• Shorter test

methods

整理一下

Page 53: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 幹,兩個又都爆了

• 進去 XMPPConnection.sendPacket 看看

再跑一次 unit test

Page 54: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 有兩個東西要注意: isConnected() 跟 packetWriter• 可以繼續使用 dependency injection ,一路做下去 or

看看 XMPPConnection 的 sendPacket()

Page 55: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 可以繼續使用 dependency injection ,一路做下去 or …• 我們可以直接覆寫MockXmppConnection的 sendPacket()• 為甚麼不一直做下去?

其實我們現在在測 XmppSdkAdapterLevel1 的 sendPacket

Page 56: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 裡面什麼都不做覆寫 MockXmppConnection 的 sendPacket

Page 57: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 綠燈再跑一次 unit test

Page 58: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

喘一下想一下

我們怎麼解決的?

Page 59: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 大量使用 Mock 物件• 適度覆寫• 把 Mock 物件放在 Constructor 的參數傳進去• Dependency Injection

我們怎麼解決的?

Page 60: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

下一步呢?

Page 61: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 寫多一點 unit test case• 比如說,離線狀態呢?• 比如說,其他奇怪的 Packet 呢?正常的 Packet 呢?

• 都可以用 Mock object 來做• 這一個 method 就功德圓滿了~~~阿彌陀佛

下一步呢?

Page 62: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

喘一下想一下

我們到目前為止做了什麼?

Page 63: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 學會了 Dependency Injection

• 可以不用真正建立起 Xmpp 的連線,而測試 Xmpp 的sendPacket方法的正確性

• 如果照樣照句的話:• 可以不用真正建立起 XXXX連線,而測試 XXXX 的 OOO方法

的正確性

我們到目前為止做了什麼?

Page 64: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

我覺得還蠻酷的

Page 65: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

你覺得呢?

Page 66: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

接下來我們來想想 unit test 的本質

Page 67: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• unit test 就是測一個 method 的正確性到底 unit test 是什麼

我是一個 method

Page 68: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• method 或許有 input ,就是參數的意思到底 unit test 是什麼

Input

我是一個 method

Page 69: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• Method也或許有 output ,就是回傳值的意思到底 unit test 是什麼

Input output

我是一個 method

Page 70: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 當然,也有可能會拋出例外到底 unit test 是什麼

Input output

Exception

我是一個 method

Page 71: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 每個 method 裡面都有自己的邏輯到底 unit test 是什麼

我是一個 method

Input output

Exception

邏輯

Page 72: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 這些邏輯,常常需要呼叫別的 Method ,拿到他的 output後,完成自己的邏輯到底 unit test 是什麼

我是一個 method

Input output

Exception

邏輯別的 method

Page 73: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

我是一個 method

• 我們要測的是橘色的部分,也就是 input與 output ( + exception) 的關係

到底 unit test 是什麼

Input output

Exception

邏輯別的 method

Page 74: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 灰色的別的 method ,我們不用管他,所以我們需要 mock 的物件來做灰色的部分到底 unit test 是什麼

我是一個 method

Input output

Exception

邏輯

請Mock我

Page 75: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

而這就是 unit test 的本質

Input output

Exception

邏輯

Page 76: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

所以我們需要 Dependency injection來幫忙 unit test

Page 77: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

• 因為“測試贏”,所以我們克服了.• 但是感覺好像開了後門,藉由破壞封裝而破壞了” singleton-ness” ,這其實不好.• 所以,接下來在寫程式的時候,要寫 singleton 又想要做 unit test 的話,要真的想清楚唷~~~

Emma 的程式裡面 已經有太多 singleton 了

Page 78: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

啾咪~

Page 79: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

Page 80: Unit test and singleton

[email protected]. Wang Terry, Chuan Yun, all rights reserved

?Question Time!

Terry Wang

Page 81: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

我知道大家都很聰明都沒問題

Page 82: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

我來問問題好了

Page 83: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

如果一個 class 的建構式需要很多參數比如說 40 個好了那我不是 Mock 到死 ?

Page 84: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

如果一個 class A 在很深的地方比如說 離 UI 層 40 個 new 的地方而這個 class A 的建構式需要另一個 class B 當參數而前 39 個其他的 class 都沒用到 class B只有第一層有用到所以我從第一層一路傳 B 下去給 A?那我不是 Mock 到死?

Page 85: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

為什麼 Clean code 說函式的參數要越 __越好?

Page 86: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

假設我們有一個 method吃一個 int 參數參數的正常值是 0 ~ 10我們理論上要寫幾個 unit test cases?

Page 87: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

為什麼不測 private methods?如果拰杯偏偏就是要測怎麼辦 ?

Page 88: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

使用 reflection?Why?

Why not?

Page 89: Unit test and singleton

Confidential. Wang Terry, Chuan Yun, all rights reserved.

你說 singleton 不好可是 Android 的 code 一缸子 singleton比如說 WifiManager, XXXXManager 等等都碼是 singleton 啊~

Page 90: Unit test and singleton

[email protected]. Wang Terry, Chuan Yun, all rights reserved

?Question Time!

Terry Wang