付費限定

🔀UUID 的隨機特性很好,測試的困難就交給 Swift Dependencies

13-avatar-img
發佈於📦 推薦 Swift Package 個房間
更新於 發佈於 閱讀時間約 12 分鐘

上一篇 Swift Dependencies 文章以 Date 為範例,相信讀者已經體會到,即使是時間這麼基本的型別,也可以造成測試上的困難。而 Swift Dependencies 可以在測試環境下,替換掉當下的系統時間,使得測試時的行為能夠符合預期。

在這篇文章中,我們繼續延伸昨天的例子,加深印象的同時多介紹一點概念。

在一個筆記 app 中,指定 id 來存取特定一篇筆記,是很常見的需求。所以,我們打算把 Note 加上 id 欄位,並且使用 UUID 型別,以確保唯一性。

UUID 唯一性的用途

UUID 的特性就是在產生時會有唯一性、不會重複。這對於確保資料之間不會衝突,是非常好的特性。

但是,如果我們直接寫 let id = UUID(),就會跟上一篇的 Date() 發生一樣的問題──無法控制產生的結果。

struct Note {  // v5
let id = UUID() // 新增 id 欄位,隨機產生
let createdDate: Date
var modifiedDate: Date
var text: String = "" {
didSet {
@Dependency(\.date.now) var date
modifiedDate = date
}
}

init() {
@Dependency(\.date.now) var date
self.createdDate = date
self.modifiedDate = date
}
}

不控制 UUID 產生的結果,就不好測試

大部分情況,其實我們並不在意 UUID 的值,因為相信系統會做到產生唯一、不衝突的值,就夠了。

但假如我們把它當成某個關鍵邏輯的參考依據,那麼這種隨機特性,就會讓測試失敗。

舉例來說,我們會想要筆記有個穩定的排序規則,依照 modifiedDatetextid 這三個條件。理論上時間與內文是有可能重複的(比如我們做了複製同一則筆記的功能),所以最後就以 id 為依據。

我們可以幫 Note 簡單地實作 Comparable protocol。如果你不熟悉這個比較 tuple 的語法,簡單來說它會由左到右依序比對 modifiedDatetext、最後才是 id

extension Note: Comparable {
static func < (lhs: Self, rhs: Self) -> Bool {
(lhs.modifiedDate, lhs.text, lhs.id) < (rhs.modifiedDate, rhs.text, rhs.id)
}
}

但是在測試時,無法得到穩定的結果。

@Test(
"[non-deterministic] Ensure note default sorting order - will fail randomly"
)
func sortNotesWillFail() {
let notes = withDependencies {
$0.date.now = .init(timeIntervalSinceReferenceDate: 0)
} operation: {
[Note(), Note(), Note()]
}

let sorted = notes.sorted(by: <)

// UUID() 是隨機的,即使 `modifiedDate`、`text` 相同,也無法預測排序後的順序
#expect(notes == sorted)
#expect(notes[0] == sorted[0])
}
💡技術細節:
各種程式語言的 UUID 主要是參照 RFC 4122,並且有多種版本。

有幾個版本的 UUID,具備 time-ordered 的特性(例如 UUIDv7),產出的 id 直接當字串來排序,就具備時間遞增的效果。這類 UUID 能兼顧唯一性與遞增排序,特別適用於一些資料庫的應用。

而 Swift Foundation 的 UUID 是依照 RFC 4122 version 4 的規格產生的。它會參考當下時間產生,但是產出的隨機字串並沒有遞增特性。所以連續呼叫的 UUID() 的結果,不會是穩定的順序。

透過 Swift Dependencies 的 UUIDGenerator 來控制產生結果

就像 DateSwift Dependencies 也內建 UUID 的注入方式。方法是:@Dependency(\.uuid) var uuid

