diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..c46f8d5c5d73108a696219f6217a31d2ff4b5a46
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,24 @@
+before_script:
+  - for ip in $(dig @8.8.8.8 github.com +short); do ssh-keyscan github.com,$ip; ssh-keyscan $ip; done 2>/dev/null >> ~/.ssh/known_hosts
+  - for ip in $(dig @8.8.8.8 git.xx.network +short); do ssh-keyscan git.xx.network,$ip; ssh-keyscan $ip; done 2>/dev/null >> ~/.ssh/known_hosts
+  - swift --version
+  - xcodebuild -version
+
+stages:
+  - test
+
+test-package-macos:
+  stage: test
+  tags: 
+    - ios
+  script:
+    - ./run-tests.sh macos
+  retry: 1
+
+test-package-ios:
+  stage: test
+  tags: 
+    - ios
+  script:
+    - ./run-tests.sh ios
+  retry: 1
diff --git a/Package.resolved b/Package.resolved
index fba7b308f7eec3bb9d3c4ad7391cd8369efd7900..57f42aceb83943cb7bab184c1b6e4f9275e6de3e 100644
--- a/Package.resolved
+++ b/Package.resolved
@@ -5,8 +5,8 @@
       "kind" : "remoteSourceControl",
       "location" : "https://github.com/groue/GRDB.swift",
       "state" : {
-        "revision" : "fead2ea634c1bf7dd81a3e02f796154992165ffd",
-        "version" : "5.24.0"
+        "revision" : "0ac435744a4c67c4ec23a4a671c0d53ce1fee7c6",
+        "version" : "6.0.0"
       }
     },
     {
@@ -14,8 +14,8 @@
       "kind" : "remoteSourceControl",
       "location" : "https://github.com/pointfreeco/swift-custom-dump.git",
       "state" : {
-        "revision" : "c4f78db9b90ca57b7b6abc2223e235242739ea3c",
-        "version" : "0.4.0"
+        "revision" : "c9b6b940d95c0a925c63f6858943415714d8a981",
+        "version" : "0.5.2"
       }
     },
     {
@@ -23,8 +23,8 @@
       "kind" : "remoteSourceControl",
       "location" : "https://github.com/pointfreeco/swift-snapshot-testing.git",
       "state" : {
-        "revision" : "f8a9c997c3c1dab4e216a8ec9014e23144cbab37",
-        "version" : "1.9.0"
+        "revision" : "f29e2014f6230cf7d5138fc899da51c7f513d467",
+        "version" : "1.10.0"
       }
     },
     {
@@ -32,8 +32,8 @@
       "kind" : "remoteSourceControl",
       "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay",
       "state" : {
-        "revision" : "50a70a9d3583fe228ce672e8923010c8df2deddd",
-        "version" : "0.2.1"
+        "revision" : "30314f1ece684dd60679d598a9b89107557b67d9",
+        "version" : "0.4.1"
       }
     }
   ],
