ExtPlayerPrefs のテストコード
目次
目的
この資料は、ExtPlayerPrefs
クラスの機能を網羅的にテストするコードの内容と、その背景を説明するものです。
テストの概要
ExtPlayerPrefs
クラスのテストコードは、以下の機能を確認することを目的としています:
- プリミティブ型データの保存と読み出しが正しく行われること。
- 複雑なオブジェクトの保存と復元が期待通り動作すること。
ScriptableObject
の保存・読み出しが適切に処理されること。- エラー処理が正しく動作し、適切な例外がスローされること。
テストの内容
1. プリミティブ型データの保存と読み出し
テストケース
- 整数型 (
int
) の同期保存と読み出し - 文字列型 (
string
) の非同期保存と読み出し
実装例
[Test]
public void SaveAndLoad_PrimitiveInt_ShouldWorkCorrectly()
{
int testValue = 42;
ExtPlayerPrefs.Save(testValue, TestFileName, EncryptionKey);
var loadedValue = ExtPlayerPrefs.Load<int>(TestFileName, EncryptionKey);
Assert.AreEqual(testValue, loadedValue);
}
[Test]
public async Task SaveAndLoadAsync_PrimitiveString_ShouldWorkCorrectly()
{
string testValue = "Hello, World!";
await ExtPlayerPrefs.SaveAsync(testValue, TestFileName, EncryptionKey);
var loadedValue = await ExtPlayerPrefs.LoadAsync<string>(TestFileName, EncryptionKey);
Assert.AreEqual(testValue, loadedValue);
}
確認ポイント
- 保存した値と読み出した値が完全に一致するか。
- ファイルが正しく生成されるか。
- 非同期処理が正常に完了するか。
2. 複雑なオブジェクトの保存と読み出し
テストケース
- カスタムクラス
TestData
の同期保存と読み出し - 非同期処理によるデータ保存と復元
実装例
[Test]
public void SaveAndLoad_ShouldWorkCorrectly()
{
var testData = new TestData { Name = "TestUser", Age = 25 };
ExtPlayerPrefs.Save(testData, TestFileName, EncryptionKey);
var loadedData = ExtPlayerPrefs.Load<TestData>(TestFileName, EncryptionKey);
Assert.AreEqual(testData.Name, loadedData.Name);
Assert.AreEqual(testData.Age, loadedData.Age);
}
[Test]
public async Task SaveAndLoadAsync_ShouldWorkCorrectly()
{
var testData = new TestData { Name = "AsyncUser", Age = 30 };
await ExtPlayerPrefs.SaveAsync(testData, TestFileName, EncryptionKey);
var loadedData = await ExtPlayerPrefs.LoadAsync<TestData>(TestFileName, EncryptionKey);
Assert.AreEqual(testData.Name, loadedData.Name);
Assert.AreEqual(testData.Age, loadedData.Age);
}
確認ポイント
- オブジェクトのプロパティが保存前後で一致しているか。
- 非同期処理が期待通り動作するか。
3. ScriptableObject の保存と読み出し
テストケース
ScriptableObject
の同期保存と読み出し- 非同期処理による
ScriptableObject
の保存と復元
実装例
[Test]
public void SaveScriptableObjectAndLoadScriptableObject_ShouldWorkCorrectly()
{
var myObject = ScriptableObject.CreateInstance<MyScriptableObject>();
myObject.Description = "Test Description";
myObject.Value = 99;
ExtPlayerPrefs.SaveScriptableObject(myObject, TestFileName, EncryptionKey);
var loadedObject = ScriptableObject.CreateInstance<MyScriptableObject>();
ExtPlayerPrefs.LoadScriptableObject(loadedObject, TestFileName, EncryptionKey);
Assert.AreEqual(myObject.Description, loadedObject.Description);
Assert.AreEqual(myObject.Value, loadedObject.Value);
}
[Test]
public async Task SaveScriptableObjectAsyncAndLoadScriptableObjectAsync_ShouldWorkCorrectly()
{
var myObject = ScriptableObject.CreateInstance<MyScriptableObject>();
myObject.Description = "Async Test Description";
myObject.Value = 99;
await ExtPlayerPrefs.SaveScriptableObjectAsync(myObject, TestFileName, EncryptionKey);
var loadedObject = ScriptableObject.CreateInstance<MyScriptableObject>();
await ExtPlayerPrefs.LoadScriptableObjectAsync(loadedObject, TestFileName, EncryptionKey);
Assert.AreEqual(myObject.Description, loadedObject.Description);
Assert.AreEqual(myObject.Value, loadedObject.Value);
}
確認ポイント
ScriptableObject
のプロパティが保存前後で一致しているか。- 非同期処理による保存・読み出しが正常に動作するか。
4. エラーハンドリング
テストケース
- 存在しないファイルを読み込もうとした場合
null
データを保存しようとした場合
実装例
[Test]
public void Load_NonExistentFile_ShouldThrowFileNotFoundException()
{
Assert.Throws<FileNotFoundException>(() =>
{
ExtPlayerPrefs.Load<int>("non_existent.json");
});
}
[Test]
public void Save_NullObject_ShouldThrowArgumentNullException()
{
Assert.Throws<System.ArgumentNullException>(() =>
{
ExtPlayerPrefs.Save<string>(null, TestFileName, EncryptionKey);
});
}
確認ポイント
- 適切な例外がスローされるか (
FileNotFoundException
、ArgumentNullException
)。 - 不正な操作によるシステムエラーが発生しないか。
テストコード全体の設計意図
- 網羅性
ExtPlayerPrefs
の全機能(プリミティブ型、複雑な型、ScriptableObject
)をカバー。- 同期処理・非同期処理の両方をテスト。
- 信頼性
- 保存前後のデータ一致を厳密に検証。
- ファイル操作における異常系を徹底的にチェック。
- 拡張性
- 新しいデータ型や機能を追加する際も、このテストを基盤として容易に検証を追加可能。
テストの実行方法
- Unityエディタでテスト実行:
Window > General > Test Runner
を開き、Edit Mode または Play Mode テストを選択。- 対象のテストを実行して結果を確認。
- テスト結果の確認:
- 成功時: すべてのテストが緑色で表示されます。
- 失敗時: エラーが発生したテストが赤色で表示され、失敗の詳細を確認できます。
結論
このテストコードは、ExtPlayerPrefs
クラスの全機能を網羅し、実際の運用で信頼性の高い動作を保証するものです。
- 対応範囲:
- プリミティブ型(
int
、string
など)
- プリミティブ型(
- 複雑な型(クラス、オブジェクト)
- Unity特有の型(
ScriptableObject
)
- Unity特有の型(
- 検証内容:
- 正常系(保存・読み出し)
- 異常系(エラー処理)
本テストコードを基に、ExtPlayerPrefs
の信頼性を高め、Unityプロジェクトでのデータ管理を強化できます。
参考)全テストコード
Assert.AreEqualメソッドは、最新のAssert.Thatを使うようにしています
using NUnit.Framework;
using UnityEngine;
using System.IO;
using System.Threading.Tasks;
using UnityEngine.TestTools;
namespace HKUtility.Tests
{
public class ExtPlayerPrefsTests
{
private const string TestFileName = "test_data.json";
private const string TestScriptableObjectFileName = "test_scriptable_object.json";
private const string EncryptionKey = "test_key";
private string testFilePath;
[SetUp]
public void SetUp()
{
testFilePath = Path.Combine(Application.persistentDataPath, TestFileName);
if (File.Exists(testFilePath))
{
File.Delete(testFilePath);
}
string scriptableObjectPath = Path.Combine(Application.persistentDataPath, TestScriptableObjectFileName);
if (File.Exists(scriptableObjectPath))
{
File.Delete(scriptableObjectPath);
}
}
[TearDown]
public void TearDown()
{
if (File.Exists(testFilePath))
{
File.Delete(testFilePath);
}
string scriptableObjectPath = Path.Combine(Application.persistentDataPath, TestScriptableObjectFileName);
if (File.Exists(scriptableObjectPath))
{
File.Delete(scriptableObjectPath);
}
}
[Test]
public void SaveAndLoad_ShouldWorkCorrectly()
{
var testData = new TestData { Name = "TestUser", Age = 25 };
// Save the data
var savedJson = ExtPlayerPrefs.Save(testData, TestFileName, EncryptionKey);
Assert.That(savedJson, Is.Not.Null);
Assert.That(File.Exists(testFilePath), Is.True);
// Load the data
var loadedData = ExtPlayerPrefs.Load<TestData>(TestFileName, EncryptionKey);
Assert.That(loadedData, Is.Not.Null);
Assert.That(loadedData.Name, Is.EqualTo(testData.Name));
Assert.That(loadedData.Age, Is.EqualTo(testData.Age));
}
[Test]
public async Task SaveAndLoadAsync_ShouldWorkCorrectly()
{
var testData = new TestData { Name = "AsyncUser", Age = 30 };
// Save the data asynchronously
var savedJson = await ExtPlayerPrefs.SaveAsync(testData, TestFileName, EncryptionKey);
Assert.That(savedJson, Is.Not.Null);
Assert.That(File.Exists(testFilePath), Is.True);
// Load the data asynchronously
var loadedData = await ExtPlayerPrefs.LoadAsync<TestData>(TestFileName, EncryptionKey);
Assert.That(loadedData, Is.Not.Null);
Assert.That(loadedData.Name, Is.EqualTo(testData.Name));
Assert.That(loadedData.Age, Is.EqualTo(testData.Age));
}
[Test]
public void SaveScriptableObjectAndLoadScriptableObject_ShouldWorkCorrectly()
{
var scriptableObject = ScriptableObject.CreateInstance<TestScriptableObject>();
scriptableObject.Description = "Test Description";
scriptableObject.Value = 42;
// Save ScriptableObject
var savedJson = ExtPlayerPrefs.SaveScriptableObject(scriptableObject, TestScriptableObjectFileName, EncryptionKey);
Assert.That(savedJson, Is.Not.Null);
Assert.That(File.Exists(Path.Combine(Application.persistentDataPath, TestScriptableObjectFileName)), Is.True);
// Load ScriptableObject
var loadedObject = ScriptableObject.CreateInstance<TestScriptableObject>();
ExtPlayerPrefs.LoadScriptableObject(loadedObject, TestScriptableObjectFileName, EncryptionKey);
Assert.That(loadedObject.Description, Is.EqualTo(scriptableObject.Description));
Assert.That(loadedObject.Value, Is.EqualTo(scriptableObject.Value));
}
[Test]
public async Task SaveScriptableObjectAsyncAndLoadScriptableObjectAsync_ShouldWorkCorrectly()
{
var scriptableObject = ScriptableObject.CreateInstance<TestScriptableObject>();
scriptableObject.Description = "Async Test Description";
scriptableObject.Value = 99;
// Save ScriptableObject asynchronously
var savedJson = await ExtPlayerPrefs.SaveScriptableObjectAsync(scriptableObject, TestScriptableObjectFileName, EncryptionKey);
Assert.That(savedJson, Is.Not.Null);
Assert.That(File.Exists(Path.Combine(Application.persistentDataPath, TestScriptableObjectFileName)), Is.True);
// Load ScriptableObject asynchronously
var loadedObject = ScriptableObject.CreateInstance<TestScriptableObject>();
await ExtPlayerPrefs.LoadScriptableObjectAsync(loadedObject, TestScriptableObjectFileName, EncryptionKey);
Assert.That(loadedObject.Description, Is.EqualTo(scriptableObject.Description));
Assert.That(loadedObject.Value, Is.EqualTo(scriptableObject.Value));
}
[Test]
public void Load_NonExistentFile_ShouldThrowFileNotFoundException()
{
Assert.That(() => ExtPlayerPrefs.Load<TestData>("non_existent.json"), Throws.TypeOf<FileNotFoundException>());
}
[Test]
public void Save_NullObject_ShouldThrowArgumentNullException()
{
Assert.That(() => ExtPlayerPrefs.Save<TestData>(null, TestFileName), Throws.TypeOf<System.ArgumentNullException>());
}
[Test]
public void SaveScriptableObject_Null_ShouldThrowArgumentNullException()
{
Assert.That(() => ExtPlayerPrefs.SaveScriptableObject<TestScriptableObject>(null, TestScriptableObjectFileName), Throws.TypeOf<System.ArgumentNullException>());
}
[System.Serializable]
private class TestData
{
public string Name;
public int Age;
}
[System.Serializable]
private class TestScriptableObject : ScriptableObject
{
public string Description;
public int Value;
}
}
}
ディスカッション
コメント一覧
まだ、コメントがありません