以行動支持創作者!付費即可解鎖
本篇內容共 4467 字、0 則留言,僅發佈於💡 實用技巧、📦 推薦 Swift Package你目前無法檢視以下內容,可能因為尚未登入,或沒有該房間的查看權限。
留言
avatar-img
留言分享你的想法!
avatar-img
13+
1.5K會員
82內容數
13 以 10+ 年 iOS 開發經驗為基礎撰寫,助你在 AI 時代成為更有自信的技術工作者。 ❤️ 支持 13 創作! 🤖 AI 工具實戰經驗與深度思考 🧠 軟體開發思維、職涯發展建議 💡 實用技巧與踩坑經驗分享 😔 開發者身心健康與職業傷害
13+的其他內容
2025/09/07
Swift Dependencies 是我最常使用的套件。它讓外部條件變成完全可控,解決了測試困難和 SwiftUI Preview 編譯緩慢的問題。使用它以後,我在區分元件職責、設計測試的功力都大幅提升。
Thumbnail
2025/09/07
Swift Dependencies 是我最常使用的套件。它讓外部條件變成完全可控,解決了測試困難和 SwiftUI Preview 編譯緩慢的問題。使用它以後,我在區分元件職責、設計測試的功力都大幅提升。
Thumbnail
2025/08/28
下載官方 App、預習活動時間表與交通資訊、提前抵達,用愉快的心情享受兩天的活動!
Thumbnail
2025/08/28
下載官方 App、預習活動時間表與交通資訊、提前抵達,用愉快的心情享受兩天的活動!
Thumbnail
2025/08/27
即使在現實中不擅長聊天,也可以享受研討會的互動。稍微做點準備即可!不論社交能力如何,這篇文章談到的準備適用於任何人。
Thumbnail
2025/08/27
即使在現實中不擅長聊天,也可以享受研討會的互動。稍微做點準備即可!不論社交能力如何,這篇文章談到的準備適用於任何人。
Thumbnail
看更多
你可能也想看
Thumbnail
透過蝦皮分潤計畫,輕鬆賺取零用金!本文分享5-6月實測心得,包含數據流程、實際收入、平臺優點及注意事項,並推薦高分潤商品,教你如何運用空閒時間創造被動收入。
Thumbnail
透過蝦皮分潤計畫,輕鬆賺取零用金!本文分享5-6月實測心得,包含數據流程、實際收入、平臺優點及注意事項,並推薦高分潤商品,教你如何運用空閒時間創造被動收入。
Thumbnail
單身的人有些會養寵物,而我養植物。畢竟寵物離世會傷心,植物沒養好再接再厲就好了~(笑)
Thumbnail
單身的人有些會養寵物,而我養植物。畢竟寵物離世會傷心,植物沒養好再接再厲就好了~(笑)
Thumbnail
不知你有沒有過這種經驗?衛生紙只剩最後一包、洗衣精倒不出來,或電池突然沒電。這次一次補貨,從電池、衛生紙到洗衣精,還順便分享使用心得。更棒的是,搭配蝦皮分潤計畫,愛用品不僅自己用得安心,分享給朋友還能賺回饋。立即使用推薦碼 X5Q344E,輕鬆上手,隨時隨地賺取分潤!
Thumbnail
不知你有沒有過這種經驗?衛生紙只剩最後一包、洗衣精倒不出來,或電池突然沒電。這次一次補貨,從電池、衛生紙到洗衣精,還順便分享使用心得。更棒的是,搭配蝦皮分潤計畫,愛用品不僅自己用得安心,分享給朋友還能賺回饋。立即使用推薦碼 X5Q344E,輕鬆上手,隨時隨地賺取分潤!
Thumbnail
身為一個典型的社畜,上班時間被會議、進度、KPI 塞得滿滿,下班後只想要找一個能夠安靜喘口氣的小角落。對我來說,畫畫就是那個屬於自己的小樹洞。無論是胡亂塗鴉,還是慢慢描繪喜歡的插畫人物,那個專注在筆觸和色彩的過程,就像在幫心靈按摩一樣,讓緊繃的神經慢慢鬆開。
Thumbnail
身為一個典型的社畜,上班時間被會議、進度、KPI 塞得滿滿,下班後只想要找一個能夠安靜喘口氣的小角落。對我來說,畫畫就是那個屬於自己的小樹洞。無論是胡亂塗鴉,還是慢慢描繪喜歡的插畫人物,那個專注在筆觸和色彩的過程,就像在幫心靈按摩一樣,讓緊繃的神經慢慢鬆開。
Thumbnail
這篇文章探討瞭如何在iOS應用程式中客製化Alert,包括改變字體大小、內嵌連結以及讓Alert的高度隨著字數增長並提供scroll操作。同時使用SwiftUI進行客製化,並介紹瞭解決高度超出範圍後文字捲動與scrollView固定高度的方法。
Thumbnail
這篇文章探討瞭如何在iOS應用程式中客製化Alert,包括改變字體大小、內嵌連結以及讓Alert的高度隨著字數增長並提供scroll操作。同時使用SwiftUI進行客製化,並介紹瞭解決高度超出範圍後文字捲動與scrollView固定高度的方法。
Thumbnail
本文介紹瞭如何在SwiftUI中調整元件的對齊方式,包括置中、向左/向右/向上/向下對齊的方法。透過調整HStack、VStack以及frame的maxWidth、maxHeight和alignment屬性,可以達到想要的對齊效果。
Thumbnail
本文介紹瞭如何在SwiftUI中調整元件的對齊方式,包括置中、向左/向右/向上/向下對齊的方法。透過調整HStack、VStack以及frame的maxWidth、maxHeight和alignment屬性,可以達到想要的對齊效果。
Thumbnail
本文檔介紹了在Swift中使用套件的詳細方法,包括如何引用第三方套件和自定義模組,如何創建自定義套件,以及一些常見的Swift套件。這些套件可以幫助開發者快速添加功能到項目中,提高開發效率和程式碼品質。
Thumbnail
本文檔介紹了在Swift中使用套件的詳細方法,包括如何引用第三方套件和自定義模組,如何創建自定義套件,以及一些常見的Swift套件。這些套件可以幫助開發者快速添加功能到項目中,提高開發效率和程式碼品質。
Thumbnail
本章節介紹了如何建立並設置Swift項目以及如何選擇和設置Swift代碼編輯器。這包括在Xcode和命令行中建立Swift項目,選擇Xcode、Visual Studio Code或AppCode作為編輯器,以及如何使用SPM安裝插件。
Thumbnail
本章節介紹了如何建立並設置Swift項目以及如何選擇和設置Swift代碼編輯器。這包括在Xcode和命令行中建立Swift項目,選擇Xcode、Visual Studio Code或AppCode作為編輯器,以及如何使用SPM安裝插件。
Thumbnail
這份文件的目的是介紹Swift語言,包括它的特性、應用範疇,以及誰在使用它。它也提供了一些學習Swift的資源和工具,以及一些常見的Swift庫和框架。
Thumbnail
這份文件的目的是介紹Swift語言,包括它的特性、應用範疇,以及誰在使用它。它也提供了一些學習Swift的資源和工具,以及一些常見的Swift庫和框架。
Thumbnail
需求情境: 在設計畫面時,資料來源是後台的 api,每一次畫面細節的修修改改,都會觸發 Xcode Preview 程序,導致不斷呼叫後台。此時若資料結構和大小都具有一定規模,就會導致效率低落,不斷等待,且消耗伺服器資源甚鉅。 解決方案: 將後台傳回的資料以檔案形式暫存在本地端,每次 pr
Thumbnail
需求情境: 在設計畫面時,資料來源是後台的 api,每一次畫面細節的修修改改,都會觸發 Xcode Preview 程序,導致不斷呼叫後台。此時若資料結構和大小都具有一定規模,就會導致效率低落,不斷等待,且消耗伺服器資源甚鉅。 解決方案: 將後台傳回的資料以檔案形式暫存在本地端,每次 pr
Thumbnail
Part.1 搞定基本的 UI 開始開發 iOS App。 首先準備一台 Mac,然後安裝 Xcode,新增專案,系統即刻生成基本的專案結構。coding 的起點在檔案 ContentView.swift: import SwiftUI struct ContentView: View {  
Thumbnail
Part.1 搞定基本的 UI 開始開發 iOS App。 首先準備一台 Mac,然後安裝 Xcode,新增專案,系統即刻生成基本的專案結構。coding 的起點在檔案 ContentView.swift: import SwiftUI struct ContentView: View {  
Thumbnail
只是 Swift 以 language level 支援 Optional 確實比用 API level 支援的 Java 要簡潔和更具可讀性。Swift 作為一個全新的語言,從一開始的設計就將許多好的語言特性加入,確實讓人驚豔。
Thumbnail
只是 Swift 以 language level 支援 Optional 確實比用 API level 支援的 Java 要簡潔和更具可讀性。Swift 作為一個全新的語言,從一開始的設計就將許多好的語言特性加入,確實讓人驚豔。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News