WWDC Quick Look 💓 By SwiftGGTeam
Automate CloudKit tests with cktool and declarative schema

Automate CloudKit tests with cktool and declarative schema

元の動画を見る

ハイライト

Apple は cktool と CloudKit 宣言型スキーマ言語を Xcode 13 に追加しました。これにより、開発者はテスト前に CloudKit コンテナを自動的にリセットし、スキーマをインポートし、サンプル データを書き込むことができ、不安定なクラウド統合テスト環境の問題が解決されました。

主要内容

CloudKit アプリケーションの統合テストで最も恐れられるのは、サーバー状態のドリフトです。

ローカル コードによってデータ モデルが変更されており、CloudKit コンテナ内のスキーマが古いバージョンのままになっている可能性があります。テストの最初の実行ではデータが作成され、2 回目の実行では前回残されたレコードが読み取られます。開発者は結局、コンソールのクリーニング、フィールドの同期、サンプル データの再構築に時間を費やすことになり、テスト自体は二次的なタスクになってしまいます。

Apple は WWDC21 で 2 つのツールを発表しました。一つ目はcktool、Xcode 13でインストールされ、経由xcrunコマンドラインからCloudKitにアクセスします。スキーマをインポートおよびエクスポートし、レコードを作成およびクエリできます。 2 つ目は CloudKit スキーマ言語 (CloudKit Schema language) で、コンテナ構造をテキスト ファイルとして記述し、アプリケーション コードとともにバージョン管理に送信できます。

このようにして、スクリプトによって CloudKit テスト環境を準備できます。テストを開始する前に、スクリプトはまず開発環境をクリアし、次にプロジェクトにスキーマ ファイルをインポートし、最後に固定サンプル データを書き込みます。 Xcode のテスト プレアクションは、テストの実行前にこのスクリプトを実行します。テストは毎回同じコンテナーの状態に直面するため、失敗の原因を特定しやすくなります。

コンソール操作をスクリプト操作に変換する

以前は、CloudKit コンソールはコンテナの手動表示と変更に適していました。スキーマ管理を完了できますが、継続的統合プロセスには適していません。また、チーム メンバーが Git diff から CloudKit スキーマの変更を確認することも困難です。

cktoolこれらの操作をコマンドラインに入力します。スキーマのエクスポートもコマンドであり、スキーマのインポートもコマンドです。テスト レコードを作成するときに、JSON を直接渡すことができます。開発者は、テスト前にブラウザを開いたり、コンソールを手動でクリックしたりする必要はありません。

暗黙的なサーバー状態からテキスト ファイルへの変更

スキーマ言語はレコードタイプ、フィールド、インデックス、権限を書き込みます。.ckdbファイル内にあります。このファイルはプロジェクト ディレクトリに配置され、Swift コードと一緒にレビューされます。

アプリケーションのデータ モデルが変更されると、スキーマの変更も同じコミットに入ります。テスト スクリプトはこのファイルをインポートします。サーバーのステータスはリポジトリ内のテキスト宣言から得られるため、チームは誰かがコンソールにアクセスしてフィールドを変更することを忘れずに済みます。

詳細

cktool を承認する

02:21cktoolCloudKit サーバーに直接接続し、使用前に認証が必要です。 CloudKit は 2 種類のトークンを提供します。管理トークンは、スキーマのインポートやエクスポートなどのコンテナー構成に使用されます。ユーザー トークンは、アプリケーション コンテナーのプライベート データベースまたはパブリック データベースにデータを書き込むために使用されます。

xcrun cktool save-token --type management

xcrun cktool save-token --type user

xcrun cktool get-teams

キーポイント:

  • xcrun cktoolXcode 13 によってインストールされた CloudKit コマンド ライン ツールを呼び出します。
  • save-token --type managementスキーマのインポートやエクスポートなどの構成操作のために管理トークンを保存します。
  • save-token --type userコンテナデータにアクセスするためのユーザートークンを保存します。
  • トークンは macOS キーチェーンに安全に保存されます。
  • get-teams現在の開発者アカウントが属する Apple 開発者チームのリストを返します。後続のコマンドにはチーム ID が必要です。

CloudKit スキーマのエクスポート

(03:45) コンテナ内に開発中のスキーマがすでにある場合は、まずファイルにエクスポートしてから、ソース コード リポジトリに送信できます。講義内でエクスポートしたファイル名はschema.ckdb

xcrun cktool export-schema \
  --team-id XYZ1234567 \
  --container-id iCloud.com.WWDC21.Example \
  --environment development \
  --output-file schema.ckdb

