クラウド Mac で iOS の触覚フィードバックを検証する

クラウド Mac で iOS の触覚フィードバックを検証する

クラウド Mac で iOS のビルドが通り、シミュレータ上で確認ボタンを押せたとしても、それだけで触覚フィードバックの検収は完了しません。シミュレータで確認できるのは、コードが適切なイベントを用意しているかどうかです。振動をどう感じるかは判断できません。この二つは別々の確認項目に分けましょう。前者は自動テストで、後者は触覚フィードバックに対応した実機で確認します。

フィードバックが何を伝えるかを先に決める

「保存完了」を例にすると、フィードバックを1回発生させるのは、ユーザーがボタンを押した時点ではなく、保存が成功した後です。保存に失敗した場合は画面にエラーを表示し、成功を示すフィードバックは再生しません。テストを書く前に、発火条件、イベントの種類、発火回数の3点を仕様として明記します。

触覚を文字や画面上の状態表示の代わりにしてはいけません。ユーザーがシステムの触覚フィードバックをオフにしている場合も、選択した触覚機能に対応していないデバイスを使っている場合もあります。保存結果は必ず画面上で確認できるようにし、触覚はその結果を伝える補助的な手掛かりとします。

自動テストで証明できるのは「どのフィードバックを要求したか」です。実機での検収では「そのフィードバックが適切に感じられるか」を判断します。どちらか一方で他方を代用することはできません。

イベントの定義を再生コードから分離する

イベントのパラメータがボタンのコールバック内に散在していると、テストでは画面を操作して何が起きたかを間接的に推測するしかありません。まずイベントを生成する関数を用意し、再生側からその関数を使うようにします。これなら、ハードウェアが振動するかどうかに依存せず、イベントの数、種類、相対時刻を直接検査できます。

クラウド Mac でイベントを検査する

次の例では、短いイベントで「保存完了」を表します。パラメータは例としての出発点であり、すべての製品に推奨する強さではありません。最終的な値は、実機で体験を確認して決めます。

import CoreHaptics

func confirmationEvents() -> [CHHapticEvent] {
    let event = CHHapticEvent(
        eventType: .hapticTransient,
        parameters: [
            CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.65),
            CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.35)
        ],
        relativeTime: 0
    )
    return [event]
}

プロジェクトのテストターゲットでは、まず再生デバイスに依存しない仕様を検査できます。テストコードとアプリのコードは同じ confirmationEvents() を参照してください。テスト内でイベントを別に作り直すと、両者のパラメータがそれぞれ変更され、食い違うおそれがあります。

import XCTest
import CoreHaptics
@testable import YourApp

final class ConfirmationHapticsTests: XCTestCase {
    func testConfirmationIsOneImmediateEvent() {
        let events = confirmationEvents()
        XCTAssertEqual(events.count, 1)
        XCTAssertEqual(events[0].relativeTime, 0)
        XCTAssertEqual(events[0].eventType, .hapticTransient)
    }
}

YourApp を実際のモジュール名に置き換え、プロジェクトで既に使っている共通のテスト実行手順から、クラウド Mac 上でこのテストターゲットを実行します。ここで検査するのはイベントの定義であり、シミュレータが実際に振動する必要はありません。後に1回のフィードバックを2段階のリズムに変えることになったら、まず仕様とテストを変更し、その後で実機での感触を検討します。

再生の失敗で保存結果を変えない

再生側では、エンジンとプレーヤーを作成する前に CHHapticEngine.capabilitiesForHardware().supportsHaptics を確認します。エンジンの起動、パターンの作成、再生はいずれも失敗する可能性があります。その場合は、アプリ内部で診断できる触覚フィードバックの失敗として記録するだけにし、既に成功した保存操作を失敗扱いにしてはいけません。エンジンが中断された後も、以前のプレーヤーが常に使えるとは限りません。アプリのライフサイクルに合わせて再生状態を準備し直します。

状況 アプリが必ず保証すること 触覚の扱い
保存に成功し、触覚に対応している 保存完了の状態を表示する 成功イベントの再生を要求する
保存に成功したが、触覚に対応していない 同じく保存完了の状態を表示する 再生をスキップする
保存に失敗した 理解しやすいエラーを表示する 成功イベントを再生しない
再生中にエラーが起きた 完了した保存の結果を維持する 今回のフィードバックを停止し、診断情報を記録する

シミュレータの感触ではなく、呼び出すタイミングをテストする

再生処理を差し替え可能なインターフェースで包みます。保存処理のテストには呼び出し回数を記録する実装を注入し、成功後は1回、失敗後は0回の呼び出しであることを検証します。連続タップを業務ロジックで防いだ場合も、余分に再生してはいけません。触覚機能がない場合の分岐もテストし、画面に表示される結果が変わらないことを確認します。「シミュレータが振動したか」よりも、これらの検査のほうが安定しており、コードが実際に保証できる動作に即しています。

体験の検収は実機で行う

実機では、少なくとも保存の成功と失敗、短時間での連続操作、バックグラウンドから戻った後の最初の操作を確認します。触覚と完了状態の表示が同時に起きるか、連続タップ時にフィードバックが密集して区別しにくくならないかを観察してください。システムによるオーディオの中断やアプリのバックグラウンド移行後も、次のフィードバックを正常に要求できるか確認します。パラメータを調整するときは一度に1項目だけ変更し、テスト端末、OS バージョン、観察結果を記録します。主観的な感じ方の違いをコードのリグレッションと取り違えないためです。

クラウド Mac では、ビルド、シミュレータテスト、イベント仕様の検査を行えます。実際の感触は、引き続きチームが触覚対応デバイスで確認する必要があります。リモートデスクトップ上で見えるボタンのアニメーションは、触覚を検収した証拠にはなりません。

マージ前に検証範囲を確認する

マージ前に、次の4点を確認します。イベント生成関数を本番コードとテストで共用していること。保存失敗時に成功フィードバックが発火しないこと。触覚に非対応の場合や再生時に異常が起きた場合も、結果が画面上で明確に分かること。実機での記録に、発火タイミングと連続操作についての観察が含まれていること。実機での体験に関する意見を受けてパラメータを調整したら、イベントテストの期待値も更新し、自動テストを再実行します。

こうして役割を分ければ、クラウド Mac 上のテストでは再現可能な事実を確かめ、実機での確認ではシミュレータでは答えられない体験上の問題を確かめられます。

よくある質問

iOS シミュレータだけで触覚の品質を確認できますか?

できません。イベントの構成や呼び出し条件は検査できますが、強さと画面との同期は対応する実機で確認します。

Core Haptics 非対応端末ではどう動かすべきですか?

本来の操作と画面の状態更新を完了し、触覚だけを省略します。再生失敗を操作失敗として扱わない設計にします。

次の実験には、専用のMacを

物理Mac mini、ノード、利用期間を必要に応じてお選びいただけます。モデルと在庫状況はコンソールでリアルタイムにご確認ください。

クラウドMacのレンタルプランを見る