3.0 ZIO测试
3.0 測試ZIO程序
除了編寫表達我們期望的邏輯的程序外,測試這些程序以確保其行為符合我們的期望也很重要。
這對于ZIO及其生態系統中的庫尤其重要,因為ZIO的主要重點是可組合性,這意味著我們可以從少量構件和操作中組合出針對更復雜問題的解決方案,以將它們組合在一起。
僅當每個構造塊和操作員都對預期行為的保證表示擔保時,才可以執行此操作。
因此我們需要保證:方案提供的是我們想要的 例如,考慮這個簡單的程序。
該程序只是嘗試將兩個整數相除,如果已定義則返回結果,如果未定義則返回失敗,例如,因為我們被零除。
如果我們熟悉上一章中的運算符,則該程序看起來非常簡單,并且其行為對于我們來說似乎很明顯。 但是我們能夠以這種方式進行推理的唯一原因是,每個構造函數和將它們組合在一起的每個運算符都具有一定的保證。
在上面的示例中,effect構造函數保證它會捕獲在評估其參數時拋出的任何非致命異常,并將該異常作為ZIO效果的失敗結果返回,否則,返回將其計算結果作為ZIO成功的結果。
effect構造函數必須捕獲任何非致命異常,無論其類型如何,并且每次都必須捕獲異常。如果沒有拋出異常,它必須返回其計算的結果,并且不能以任何方式更改該結果。
這可以使我們推斷出,當我們在ZIO.effect構造函數中對兩個數字進行除法時,如果得到除法結果,則將獲得成功的ZIO效果,如果計算過程中拋出任何錯誤,則將獲得錯誤的沒有正確值ZIO effect。
同樣,catchAll操作需要一個錯誤處理函數,并把函數應用于錯誤的結果,如果原始效果失敗,則返回錯誤處理程序的結果,如果成功,則返回原始效果的成功結果。
在這種情況下,這些保證相對明顯,我們甚至可能無需考慮它們。但是,隨著我們在本書中學習得更多,我們將看到ZIO的很多功能來自它給我們的保證,這些保證并不那么明顯,例如,如果獲取了資源,它將始終被釋放,或者如果我們的程序被中斷它的所有部分都將立即盡快關閉。
這些強大的保證,以及理解我們一起編寫不同程序時如何應用這些保證,是我們構建復雜程序的方式,這些程序對于我們自己和我們的用戶仍然具有非常強大的安全性和效率性。因此,能夠通過測試來驗證我們正在創建的組件確實確實兌現了我們認為至關重要的保證。
當然,Scala中已經有各種其他測試框架。例如,以下是我們如何使用ScalaTest庫測試簡單的斷言的方法,您可能已經在有關Scala的入門課程之一中學到了這一點。
這行得通,但是我們想去測試ZIO effect會遇到一些麻煩。 例如,這是測試有關ZIO效果的簡單斷言的初步嘗試。
class ExampleSpec2 extends FunSuite {test("addition works") {assert(ZIO.succeed(1 + 1) === 2)}}可以編譯,但是該測試沒有任何意義,并且會始終失敗,因為我們正在比較兩種完全不相關的類型。 左側是ZIO效果,它是并發程序的藍圖,該程序最終將返回Int,而右側僅是Int。
我們真正想要的不是說ZIO.succeed(1 +1)等于2,而是求ZIO.succeed(1 +1)的結果等于2。
我們可以通過創建ZIO運行時并使用其unsafeRun方法運行ZIO效果,將并發程序的ZIO藍圖轉換為實際運行該程序的結果來表達這一點。 這類似于ZIO App特性在上一章中自動為我們所做的。
該測試現在很有意義,可以照原樣通過,但是仍然存在一些問題。
首先,這在Scala.js上根本不起作用。 unsafeRun方法運行ZIO效果以產生一個值,這意味著它需要一直阻塞直到結果可用,但我們無法在Scala.js上阻塞!我們可以使用更復雜的方法,在ZIO效果上運行一個scala.concurrent.Future,然后與ScalaTest中的 函數式接口 以對Future值進行斷言,但是我們已經在這里引入了相當多的復雜性,因為它應該是簡單的測試。
另外,還有一個更根本的問題。 ScalaTest對ZIO,其環境類型,其錯誤類型或ZIO支持的任何操作一無所知。因此,在實現與測試相關的功能時,ScalaTest無法利用ZIO的任何功能。
例如,ScalaTest具有用于使耗時太長的測試超時的功能。但是由于正如我們在上一章中了解到的那樣,“未來”是不可中斷的,因此“超時”只是在指定的持續時間之后無法通過測試。測試仍在運行在后臺,可能會消耗系統資源。
ZIO支持中斷,但是ScalaTest的超時無法與這種中斷集成,因為ScalaTest對ZIO一無所知,除非我們手動完成一些管道工作,否則我們將無法進行自己的工作。
從根本上講,問題在于大多數測試庫將 effect 視為二等公民。 它們只是運行以生成“真實”值(例如Int,String或可能是Future)的東西,而這些正是測試框架可以理解的東西。
這樣的結果是,當我們使用這樣的測試框架編寫測試時,最終放棄了ZIO的所有功能,這很痛苦,因為我們剛剛習慣于使用ZIO的功能和可編寫性來編寫生產代碼。
總結
- 上一篇: mpaaS的kylin框架-项目结构(脚
- 下一篇: 知乎凡尔赛沙雕语录,究竟有多沙雕?