キーポイント:

  • export-schemaCloudKit コンテナからスキーマをエクスポートします。
  • --team-id XYZ1234567Apple 開発者チームを指定します。
  • --container-id iCloud.com.WWDC21.Example操作する CloudKit コンテナを指定します。
  • --environment development開発環境を選択します。講演では、開発環境ではレコードタイプとカスタムフィールドを追加したり削除したりできることが強調された。
  • --output-file schema.ckdbエクスポートしたスキーマをテキスト ファイルに書き込み、バージョン管理に簡単に含めることができます。

テスト記録を作成する

04:07cktoolデータの書き込みも可能です。 JSON を使用して表現する講義Book記録し、それをパブリック データベースに作成します。

xcrun cktool create-record \
  --team-id XYZ1234567 \
  --container-id iCloud.com.WWDC21.Example \
  --environment development \
  --database-type public \
  --record-type Book \
  --fields-json '{
       "title": { "type": "stringType", "value": "Treasure Island" },
       "pageCount": { "type": "int64Type", "value": 304 }
    }'

キーポイント:

  • create-recordCloudKit サーバーにレコードを作成します。
  • --database-type publicパブリックデータベースへの書き込みを指定します。
  • --record-type Book指定したレコード タイプは、コンテナ スキーマのレコード タイプと一致している必要があります。
  • --fields-jsonJSON を使用してフィールド値を記述します。
  • title種類はstringType、値はTreasure Island
  • pageCount種類はint64Type、値は304

CloudKit の準備手順を Xcode テストに統合する

(05:05) この講義では、コンテナのリセット、プロジェクトへのスキーマ ファイルのインポート、サンプル レコードの作成という 3 種類の操作を Xcode スキームの Test プレアクションに組み込みます。cktoolコマンドは同期的に実行され、前のコマンドが失敗すると、後続のコマンドは実行を継続できなくなります。

xcrun cktool reset-schema \
    --team-id XYZ1234567 \
    --container-id iCloud.com.WWDC21.Example

xcrun cktool import-schema \
    --team-id XYZ1234567 \
    --container-id iCloud.com.WWDC21.Example \
    --environment development \
    --file $PROJECT_DIR/Example/CloudKitSchema.ckdb

xcrun cktool create-record \
    --team-id XYZ1234567 \
    --container-id iCloud.com.WWDC21.Example \
    --environment development \
    --database-type public \
    --record-type Book \
    --fields-json '{
       "title": { "type": "stringType", "value": "Great Expectations" },
       "pageCount": { "type": "int64Type", "value": 544 },
       "description": { "type": "stringType", "value": "Depiction of the education of an orphan nicknamed Pip" },
       "publishedOn": { "type": "timestampType", "value": "1860-12-01T03:23:07.415Z" },
       "reviewStatus": { "type": "int64Type", "value": 1 }
    }'

キーポイント:

  • reset-schema指定した CloudKit コンテナのスキーマをリセットします。これは、テスト前に開発環境をクリーンアップするのに適しています。
  • import-schemaプロジェクトに投入する.ckdbスキーマ ファイルは CloudKit サーバーに送信されます。
  • $PROJECT_DIR/Example/CloudKitSchema.ckdbXcode ビルド設定を使用して、プロジェクト内のスキーマ ファイルを見つけます。
  • 2番目create-recordより完全なものを書くBookサンプルレコード。
  • publishedOn使用timestampType、値は ISO 時間文字列です。
  • reviewStatus使用int64Type、値は1
  • このスクリプトがテストのプレアクションに配置されると、各テストが実行される前に、同じ一連の CloudKit 状態が準備されます。

スキーマ言語ファイルの読み取り

(05:51) スキーマ ファイルには、CloudKit のレコード タイプ、フィールド、インデックス、セキュリティ ロールが記述されています。トーク定義の例Bookレコードタイプ。

DEFINE SCHEMA
     RECORD TYPE Book (
        "___createTime" TIMESTAMP,
        "___createdBy"  REFERENCE,
        "___etag"       STRING,
        "___modTime"    TIMESTAMP,
        "___modifiedBy" REFERENCE,
        "___recordID"   REFERENCE QUERYABLE,
        description     STRING,
        pageCount       INT64,
        publishedOn     TIMESTAMP,
        reviewStatus    INT64,
        // A single-line comment, for humans
        title           STRING QUERYABLE,
        GRANT WRITE TO "_creator",
        GRANT CREATE TO "_icloud",
        GRANT READ TO "_world"
     );

