結論
Unity Test Runnerは、PlayerPrefsをテスト専用の保存領域へ自動で隔離しません。
テストのSetUpやTearDownでPlayerPrefs.DeleteAll()を呼ぶと、その時点でUnity Editorが使用しているPlayerPrefsの全キーが削除されます。
テスト用データだけを初期化したい場合はDeleteAll()を使わず、テストが変更するキーだけを削除・保存・復元します。
Unity Test Runner自体を初めて使う場合は、先にUnity Test Runnerとは?基本と使い方を確認してください。
症状
今回確認した症状は次のとおりです。
- Edit Modeテストの終了後、テストで直接使用していないPlayerPrefsまで消えていた
- テスト自体はすべて成功していた
- Consoleにも原因を示す例外は出ていなかった
- テスト前後でPlayerPrefsを比較して初めて削除に気づいた
原因
Unity Test Runnerは保存先を切り替えない
Edit ModeテストやPlay Modeテストから通常のPlayerPrefs APIを呼ぶと、Unity Editorが現在使用しているPlayerPrefsへアクセスします。
Test RunnerがCompany Name、Product Name、保存先をテスト用へ自動変更する処理はありません。
PlayerPrefs.DeleteAll()は全キーを削除する
テストのSetUpとTearDownで、次の処理を実行していました。
[SetUp]
public void SetUp()
{
PlayerPrefs.DeleteAll();
}
DeleteAll()は、このテストが使用するキーだけを削除する処理ではありません。同じPlayerPrefs領域にある次のような値も削除対象になります。
- ゲーム進行状況
- 音量や表示設定
- チュートリアル完了状態
- SDKや別機能が保存した値
確認方法
テストコード内で、まず次を検索します。
PlayerPrefs.DeleteAll()
見つかった場合は、SetUp、TearDown、テスト用helperなど、どこから呼ばれているか確認します。
テスト対象外の確認用キーを1つ用意し、テスト後も残っているか比較する方法も有効です。
PlayerPrefs.SetString("sentinel_key", "before-test");
PlayerPrefs.Save();
テスト終了後にこのキーが消えていれば、対象外のPlayerPrefsまで変更されています。
解決方法
DeleteAll()ではなく変更するキーだけを扱う
テストが専用キーだけを使用するなら、PlayerPrefs.DeleteKey()で対象キーだけを削除します。
private const string TestKey = "test_score";
[SetUp]
public void SetUp()
{
PlayerPrefs.DeleteKey(TestKey);
}
[TearDown]
public void TearDown()
{
PlayerPrefs.DeleteKey(TestKey);
}
元から存在するキーを変更する場合は復元する
ゲーム本体でも使用するキーをテストで変更する場合は、テスト前に次の情報を保存します。
- キーが存在していたか
- 値の型
- 元の値
テスト終了時には、元から存在していたキーは元の値へ戻し、存在していなかったキーは削除します。
可能ならPlayerPrefsを直接テストしない
ゲームコードからPlayerPrefsを直接呼ばず、保存処理をinterfaceなどで分離する方法もあります。
テスト時にメモリ上の実装へ差し替えれば、実際のPlayerPrefsへ触れずにロジックを確認できます。
関連記事
Play Modeテスト終了時に実Saveファイルが更新される問題は、Unity Test RunnerでSaveが書き換わる原因と対策で説明しています。