Last active
March 6, 2024 03:42
-
-
Save SolidAlloy/3027f88e69b63700b9ae530360cfd0eb to your computer and use it in GitHub Desktop.
AssetDatabase unit tests that show the implications of Refresh() and SaveAssets()
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using JetBrains.Annotations; | |
using NUnit.Framework; | |
using UnityEditor; | |
using UnityEngine; | |
using Object = UnityEngine.Object; | |
/// <summary> | |
/// Unit tests that show how AssetDatabase operates. | |
/// </summary> | |
public class AssetDatabaseTests | |
{ | |
private const string TestingFolder = "Assets/Testing"; | |
private const string ExpectedFieldValue = "changed"; | |
[OneTimeSetUp] | |
public void BeforeAllTests() | |
{ | |
var parts = TestingFolder.Split(new[] { '/' }, 2); | |
AssetDatabase.CreateFolder(parts[0], parts[1]); | |
} | |
[OneTimeTearDown] | |
public void AfterAllTests() | |
{ | |
AssetDatabase.DeleteAsset(TestingFolder); | |
} | |
[Test] | |
public void Does_not_register_a_manually_created_file_without_refresh() | |
{ | |
string assetPath = CreateFileManually(); | |
string actualGUID = AssetDatabase.AssetPathToGUID(assetPath); | |
Assert.IsTrue(string.IsNullOrEmpty(actualGUID)); | |
} | |
[Test] | |
public void Registers_file_without_refresh_after_CreateAsset() | |
{ | |
string assetPath = CreateFileThroughAssetDatabase(); | |
string actualGUID = AssetDatabase.AssetPathToGUID(assetPath); | |
Assert.IsFalse(string.IsNullOrEmpty(actualGUID)); | |
} | |
[Test] | |
public void Cannot_obtain_object_from_manually_created_asset_without_refresh() | |
{ | |
string assetPath = CreateFileManually(); | |
var asset = AssetDatabase.LoadAssetAtPath<TextAsset>(assetPath); | |
Assert.IsNull(asset); | |
} | |
[Test] | |
public void Can_obtain_object_from_asset_created_using_CreateAsset_without_refresh() | |
{ | |
string assetPath = CreateFileThroughAssetDatabase(); | |
var asset = AssetDatabase.LoadAssetAtPath<TextAsset>(assetPath); | |
Assert.IsNotNull(asset); | |
} | |
[Test] | |
public void Can_obtain_object_from_manually_created_asset_after_refresh() | |
{ | |
string assetPath = CreateFileManually(); | |
AssetDatabase.Refresh(); | |
var asset = AssetDatabase.LoadAssetAtPath<TextAsset>(assetPath); | |
Assert.IsNotNull(asset); | |
} | |
// BE AWARE !!! | |
// A GUID of a previously created asset is not removed from AssetDatabase until an Editor restart, | |
// no matter in what way you delete the asset. | |
[Test] | |
public void Does_not_remove_guid_from_database_after_asset_is_loaded() | |
{ | |
string assetPath = CreateFileManually(); | |
AssetDatabase.Refresh(); | |
// Try everything to make AssetDatabase notice that both asset and the loaded Object are removed. | |
EditorUtility.UnloadUnusedAssetsImmediate(); | |
AssetDatabase.DeleteAsset(assetPath); | |
AssetDatabase.Refresh(); | |
string actualGUID = AssetDatabase.AssetPathToGUID(assetPath); | |
// The asset GUID is not empty. | |
Assert.IsFalse(string.IsNullOrEmpty(actualGUID)); | |
// And the path can still be obtained. | |
string actualAssetPath = AssetDatabase.GUIDToAssetPath(actualGUID); | |
Assert.AreEqual(assetPath, actualAssetPath); | |
// However, no assets can be loaded from it. | |
var assets = AssetDatabase.LoadAllAssetsAtPath(assetPath); | |
Assert.That(assets.Length.Equals(0)); | |
} | |
[Test] | |
public void Does_not_write_object_changes_to_disk_automatically() | |
{ | |
(string assetPath, _) = SetScriptableObjectFieldToExpectedValue(); | |
AssertThatChangesAreNotSaved(assetPath); | |
} | |
[Test] | |
public void Does_not_write_object_changes_to_disk_after_SaveAssets() | |
{ | |
(string assetPath, _) = SetScriptableObjectFieldToExpectedValue(); | |
AssetDatabase.SaveAssets(); | |
AssetDatabase.Refresh(); | |
AssertThatChangesAreNotSaved(assetPath); | |
} | |
[Test] | |
public void Does_not_write_object_changes_to_disk_after_SetDirty() | |
{ | |
(string assetPath, var scriptableObject) = SetScriptableObjectFieldToExpectedValue(); | |
EditorUtility.SetDirty(scriptableObject); | |
AssertThatChangesAreNotSaved(assetPath); | |
} | |
[Test] | |
public void Writes_object_changes_to_disk_after_SetDirty_and_SaveAssets() | |
{ | |
(string assetPath, var scriptableObject) = SetScriptableObjectFieldToExpectedValue(); | |
EditorUtility.SetDirty(scriptableObject); | |
AssetDatabase.SaveAssets(); | |
string fileContent = File.ReadAllText(assetPath); | |
Assert.IsTrue(fileContent.Contains(ExpectedFieldValue)); | |
} | |
private static string CreateFileManually() | |
{ | |
string assetPath = GetUniqueTextFilePath(); | |
File.WriteAllText(assetPath, "test"); | |
return assetPath; | |
} | |
private static string CreateFileThroughAssetDatabase() | |
{ | |
string assetPath = GetUniqueTextFilePath(); | |
TextAsset asset = new TextAsset("test"); | |
AssetDatabase.CreateAsset(asset, assetPath); | |
return assetPath; | |
} | |
private static string GetUniqueTextFilePath() | |
{ | |
return $"{TestingFolder}/test{Guid.NewGuid().ToString()}.txt"; | |
} | |
private static (string assetPath, Object obj) SetScriptableObjectFieldToExpectedValue() | |
{ | |
(string assetPath, var testSO) = CreateTestSOAsset(); | |
testSO.StringField = ExpectedFieldValue; | |
return (assetPath, testSO); | |
} | |
private static void AssertThatChangesAreNotSaved(string assetPath) | |
{ | |
string fileContent = File.ReadAllText(assetPath); | |
Assert.IsFalse(fileContent.Contains(ExpectedFieldValue)); | |
} | |
private static (string assetPath, TestScriptableObject obj) CreateTestSOAsset() | |
{ | |
var testSO = ScriptableObject.CreateInstance<TestScriptableObject>(); | |
string assetPath = GetUniqueScriptableObjectPath(); | |
AssetDatabase.CreateAsset(testSO, assetPath); | |
return (assetPath, testSO); | |
} | |
private static string GetUniqueScriptableObjectPath() | |
{ | |
return $"{TestingFolder}/testSO{Guid.NewGuid().ToString()}.asset"; | |
} | |
private class TestScriptableObject : ScriptableObject | |
{ | |
[UsedImplicitly] | |
public string StringField; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment