テストとデバッグ - Swift SDK
項目一覧
テスト
デフォルトの Realm を使用したテスト
Realm ベースのアプリケーションを使用してテストする最も簡単な方法は、デフォルトの Realm を使用することです。 アプリケーション データがオーバーライドされたり、テスト間で状態がリークされたりしないようにするには、テストごとに新しいファイルにデフォルトの Realm を設定します。
// A base class which each of your Realm-using tests should inherit from rather // than directly from XCTestCase class TestCaseBase: XCTestCase { override func setUp() { super.setUp() // Use an in-memory Realm identified by the name of the current test. // This ensures that each test can't accidentally access or modify the data // from other tests or the application itself, and because they're in-memory, // there's nothing that needs to be cleaned up. Realm.Configuration.defaultConfiguration.inMemoryIdentifier = self.name } }
Realm インスタンスの挿入
Realm 関連のコードをテストする別の方法は、テストするすべてのメソッドが Realm インスタンスを引数として受け入れさせることです。 これにより、アプリを実行するときとテストするときに異なるRealmを渡すことができます。
たとえば、アプリに JSON API からユーザー プロファイルを GET
するメソッドがあるとします。 ローカル プロファイルが正しく作成されているかどうかをテストするには以下を行います。
// Application Code func updateUserFromServer() { let url = URL(string: "http://myapi.example.com/user") URLSession.shared.dataTask(with: url!) { data, _, _ in let realm = try! Realm() createOrUpdateUser(in: realm, with: data!) } } public func createOrUpdateUser(in realm: Realm, with data: Data) { let object = try! JSONSerialization.jsonObject(with: data) as? [String: String] try! realm.write { realm.create(User.self, value: object, update: .modified) } } // Test Code let realmPath = URL(fileURLWithPath: "...") func testThatUserIsUpdatedFromServer() { let config = Realm.Configuration(fileURL: realmPath) let testRealm = try! Realm(configuration: config) let jsonData = "{\"email\": \"help@realm.io\"}".data(using: .utf8)! // In our test, we're passing in the testRealm. This is where we'd // pass in our "real" realm in the application code above. createOrUpdateUser(in: testRealm, with: jsonData) XCTAssertEqual(testRealm.objects(User.self).first!.email, "help@realm.io", "User was not properly updated from server.") }
クラスプロジェクションによるテストの簡素化
バージョン10.21.0の新機能。
テスト用にオブジェクトのプロパティのサブセットを操作する場合は、 クラス プロジェクション を作成できます。 クラスプロジェクションは、Realm オブジェクトプロパティを渡したり、名前を変更したり、除外したりできるモデル抽象化です。 この機能によりビューモデルの実装が簡素化されますが、Realm によるテストも簡素化されます。
例
この例では、 「 クラス プロジェクションの定義と使用 」ページ のオブジェクト モデル と クラス プロジェクションを使用します。
この例では、完全なオブジェクトモデルを使用して Realm オブジェクトを作成します。 次に、オブジェクトをクラス プロジェクションとして取得し、そのプロパティのサブセットのみを操作します。
このクラス プロジェクションでは、テストする必要のないプロパティにアクセスしたり、アカウントを作成したりする必要はありません。
func testWithProjection() { let realm = try! Realm() // Create a Realm object, populate it with values let jasonBourne = Person(value: ["firstName": "Jason", "lastName": "Bourne", "address": [ "city": "Zurich", "country": "Switzerland"]]) try! realm.write { realm.add(jasonBourne) } // Retrieve all class projections of the given type `PersonProjection` // and filter for the first class projection where the `firstName` property // value is "Jason" let person = realm.objects(PersonProjection.self).first(where: { $0.firstName == "Jason" })! // Verify that we have the correct PersonProjection XCTAssert(person.firstName == "Jason") // See that `homeCity` exists as a projection property // Although it is not on the object model XCTAssert(person.homeCity == "Zurich") // Change a value on the class projection try! realm.write { person.firstName = "David" } // Verify that the projected property's value has changed XCTAssert(person.firstName == "David") }
テスト対象
Realm フレームワークをテスト ターゲットに直接リンクしないでください。 これによりテストが失敗し、「オブジェクトタイプ 'あなたのオブジェクト' は Realm によって管理されていません」という例外メッセージが表示される可能性があります。 テスト ターゲットから Realm のリンクを解除すると、この問題は解決されます。
アプリケーションまたはフレームワーク ターゲットでモデル クラス ファイルをコンパイルします。ユニット テストのターゲットに追加しないでください。 そうしないと、それらのクラスはテスト時に重複されるため、デバッグが困難な問題が発生する可能性があります。
テストに必要なすべてのコードをユニット テスト ターゲットに公開します。public
アクセス修飾子または @ Testable を使用します。
Realm を動的フレームワークとして使用しているため、ユニット テストのターゲットが Realm を見つけられることを確認する必要があります。 RealmSwift.framework
への親パスをユニット テストの「フレームワーク検索パス」に追加します。
デバッグ
Realm Studio を使用したデバッグ
Realm Studioを使用すると、ローカル Realm を開いて編集できます。 Mac、Windows、および Linux をサポートしています。
LLDB
Realm の Swift API を使用してアプリをデバッグする場合は、LDDB コンソールを使用して実行する必要があります。
LDDB スクリプトを使用すると、Xcode の UI で Realm 変数の内容を検査できますが、これは Swift ではまだ機能しません。 これらの変数は誤ったデータを表示します。 代わりに、LDDB のpo
コマンドを使用して、Realm に保存されているデータの内容を検査します。
トラブルシューティング
ビルドの問題の解決
一部の開発者は、 CocoaPods または Chartsage 経由で Realm Swift SDK をインストールした後にビルドの問題が発生します。 これらの問題の一般的な原因は次のとおりです。
インストールの問題:
最初のインストールは失敗
サポートされていないバージョンの依存関係マネージャーの使用
ビルド ツールの問題:
ビルド ツールには古いキャッシュがあります
ビルド ツールのバージョンの更新
次のようなプロジェクト設定に変更を加えます。
新しいターゲットの追加
ターゲット間で依存関係を共有
これらの問題をクリアすることが多い修正は、派生データを削除し、Xcode ビルド フォルダーをクリーンアップすることです。
UI をロードする前に Realm を起動する際の問題
Realm を開くと、任意または必須のプロパティに関連するエラー メッセージとクラッシュがすぐに表示される場合があります。 オブジェクトモデルに問題があると、このようなクラッシュが発生する可能性があります。 これらのエラーは、Realm を開いた後、UI にアクセスする前に発生します。
Realm には、デバイス上で Realm が開くときに「スキーマ検出」フェーズがあります。 この時点で、Realm は、管理するすべてのオブジェクトのスキーマを検査します。 アプリケーション内のオブジェクトのサブセットのみを管理するよう指定できます。
スキーマ検出中にプロパティに関連するエラーが表示される場合は、特定のオブジェクトのデータに関連するものではなく、スキーマの問題が原因である可能性があります。 たとえば、 1 対 1 の関係を任意ではなく必須として定義すると、スキーマ検出エラーが表示される可能性があります。
これらのクラッシュをデバッグするには、定義したスキーマを確認します。
これらは UI がロードする前に発生するため、これらはスキーマ検出の問題であることがわかります。 つまり、プロパティを誤って使用しようとする UI 要素はなく、メモリ内に間違ったデータを含む可能性のあるオブジェクトはありません。 UI のロード後にプロパティに関連するエラーが発生する場合は、無効なスキーマが原因ではない可能性があります。 代わりに、誤ったデータやタイプ、データの欠落が原因でエラーが発生する可能性が高くなります。
モデルにプロパティは定義されていません
Realm Swift SDK は Swift 言語反映機能を使用して、実行時にモデル内のプロパティを決定します。 次のようなクラッシュが発生した場合は、プロジェクトでリフレクション メタデータが無効になっていないことを確認してください。
Terminating app due to uncaught exception 'RLMException', reason: 'No properties are defined for 'ObjectName'.
SWIFT_REFLECTION_METADATA_LEVEL = none
を設定すると、Realm は、プロパティや列挙などの型の子を検出できません。 プロジェクトでこの設定のレベルが特に設定されていない場合は、反映はデフォルトで有効になります。
無効な割り当て/使用可能なメモリが不足しています
使用可能なメモリがほとんどない iOS または IP デバイス、または複数の Realm や多数の通知を使用するメモリ集中型のアプリケーションでは、次のエラーが発生する可能性があります。
libc++abi: terminating due to an uncaught exception of type std::bad_alloc: std::bad_alloc
このエラーは通常、十分なメモリが利用できないため、リソースを割り当てることができないことを示します。
iOS15 + または iOS15 + 用にビルドしている場合は、 拡張仮想アドレス指定権限 を追加できます この問題を解決するには、 を使用します。
これらのキーをプロパティ リストに追加し、値をtrue
に設定します。
<key>com.apple.developer.kernel.extended-virtual-addressing</key> <true/> <key>com.apple.developer.kernel.increased-memory-limit</key> <true/>
Swift パッケージ ターゲットは動的に構築できません
バージョン10.49.3で変更。
Swift SDK v 10.49.3 Swift パッケージ マネージャー(SPM)を使用してパッケージをインストールするための詳細を変更しました。 パッケージの古いバージョンから v 10.49.3以降に更新すると、次のようなビルド エラーが発生する場合があります。
Swift package target `Realm` is linked as a static library by `TargetName` and `Realm`, but cannot be built dynamically because there is a package product with the same name.
このエラーを解決するには、 Realm
またはRealmSwift
パッケージのいずれかについて、ビルドターゲットからのリンクを解除します。 Xcode で次の手順に従ってこれを実行できます。
プロジェクト Targetsで、ビルド ターゲットを選択します。
[Build Phases] タブに移動します。
Link Binary With Libraries要素を展開します。
Realm
またはRealmSwift
のいずれかを選択し、[ Remove items( - )] ボタンをクリックして、不要なバイナリを削除します。Swift または Swift と Objective-C API を使用する場合は、
RealmSwift
を維持します。Objective-C API のみを使用する場合は、
Realm
を保持します。
これで、ターゲットはこのエラーなしでビルドされるはずです。