キーポイント:

  • DEFINE SCHEMACloudKit スキーマ宣言を開始します。
  • RECORD TYPE Bookという名前のファイルを定義しますBookレコードタイプ。
  • "___createTime""___createdBy""___etag""___modTime""___modifiedBy""___recordID"CloudKit によってレコード タイプごとに作成されるシステム フィールドです。
  • descriptionpageCountpublishedOnreviewStatustitleアプリケーションのカスタムフィールドです。
  • TIMESTAMPREFERENCESTRINGINT64フィールドのデータ型です。
  • QUERYABLE例では、フィールドのクエリ可能なインデックスを作成します。___recordIDそしてtitleインデックスが宣言されています。
  • // A single-line comment, for humansチームが読むためのコメントであり、CloudKit サーバーがファイルを処理するときに無視されます。
  • GRANT WRITE TO "_creator"レコード作成者に書き込みを許可します。
  • GRANT CREATE TO "_icloud"認証された iCloud ユーザーがレコードを作成できるようにします。
  • GRANT READ TO "_world"すべてのユーザーに読み取りを許可します。

本番環境のスキーマ進化ルールを覚えておいてください

(07:14) スキーマ ファイルにより変更が高速化されますが、CloudKit の実稼働環境ルールは変更されていません。レコードタイプは開発環境で追加および削除でき、カスタムフィールドも追加および削除できます。レコード タイプが運用環境に昇格されると、削除したり名前を変更したりすることはできません。運用環境にプロモートされたカスタム フィールドは、削除したり名前を変更したりすることはできません。

Development environment:
- Add and remove record types
- Add and remove custom fields

Production environment:
- Promote new record types
- Add new fields to existing record types
- Cannot delete or rename promoted record types
- Cannot delete or rename promoted custom fields
- Can add and remove indexes
- Can modify security role settings

キーポイント:

  • 開発環境はスキーマの迅速な反復に適しています。
  • 運用環境では古いレコード タイプとフィールドが保持されるため、CloudKit サーバーは古いバージョンのアプリケーションで使用されているデータを引き続き理解できます。
  • 破壊的なスキーマ変更は開発環境に現れる可能性があり、運用環境にプロモートすることはできません。
  • インデックスとセキュリティ ロールの設定は、運用環境でも引き続き変更できます。

重要ポイント

  • やるべきこと: 再現可能な統合テスト環境を CloudKit アプリに追加します。 実行する価値がある理由:cktoolテスト前にスキーマをインポートしてサンプル データを作成し、手動で準備したサーバーの状態に依存するテストを回避できます。 開始方法:reset-schemaimport-schemacreate-recordXcode スキームのテスト プレアクションを記述し、スキーマ ファイル パスを使用します。$PROJECT_DIR

  • やるべきこと: CloudKit スキーマを Git コード レビューに組み込みます。 実行する価値がある理由:.ckdbドキュメントにはレコードの種類、フィールド、インデックス、権限を記述することができ、チームは Swift コードをレビューするのと同じ方法でデータ モデルの変更をレビューできます。 開始方法: 最初に使用しますxcrun cktool export-schema --environment development --output-file schema.ckdb既存のスキーマをエクスポートし、ファイルをプロジェクトに追加します。

  • やるべきこと: UI テスト用の固定クラウド サンプル データを準備します。 実行する価値がある理由:create-recordJSON を使用したパブリック データベースへの書き込みをサポートし、テストでは同じレコード セットを安定して読み取ることができます。 開始方法: それぞれのテスト シナリオのセットを作成します。--fields-json、テスト終了前スクリプトで必要な CloudKit レコードを 1 つずつ作成します。

  • やるべきこと: チーム用の CloudKit スキーマ移行チェックリストを作成します。 実行する価値がある理由: プロモートされたレコード タイプとカスタム フィールドは、運用環境では削除したり名前を変更したりできません。事前に確認することで導入の失敗を減らすことができます。 開始方法: PR テンプレートに追加します.ckdb項目を変更し、重大な変更、インデックスの変更、セキュリティ ロールの変更が含まれているかどうかを確認します。

  • 対処方法: 継続的統合のために管理トークンとユーザー トークンを分割します。 実行する価値がある理由: 管理トークンはコンテナー構成のみを処理し、ユーザー トークンはデータ書き込みのみを処理し、アクセス許可の境界がより明確になります。 開始方法: まずはこのマシンで使用してくださいsave-token --type managementそしてsave-token --type user認可が完了すると、テスト スクリプトは構成操作とデータ操作に従ってセグメントに編成されます。

関連セッション

コメント

GitHub Issues · utterances