Skip to content

Commit c8578cb

Browse files
metyatechclaude
andcommitted
test: add positive-path automation tests with minimal OBJ and glTF test assets
- Add test assets: test_triangle.obj, test_cube.obj, test_scene.gltf - Add positive-path tests: verify actual file loading succeeds and returns non-empty mesh data for OBJ and glTF formats - Add LoadMeshFromAssetData test loading OBJ bytes from memory - Add Projects module dependency for IPluginManager access Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent f8c5995 commit c8578cb

6 files changed

Lines changed: 231 additions & 1 deletion

File tree

Source/RuntimeAssetImportTest/Private/AssetLoaderTest.cpp

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
#include "AssetLoader.h"
22
#include "CoreMinimal.h"
3+
#include "Interfaces/IPluginManager.h"
34
#include "Misc/AutomationTest.h"
5+
#include "Misc/FileHelper.h"
6+
7+
// ---------------------------------------------------------------------------
8+
// Failure-path tests
9+
// ---------------------------------------------------------------------------
410

511
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
612
FLoadMeshFromAssetFile_NonExistentPath_ReturnsFailure,
@@ -51,3 +57,136 @@ bool FLoadMeshFromAssetData_EmptyArray_ReturnsFailure::RunTest(const FString& Pa
5157
Result, ELoadMeshFromAssetDataResult::Failure);
5258
return true;
5359
}
60+
61+
// ---------------------------------------------------------------------------
62+
// Positive-path tests
63+
// ---------------------------------------------------------------------------
64+
65+
namespace
66+
{
67+
FString GetTestAssetsDir()
68+
{
69+
TSharedPtr<IPlugin> Plugin = IPluginManager::Get().FindPlugin(TEXT("RuntimeAssetImport"));
70+
if (!Plugin.IsValid())
71+
{
72+
return FString();
73+
}
74+
return FPaths::Combine(Plugin->GetBaseDir(),
75+
TEXT("Source/RuntimeAssetImportTest/TestAssets"));
76+
}
77+
} // namespace
78+
79+
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
80+
FLoadMeshFromAssetFile_ObjTriangle_ReturnsSuccess,
81+
"RuntimeAssetImport.AssetLoader.LoadMeshFromAssetFile.ObjTriangle",
82+
EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter)
83+
84+
bool FLoadMeshFromAssetFile_ObjTriangle_ReturnsSuccess::RunTest(const FString& Parameters)
85+
{
86+
const FString TestAssetsDir = GetTestAssetsDir();
87+
if (TestAssetsDir.IsEmpty())
88+
{
89+
AddError(TEXT("Could not find RuntimeAssetImport plugin"));
90+
return false;
91+
}
92+
const FString ObjPath = FPaths::Combine(TestAssetsDir, TEXT("test_triangle.obj"));
93+
94+
ELoadMeshFromAssetFileResult Result;
95+
FLoadedMeshData MeshData = UAssetLoader::LoadMeshFromAssetFile(ObjPath, Result);
96+
97+
TestEqual(
98+
TEXT("Loading a valid OBJ triangle should return Success"),
99+
Result, ELoadMeshFromAssetFileResult::Success);
100+
TestTrue(
101+
TEXT("Loaded OBJ triangle should have at least one mesh node"),
102+
MeshData.NodeList.Num() > 0);
103+
return true;
104+
}
105+
106+
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
107+
FLoadMeshFromAssetFile_ObjCube_ReturnsSuccess,
108+
"RuntimeAssetImport.AssetLoader.LoadMeshFromAssetFile.ObjCube",
109+
EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter)
110+
111+
bool FLoadMeshFromAssetFile_ObjCube_ReturnsSuccess::RunTest(const FString& Parameters)
112+
{
113+
const FString TestAssetsDir = GetTestAssetsDir();
114+
if (TestAssetsDir.IsEmpty())
115+
{
116+
AddError(TEXT("Could not find RuntimeAssetImport plugin"));
117+
return false;
118+
}
119+
const FString ObjPath = FPaths::Combine(TestAssetsDir, TEXT("test_cube.obj"));
120+
121+
ELoadMeshFromAssetFileResult Result;
122+
FLoadedMeshData MeshData = UAssetLoader::LoadMeshFromAssetFile(ObjPath, Result);
123+
124+
TestEqual(
125+
TEXT("Loading a valid OBJ cube should return Success"),
126+
Result, ELoadMeshFromAssetFileResult::Success);
127+
TestTrue(
128+
TEXT("Loaded OBJ cube should have at least one mesh node"),
129+
MeshData.NodeList.Num() > 0);
130+
return true;
131+
}
132+
133+
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
134+
FLoadMeshFromAssetFile_GltfScene_ReturnsSuccess,
135+
"RuntimeAssetImport.AssetLoader.LoadMeshFromAssetFile.GltfScene",
136+
EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter)
137+
138+
bool FLoadMeshFromAssetFile_GltfScene_ReturnsSuccess::RunTest(const FString& Parameters)
139+
{
140+
const FString TestAssetsDir = GetTestAssetsDir();
141+
if (TestAssetsDir.IsEmpty())
142+
{
143+
AddError(TEXT("Could not find RuntimeAssetImport plugin"));
144+
return false;
145+
}
146+
const FString GltfPath = FPaths::Combine(TestAssetsDir, TEXT("test_scene.gltf"));
147+
148+
ELoadMeshFromAssetFileResult Result;
149+
FLoadedMeshData MeshData = UAssetLoader::LoadMeshFromAssetFile(GltfPath, Result);
150+
151+
TestEqual(
152+
TEXT("Loading a valid glTF scene should return Success"),
153+
Result, ELoadMeshFromAssetFileResult::Success);
154+
TestTrue(
155+
TEXT("Loaded glTF scene should have at least one mesh node"),
156+
MeshData.NodeList.Num() > 0);
157+
return true;
158+
}
159+
160+
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
161+
FLoadMeshFromAssetData_ObjTriangle_ReturnsSuccess,
162+
"RuntimeAssetImport.AssetLoader.LoadMeshFromAssetData.ObjTriangle",
163+
EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter)
164+
165+
bool FLoadMeshFromAssetData_ObjTriangle_ReturnsSuccess::RunTest(const FString& Parameters)
166+
{
167+
const FString TestAssetsDir = GetTestAssetsDir();
168+
if (TestAssetsDir.IsEmpty())
169+
{
170+
AddError(TEXT("Could not find RuntimeAssetImport plugin"));
171+
return false;
172+
}
173+
const FString ObjPath = FPaths::Combine(TestAssetsDir, TEXT("test_triangle.obj"));
174+
175+
TArray<uint8> FileBytes;
176+
if (!FFileHelper::LoadFileToArray(FileBytes, *ObjPath))
177+
{
178+
AddError(FString::Printf(TEXT("Could not read test asset: %s"), *ObjPath));
179+
return false;
180+
}
181+
182+
ELoadMeshFromAssetDataResult Result;
183+
FLoadedMeshData MeshData = UAssetLoader::LoadMeshFromAssetData(FileBytes, Result);
184+
185+
TestEqual(
186+
TEXT("Loading OBJ triangle bytes should return Success"),
187+
Result, ELoadMeshFromAssetDataResult::Success);
188+
TestTrue(
189+
TEXT("Loaded OBJ triangle from memory should have at least one mesh node"),
190+
MeshData.NodeList.Num() > 0);
191+
return true;
192+
}

Source/RuntimeAssetImportTest/RuntimeAssetImportTest.Build.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ public RuntimeAssetImportTest(ReadOnlyTargetRules Target) : base(Target)
66
{
77
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
88

9-
PublicDependencyModuleNames.AddRange(new string[] { "Core", "RuntimeAssetImport" });
9+
PublicDependencyModuleNames.AddRange(new string[] { "Core", "RuntimeAssetImport", "Projects" });
1010
PrivateDependencyModuleNames.AddRange(new string[] { "CoreUObject", "Engine" });
1111
}
1212
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Minimal OBJ test file - cube for automated testing
2+
# Tests multi-section mesh loading
3+
4+
v -0.5 -0.5 0.5
5+
v 0.5 -0.5 0.5
6+
v 0.5 0.5 0.5
7+
v -0.5 0.5 0.5
8+
v -0.5 -0.5 -0.5
9+
v 0.5 -0.5 -0.5
10+
v 0.5 0.5 -0.5
11+
v -0.5 0.5 -0.5
12+
13+
vn 0 0 1
14+
vn 0 0 -1
15+
vn 0 1 0
16+
vn 0 -1 0
17+
vn 1 0 0
18+
vn -1 0 0
19+
20+
f 1//1 2//1 3//1
21+
f 1//1 3//1 4//1
22+
f 6//2 5//2 8//2
23+
f 6//2 8//2 7//2
24+
f 4//3 3//3 7//3
25+
f 4//3 7//3 8//3
26+
f 5//4 6//4 2//4
27+
f 5//4 2//4 1//4
28+
f 2//5 6//5 7//5
29+
f 2//5 7//5 3//5
30+
f 5//6 1//6 4//6
31+
f 5//6 4//6 8//6
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"asset": { "version": "2.0", "generator": "RuntimeAssetImportPlugin Test" },
3+
"scene": 0,
4+
"scenes": [ { "name": "TestScene", "nodes": [ 0 ] } ],
5+
"nodes": [ { "name": "TestMesh", "mesh": 0 } ],
6+
"meshes": [
7+
{
8+
"name": "Triangle",
9+
"primitives": [
10+
{
11+
"attributes": { "POSITION": 0 },
12+
"indices": 1,
13+
"mode": 4
14+
}
15+
]
16+
}
17+
],
18+
"accessors": [
19+
{
20+
"bufferView": 0,
21+
"componentType": 5126,
22+
"count": 3,
23+
"type": "VEC3",
24+
"max": [ 1.0, 1.0, 0.0 ],
25+
"min": [ 0.0, 0.0, 0.0 ]
26+
},
27+
{
28+
"bufferView": 1,
29+
"componentType": 5123,
30+
"count": 3,
31+
"type": "SCALAR"
32+
}
33+
],
34+
"bufferViews": [
35+
{ "buffer": 0, "byteOffset": 0, "byteLength": 36 },
36+
{ "buffer": 0, "byteOffset": 36, "byteLength": 6 }
37+
],
38+
"buffers": [
39+
{
40+
"byteLength": 42,
41+
"uri": "data:application/octet-stream;base64,AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAACAPwAAAAAAAAABAAIA"
42+
}
43+
]
44+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Material file for test_triangle.obj
2+
newmtl TestMaterial
3+
Kd 0.8 0.4 0.2
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Minimal OBJ test file - single triangle for automated testing
2+
# This file is used by RuntimeAssetImportTest automation tests
3+
4+
mtllib test_triangle.mtl
5+
6+
v 0.0 0.0 0.0
7+
v 1.0 0.0 0.0
8+
v 0.5 1.0 0.0
9+
10+
vn 0.0 0.0 1.0
11+
12+
usemtl TestMaterial
13+
f 1//1 2//1 3//1

0 commit comments

Comments
 (0)