diff --git a/Package.swift b/Package.swift
index a45412c2864f527026d2b7b4c3e3a5de7badcc4a..550624a500043b7f97be842115fc567d441dd5a0 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,17 +1,10 @@
-// swift-tools-version: 5.6
+// swift-tools-version: 5.7
 import PackageDescription
 
 let swiftSettings: [SwiftSetting] = [
-  // Uncomment to measure compilation time:
-  //.unsafeFlags(
-  //  [
-  //    "-Xfrontend",
-  //    "-debug-time-function-bodies",
-  //    "-Xfrontend",
-  //    "-debug-time-expression-type-checking",
-  //  ],
-  //  .when(configuration: .debug)
-  //),
+  //.unsafeFlags(["-Xfrontend", "-warn-concurrency"], .when(configuration: .debug)),
+  //.unsafeFlags(["-Xfrontend", "-debug-time-function-bodies"], .when(configuration: .debug)),
+  //.unsafeFlags(["-Xfrontend", "-debug-time-expression-type-checking"], .when(configuration: .debug)),
 ]
 
 let package = Package(
@@ -21,77 +14,47 @@ let package = Package(
     .macOS(.v12),
   ],
   products: [
-    .library(
-      name: "XXModels",
-      targets: ["XXModels"]
-    ),
-    .library(
-      name: "XXLegacyDatabaseMigrator",
-      targets: ["XXLegacyDatabaseMigrator"]
-    ),
-    .library(
-      name: "XXDatabase",
-      targets: ["XXDatabase"]
-    ),
+    .library(name: "XXModels", targets: ["XXModels"]),
+    .library(name: "XXLegacyDatabaseMigrator", targets: ["XXLegacyDatabaseMigrator"]),
+    .library(name: "XXDatabase", targets: ["XXDatabase"]),
   ],
   dependencies: [
-    .package(
-      url: "https://github.com/groue/GRDB.swift",
-      .upToNextMajor(from: "5.24.0")
-    ),
-    .package(
-      url: "https://github.com/pointfreeco/swift-custom-dump.git",
-      .upToNextMajor(from: "0.4.0")
-    ),
-    .package(
-      url: "https://github.com/pointfreeco/swift-snapshot-testing.git",
-      .upToNextMajor(from: "1.9.0")
-    ),
+    .package(url: "https://github.com/groue/GRDB.swift", .upToNextMajor(from: "6.0.0")),
+    .package(url: "https://github.com/pointfreeco/swift-custom-dump.git", .upToNextMajor(from: "0.5.2")),
+    .package(url: "https://github.com/pointfreeco/swift-snapshot-testing.git", .upToNextMajor(from: "1.10.0")),
+    .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay.git", .upToNextMajor(from: "0.4.1")),
   ],
   targets: [
     .target(
       name: "XXModels",
+      dependencies: [
+        .product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay"),
+      ],
       swiftSettings: swiftSettings
     ),
     .testTarget(
       name: "XXModelsTests",
       dependencies: [
-        .target(
-          name: "XXModels"
-        ),
+        .target(name: "XXModels"),
       ],
       swiftSettings: swiftSettings
     ),
     .target(
       name: "XXLegacyDatabaseMigrator",
       dependencies: [
-        .target(
-          name: "XXDatabase"
-        ),
-        .target(
-          name: "XXModels"
-        ),
-        .product(
-          name: "GRDB",
-          package: "GRDB.swift"
-        ),
+        .target(name: "XXDatabase"),
+        .target(name: "XXModels"),
+        .product(name: "GRDB", package: "GRDB.swift"),
+        .product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay"),
       ],
       swiftSettings: swiftSettings
     ),
     .testTarget(
       name: "XXLegacyDatabaseMigratorTests",
       dependencies: [
-        .target(
-          name: "XXLegacyDatabaseMigrator"
-        ),
-        .product(
-          name: "CustomDump",
-          package: "swift-custom-dump"
-        ),
-        .product(
-          name: "SnapshotTesting",
-          package: "swift-snapshot-testing"
-        ),
+        .target(name: "XXLegacyDatabaseMigrator"),
+        .product(name: "CustomDump", package: "swift-custom-dump"),
+        .product(name: "SnapshotTesting", package: "swift-snapshot-testing"),
       ],
       exclude: [
         "__Snapshots__",
@@ -107,26 +70,16 @@ let package = Package(
     .target(
       name: "XXDatabase",
       dependencies: [
-        .target(
-          name: "XXModels"
-        ),
-        .product(
-          name: "GRDB",
-          package: "GRDB.swift"
-        ),
+        .target(name: "XXModels"),
+        .product(name: "GRDB", package: "GRDB.swift"),
       ],
       swiftSettings: swiftSettings
     ),
     .testTarget(
       name: "XXDatabaseTests",
       dependencies: [
-        .target(
-          name: "XXDatabase"
-        ),
-        .product(
-          name: "CustomDump",
-          package: "swift-custom-dump"
-        ),
+        .target(name: "XXDatabase"),
+        .product(name: "CustomDump", package: "swift-custom-dump"),
       ],
       swiftSettings: swiftSettings
     ),
diff --git a/README.md b/README.md
index b470d2ddfad029a3ec1c5dcee3255b6f8356cc95..14e10d022a43ff88959758e2dbe5ef3b344fed9a 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,13 @@
 # xx-client-ios-db
 
-![Swift 5.6](https://img.shields.io/badge/swift-5.6-orange.svg)
+![Swift 5.7](https://img.shields.io/badge/swift-5.7-orange.svg)
 ![platform iOS macOS](https://img.shields.io/badge/platform-iOS_macOS-blue.svg)
 
 Database layer for xx Messenger iOS app.
 
 ## 🛠 Development
 
-Open `Package.swift` in Xcode (≥13).
+Open `Package.swift` in Xcode (≥14).
 
 ### Package structure
 
diff --git a/Sources/XXDatabase/Models/Message+GRDB.swift b/Sources/XXDatabase/Models/Message+GRDB.swift
index d242a67d2a48510bf27a123b8b8441546a715d05..9adda885d3b7d5ea3d19c466366b9668f77720cb 100644
--- a/Sources/XXDatabase/Models/Message+GRDB.swift
+++ b/Sources/XXDatabase/Models/Message+GRDB.swift
@@ -119,9 +119,7 @@ extension Message: FetchableRecord, MutablePersistableRecord {
     return columnAssignments
   }
 
-  public mutating func didInsert(with rowID: Int64, for column: String?) {
-    if column == Column.id.rawValue {
-      id = rowID
-    }
+  public mutating func didInsert(_ inserted: InsertionSuccess) {
+    id = inserted.rowID
   }
 }
diff --git a/Sources/XXLegacyDatabaseMigrator/Legacy/Contact.swift b/Sources/XXLegacyDatabaseMigrator/Legacy/Contact.swift
index cd42ecf4b435b46f875f20aff21895c203b7551b..1f5bb4ea1ad00c412a23b0c9c8fa19c00d65342e 100644
--- a/Sources/XXLegacyDatabaseMigrator/Legacy/Contact.swift
+++ b/Sources/XXLegacyDatabaseMigrator/Legacy/Contact.swift
@@ -37,9 +37,7 @@ extension Contact: FetchableRecord, MutablePersistableRecord {
 
   static let databaseTableName = "contacts"
 
-  mutating func didInsert(with rowID: Int64, for column: String?) {
-    if column == Column.id.rawValue {
-      id = rowID
-    }
+  mutating func didInsert(_ inserted: InsertionSuccess) {
+    id = inserted.rowID
   }
 }
diff --git a/Sources/XXLegacyDatabaseMigrator/Legacy/FileTransfer.swift b/Sources/XXLegacyDatabaseMigrator/Legacy/FileTransfer.swift
index 27b4a623854ecf934bcc2c337ab2461ba74618b3..d63afb1c88f098eb208cbe9028e9ad128909b8f4 100644
--- a/Sources/XXLegacyDatabaseMigrator/Legacy/FileTransfer.swift
+++ b/Sources/XXLegacyDatabaseMigrator/Legacy/FileTransfer.swift
@@ -17,9 +17,7 @@ extension FileTransfer: FetchableRecord, MutablePersistableRecord {
 
   static let databaseTableName = "transfers"
 
-  mutating func didInsert(with rowID: Int64, for column: String?) {
-    if column == Column.id.rawValue {
-      id = rowID
-    }
+  mutating func didInsert(_ inserted: InsertionSuccess) {
+    id = inserted.rowID
   }
 }
diff --git a/Sources/XXLegacyDatabaseMigrator/Legacy/Group.swift b/Sources/XXLegacyDatabaseMigrator/Legacy/Group.swift
index d2328defd36d4183411b974f1848afe5472aea45..6789f76720e9e7b495d601fca8c62ea8dc435b79 100644
--- a/Sources/XXLegacyDatabaseMigrator/Legacy/Group.swift
+++ b/Sources/XXLegacyDatabaseMigrator/Legacy/Group.swift
@@ -25,9 +25,7 @@ extension Group: FetchableRecord, MutablePersistableRecord {
 
   static let databaseTableName = "groups"
 
-  mutating func didInsert(with rowID: Int64, for column: String?) {
-    if column == Column.id.rawValue {
-      id = rowID
-    }
+  mutating func didInsert(_ inserted: InsertionSuccess) {
+    id = inserted.rowID
   }
 }
diff --git a/Sources/XXLegacyDatabaseMigrator/Legacy/GroupMember.swift b/Sources/XXLegacyDatabaseMigrator/Legacy/GroupMember.swift
index 244fa39dfaf1ee92024815b0c55fdb3b3d5411d6..f9efb997586e0e41b708efd593fdca693925219a 100644
--- a/Sources/XXLegacyDatabaseMigrator/Legacy/GroupMember.swift
+++ b/Sources/XXLegacyDatabaseMigrator/Legacy/GroupMember.swift
@@ -20,9 +20,7 @@ extension GroupMember: FetchableRecord, MutablePersistableRecord {
     case id, photo, status, userId, groupId, username
   }
 
-  mutating func didInsert(with rowID: Int64, for column: String?) {
-    if column == Column.id.rawValue {
-      id = rowID
-    }
+  mutating func didInsert(_ inserted: InsertionSuccess) {
+    id = inserted.rowID
   }
 }
diff --git a/Sources/XXLegacyDatabaseMigrator/Legacy/GroupMessage.swift b/Sources/XXLegacyDatabaseMigrator/Legacy/GroupMessage.swift
index 31c2be042944b761e2405833539487b6fd24cec4..8320ed7165fb55a326035a78bdab8c9869da86b6 100644
--- a/Sources/XXLegacyDatabaseMigrator/Legacy/GroupMessage.swift
+++ b/Sources/XXLegacyDatabaseMigrator/Legacy/GroupMessage.swift
@@ -30,9 +30,7 @@ extension GroupMessage: FetchableRecord, MutablePersistableRecord {
 
   static let databaseTableName = "groupMessages"
 
-  mutating func didInsert(with rowID: Int64, for column: String?) {
-    if column == Column.id.rawValue {
-      id = rowID
-    }
+  mutating func didInsert(_ inserted: InsertionSuccess) {
+    id = inserted.rowID
   }
 }
diff --git a/Sources/XXLegacyDatabaseMigrator/Legacy/Message.swift b/Sources/XXLegacyDatabaseMigrator/Legacy/Message.swift
index 25e58febd9a3fbcf749a356476d3353fe28c2a6e..e7a76d34a42abca21cfe3e17349dc696663a45a5 100644
--- a/Sources/XXLegacyDatabaseMigrator/Legacy/Message.swift
+++ b/Sources/XXLegacyDatabaseMigrator/Legacy/Message.swift
@@ -33,9 +33,7 @@ extension Message: FetchableRecord, MutablePersistableRecord {
 
   static let databaseTableName = "messages"
 
-  mutating func didInsert(with rowID: Int64, for column: String?) {
-    if column == Column.id.rawValue {
-      id = rowID
-    }
+  mutating func didInsert(_ inserted: InsertionSuccess) {
+    id = inserted.rowID
   }
 }
diff --git a/Sources/XXLegacyDatabaseMigrator/Migrator.swift b/Sources/XXLegacyDatabaseMigrator/Migrator.swift
index 2e15273b93a69c2de134d34f4a1f5aae1a73e70d..eacfb191ffbfe603556b871c6f8a6b583ee3d795 100644
--- a/Sources/XXLegacyDatabaseMigrator/Migrator.swift
+++ b/Sources/XXLegacyDatabaseMigrator/Migrator.swift
@@ -70,7 +70,11 @@ extension Migrator {
 }
 
 #if DEBUG
+import XCTestDynamicOverlay
+
 extension Migrator {
-  public static let failing = Migrator { _, _, _, _ in fatalError() }
+  public static let unimplemented = Migrator(
+    run: XCTUnimplemented("\(Self.self)")
+  )
 }
 #endif
diff --git a/Sources/XXModels/Database.swift b/Sources/XXModels/Database.swift
index 7b20c22db659110c53a08fb1bcbfb895878dbf77..f73b8cc5bf8b43ca380393cb73076fa4cb976990 100644
--- a/Sources/XXModels/Database.swift
+++ b/Sources/XXModels/Database.swift
@@ -177,37 +177,37 @@ public struct Database {
 
 #if DEBUG
 extension Database {
-  static public let failing = Database(
-    fetchChatInfos: .failing(),
-    fetchChatInfosPublisher: .failing(),
-    fetchContacts: .failing(),
-    fetchContactsPublisher: .failing(),
-    saveContact: .failing(),
-    bulkUpdateContacts: .failing(),
-    deleteContact: .failing(),
-    fetchContactChatInfos: .failing(),
-    fetchContactChatInfosPublisher: .failing(),
-    fetchGroups: .failing(),
-    fetchGroupsPublisher: .failing(),
-    saveGroup: .failing(),
-    deleteGroup: .failing(),
-    fetchGroupChatInfos: .failing(),
-    fetchGroupChatInfosPublisher: .failing(),
-    fetchGroupInfos: .failing(),
-    fetchGroupInfosPublisher: .failing(),
-    saveGroupMember: .failing(),
-    deleteGroupMember: .failing(),
-    fetchMessages: .failing(),
-    fetchMessagesPublisher: .failing(),
-    saveMessage: .failing(),
-    bulkUpdateMessages: .failing(),
-    deleteMessage: .failing(),
-    deleteMessages: .failing(),
-    fetchFileTransfers: .failing(),
-    fetchFileTransfersPublisher: .failing(),
-    saveFileTransfer: .failing(),
-    deleteFileTransfer: .failing(),
-    drop: .failing
+  static public let unimplemented = Database(
+    fetchChatInfos: .unimplemented(),
+    fetchChatInfosPublisher: .unimplemented(),
+    fetchContacts: .unimplemented(),
+    fetchContactsPublisher: .unimplemented(),
+    saveContact: .unimplemented(),
+    bulkUpdateContacts: .unimplemented(),
+    deleteContact: .unimplemented(),
+    fetchContactChatInfos: .unimplemented(),
+    fetchContactChatInfosPublisher: .unimplemented(),
+    fetchGroups: .unimplemented(),
+    fetchGroupsPublisher: .unimplemented(),
+    saveGroup: .unimplemented(),
+    deleteGroup: .unimplemented(),
+    fetchGroupChatInfos: .unimplemented(),
+    fetchGroupChatInfosPublisher: .unimplemented(),
+    fetchGroupInfos: .unimplemented(),
+    fetchGroupInfosPublisher: .unimplemented(),
+    saveGroupMember: .unimplemented(),
+    deleteGroupMember: .unimplemented(),
+    fetchMessages: .unimplemented(),
+    fetchMessagesPublisher: .unimplemented(),
+    saveMessage: .unimplemented(),
+    bulkUpdateMessages: .unimplemented(),
+    deleteMessage: .unimplemented(),
+    deleteMessages: .unimplemented(),
+    fetchFileTransfers: .unimplemented(),
+    fetchFileTransfersPublisher: .unimplemented(),
+    saveFileTransfer: .unimplemented(),
+    deleteFileTransfer: .unimplemented(),
+    drop: .unimplemented
   )
 }
 #endif
diff --git a/Sources/XXModels/Operations/BulkUpdate.swift b/Sources/XXModels/Operations/BulkUpdate.swift
index 6c9c28f4de91d1844d853cbc800defdd92e56e57..a814ed614cadf419e24668272149e398f4210463 100644
--- a/Sources/XXModels/Operations/BulkUpdate.swift
+++ b/Sources/XXModels/Operations/BulkUpdate.swift
@@ -22,9 +22,11 @@ public struct BulkUpdate<Query, Assignments> {
 }
 
 #if DEBUG
+import XCTestDynamicOverlay
+
 extension BulkUpdate {
-  public static func failing<Query, Assignments>() -> BulkUpdate<Query, Assignments> {
-    BulkUpdate<Query, Assignments> { _, _ in fatalError() }
+  public static func unimplemented<Query, Assignments>() -> BulkUpdate<Query, Assignments> {
+    BulkUpdate<Query, Assignments>(run: XCTUnimplemented("\(Self.self)"))
   }
 }
 #endif
diff --git a/Sources/XXModels/Operations/Delete.swift b/Sources/XXModels/Operations/Delete.swift
index b305699998ceb845a1492096a79496b65ca2bb52..fb6bcfed0e84a6368cb105b7b77bb0e20febbccf 100644
--- a/Sources/XXModels/Operations/Delete.swift
+++ b/Sources/XXModels/Operations/Delete.swift
@@ -22,9 +22,11 @@ public struct Delete<Model> {
 }
 
 #if DEBUG
+import XCTestDynamicOverlay
+
 extension Delete {
-  public static func failing<Model>() -> Delete<Model> {
-    Delete<Model> { _ in fatalError() }
+  public static func unimplemented<Model>() -> Delete<Model> {
+    Delete<Model>(run: XCTUnimplemented("\(Self.self)"))
   }
 }
 #endif
diff --git a/Sources/XXModels/Operations/DeleteMany.swift b/Sources/XXModels/Operations/DeleteMany.swift
index 43c155cbaab3c8a14b9e41dd780e12bcb12e1673..23e20cf351f56873537e115415e7d6bf4aa30ecb 100644
--- a/Sources/XXModels/Operations/DeleteMany.swift
+++ b/Sources/XXModels/Operations/DeleteMany.swift
@@ -21,9 +21,11 @@ public struct DeleteMany<Model, Query> {
 }
 
 #if DEBUG
+import XCTestDynamicOverlay
+
 extension DeleteMany {
-  public static func failing<Model, Query>() -> DeleteMany<Model, Query> {
-    DeleteMany<Model, Query> { _ in fatalError() }
+  public static func unimplemented<Model>() -> DeleteMany<Model, Query> {
+    DeleteMany<Model, Query>(run: XCTUnimplemented("\(Self.self)"))
   }
 }
 #endif
diff --git a/Sources/XXModels/Operations/Drop.swift b/Sources/XXModels/Operations/Drop.swift
index d80e2425413417c2d40461800e98854d63e1bb7a..1b7bd31cac48753f5f9f114c6c92226d35bce14e 100644
--- a/Sources/XXModels/Operations/Drop.swift
+++ b/Sources/XXModels/Operations/Drop.swift
@@ -20,7 +20,9 @@ public struct Drop {
 }
 
 #if DEBUG
+import XCTestDynamicOverlay
+
 extension Drop {
-  public static let failing = Drop { fatalError() }
+  public static let unimplemented = Drop(run: XCTUnimplemented("\(Self.self)"))
 }
 #endif
diff --git a/Sources/XXModels/Operations/Fetch.swift b/Sources/XXModels/Operations/Fetch.swift
index 7fe8e6e93891b126d3919d2550e4e0adfee80ca7..5f300f1d19657286e9f4e0949ad0fc5529547d20 100644
--- a/Sources/XXModels/Operations/Fetch.swift
+++ b/Sources/XXModels/Operations/Fetch.swift
@@ -22,9 +22,11 @@ public struct Fetch<Model, Query> {
 }
 
 #if DEBUG
+import XCTestDynamicOverlay
+
 extension Fetch {
-  public static func failing<Model, Query>() -> Fetch<Model, Query> {
-    Fetch<Model, Query> { _ in fatalError() }
+  public static func unimplemented<Model, Query>() -> Fetch<Model, Query> {
+    Fetch<Model, Query>(run: XCTUnimplemented("\(Self.self)"))
   }
 }
 #endif
diff --git a/Sources/XXModels/Operations/FetchPublisher.swift b/Sources/XXModels/Operations/FetchPublisher.swift
index fe78d3b5208fe088631796097dca0deea103799f..9758e025f238d4b244b0b25c5c1c7b91ef45cc8e 100644
--- a/Sources/XXModels/Operations/FetchPublisher.swift
+++ b/Sources/XXModels/Operations/FetchPublisher.swift
@@ -23,9 +23,13 @@ public struct FetchPublisher<Model, Query> {
 }
 
 #if DEBUG
+import XCTestDynamicOverlay
+
 extension FetchPublisher {
-  public static func failing<Model, Query>() -> FetchPublisher<Model, Query> {
-    FetchPublisher<Model, Query> { _ in fatalError() }
+  public static func unimplemented<Model, Query>() -> FetchPublisher<Model, Query> {
+    FetchPublisher<Model, Query>(
+      run: XCTUnimplemented("\(Self.self)", placeholder: Empty().eraseToAnyPublisher())
+    )
   }
 }
 #endif
diff --git a/Sources/XXModels/Operations/Save.swift b/Sources/XXModels/Operations/Save.swift
index 31ec662ba5cc4730a2e872f972d1b4b693037a42..abc6ab706135eace82159049a4955948f1317c7e 100644
--- a/Sources/XXModels/Operations/Save.swift
+++ b/Sources/XXModels/Operations/Save.swift
@@ -25,9 +25,11 @@ public struct Save<Model> {
 }
 
 #if DEBUG
+import XCTestDynamicOverlay
+
 extension Save {
-  public static func failing<Model>() -> Save<Model> {
-    Save<Model> { _ in fatalError() }
+  public static func unimplemented<Model>() -> Save<Model> {
+    Save<Model>(run: XCTUnimplemented("\(Self.self)"))
   }
 }
 #endif
diff --git a/Tests/XXDatabaseTests/Database+GRDBTests.swift b/Tests/XXDatabaseTests/Database+GRDBTests.swift
index f865f73ec32cba205e7d85a7028f138052539d16..67221f1418237a32abf74a3dcde2e36428f8aec2 100644
--- a/Tests/XXDatabaseTests/Database+GRDBTests.swift
+++ b/Tests/XXDatabaseTests/Database+GRDBTests.swift
@@ -9,7 +9,7 @@ final class DatabaseGRDBTests: XCTestCase {
   var writer: DatabaseWriter!
 
   override func setUp() async throws {
-    writer = DatabaseQueue()
+    writer = try DatabaseQueue()
     db = try Database.grdb(
       writer: writer,
       queue: DispatchQueue(label: "XXDatabase"),
diff --git a/Tests/XXDatabaseTests/Group+GRDBTests.swift b/Tests/XXDatabaseTests/Group+GRDBTests.swift
index ad3786a7f8de7725b4b884fa8275473834fad2ad..5454c949a6e2610cee7a68a63a33d63ea5362eaa 100644
--- a/Tests/XXDatabaseTests/Group+GRDBTests.swift
+++ b/Tests/XXDatabaseTests/Group+GRDBTests.swift
@@ -9,7 +9,7 @@ final class GroupGRDBTests: XCTestCase {
   var writer: DatabaseWriter!
 
   override func setUp() async throws {
-    writer = DatabaseQueue()
+    writer = try DatabaseQueue()
     db = try Database.grdb(
       writer: writer,
       queue: DispatchQueue(label: "XXDatabase"),
diff --git a/Tests/XXDatabaseTests/GroupMember+GRDBTests.swift b/Tests/XXDatabaseTests/GroupMember+GRDBTests.swift
index a8f6e0e68f82a5475b62ad811ccb8d82db5cad39..419f9431191db8234a46110e2f498538a4c9a5ca 100644
--- a/Tests/XXDatabaseTests/GroupMember+GRDBTests.swift
+++ b/Tests/XXDatabaseTests/GroupMember+GRDBTests.swift
@@ -9,7 +9,7 @@ final class GroupMemberGRDBTests: XCTestCase {
   var writer: DatabaseWriter!
 
   override func setUp() async throws {
-    writer = DatabaseQueue()
+    writer = try DatabaseQueue()
     db = try Database.grdb(
       writer: writer,
       queue: DispatchQueue(label: "XXDatabase"),
diff --git a/Tests/XXLegacyDatabaseMigratorTests/MigratorTests.swift b/Tests/XXLegacyDatabaseMigratorTests/MigratorTests.swift
index 2a83537f4e496ccd355de9d39c550e6ab8498b66..d4d46a1a2a5c4b6978a5530d996621bc34c52f6b 100644
--- a/Tests/XXLegacyDatabaseMigratorTests/MigratorTests.swift
+++ b/Tests/XXLegacyDatabaseMigratorTests/MigratorTests.swift
@@ -36,7 +36,7 @@ final class MigratorTests: XCTestCase {
 
     var didSaveContacts = [XXModels.Contact]()
 
-    var newDb = XXModels.Database.failing
+    var newDb = XXModels.Database.unimplemented
     newDb.fetchContacts = .init { _ in [] }
     newDb.saveContact = .init(run: {
       didSaveContacts.append($0)
@@ -125,7 +125,7 @@ final class MigratorTests: XCTestCase {
   func testMigratingLegacyDatabase1() throws {
     let path = Bundle.module.path(forResource: "legacy_database_1", ofType: "sqlite")!
     let legacyDb = try LegacyDatabase(path: path)
-    let newDbQueue = DatabaseQueue()
+    let newDbQueue = try DatabaseQueue()
     let newDb = try XXModels.Database.grdb(writer: newDbQueue)
     let currentDate = Date(timeIntervalSince1970: 1234)
     let migrate = Migrator.live(currentDate: { currentDate })
@@ -150,7 +150,7 @@ final class MigratorTests: XCTestCase {
   func testMigratingLegacyDatabase2() throws {
     let path = Bundle.module.path(forResource: "legacy_database_2", ofType: "sqlite")!
     let legacyDb = try LegacyDatabase(path: path)
-    let newDbQueue = DatabaseQueue()
+    let newDbQueue = try DatabaseQueue()
     let newDb = try XXModels.Database.grdb(writer: newDbQueue)
     let currentDate = Date(timeIntervalSince1970: 1234)
     let migrate = Migrator.live(currentDate: { currentDate })
@@ -182,7 +182,7 @@ final class MigratorTests: XCTestCase {
 
     // Mock up new database:
 
-    var newDb = XXModels.Database.failing
+    var newDb = XXModels.Database.unimplemented
     newDb.fetchContacts = .init { _ in [] }
     newDb.saveContact = .init { $0 }
 
diff --git a/run-tests.sh b/run-tests.sh
new file mode 100755
index 0000000000000000000000000000000000000000..7bfc617118bea4b955a221a110a000711824a77b
--- /dev/null
+++ b/run-tests.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+set -e
+
+if [ "$1" = "macos" ]; then
+
+  echo "\n\033[1;32mâ–¶ Running package tests on macOS...\033[0m"
+  set -o pipefail && swift test | ./xcbeautify
+
+elif [ "$1" = "ios" ]; then
+
+  echo "\n\033[1;32mâ–¶ Running package tests on iOS Simulator...\033[0m"
+  set -o pipefail && xcodebuild -scheme 'xx-client-ios-db-Package' -sdk iphonesimulator -destination 'platform=iOS Simulator,OS=16.0,name=iPhone 14' test | ./xcbeautify
+
+else
+
+  echo "\n\033[1;31mâ–¶ Invalid option.\033[0m Usage:"
+  echo "  run-tests.sh macos        - Run package tests on macOS"
+  echo "  run-tests.sh ios          - Run package tests on iOS Simulator"
+  exit 1
+
+fi
diff --git a/xcbeautify b/xcbeautify
new file mode 100755
index 0000000000000000000000000000000000000000..76b5df583a5d8f479e2088d4927ad90288c9d4cd
Binary files /dev/null and b/xcbeautify differ