Files
spacegame/Plugins/UnrealMCPython/Content/Python/UnrealMCPython/tests/test_data_table.py
Joshua Deville 496320cc8c Add empty test level and Unreal MCP tooling
- L_TestFlight: empty, zero-gravity level for Phase 0 flight testing,
  set as editor/game default map.
- Enable UnrealMCPython + Python Editor Script Plugin, third-party
  MCP plugin (GenOrca/unreal-mcp v2.2.0) giving direct editor control
  (actors, blueprints, levels, materials, etc.) alongside Epic's
  built-in Unreal MCP plugin.
- Vendor the mcp-server Python source used to bridge to the plugin.
- .mcp.json intentionally gitignored (machine-specific absolute paths).
2026-07-08 14:56:57 -04:00

105 lines
4.3 KiB
Python

import unreal
from UnrealMCPython.tests.base import MCPTestCase, TEST_ROOT
# A DataTable that ships with the NNEDenoiser plugin (10 rows) — duplicated into
# /Game so write actions never touch read-only plugin assets.
_SRC_DT = "/NNEDenoiser/NNEDIM_ColorAlbedoNormal_Default"
_DT_NAME = "MCP_TestDataTable"
_DT_PATH = f"{TEST_ROOT}/{_DT_NAME}"
class TestDataTableActions(MCPTestCase):
def setUp(self):
self._dt_path = None
self.ensure_test_dir()
self.delete_asset(_DT_PATH)
if unreal.EditorAssetLibrary.does_asset_exist(_SRC_DT):
dt = unreal.EditorAssetLibrary.duplicate_asset(_SRC_DT, _DT_PATH)
if dt:
self._dt_path = _DT_PATH
def tearDown(self):
if self._dt_path:
self.delete_asset(self._dt_path)
def _skip_if_no_dt(self):
if not self._dt_path:
self.skipTest("Source DataTable (NNEDenoiser) not available")
def test_get_row_names(self):
self._skip_if_no_dt()
r = self.call("data_table_actions", "ue_get_row_names", asset_path=self._dt_path)
self.assertSuccess(r)
self.assertGreater(r["count"], 0)
def test_get_column_names(self):
self._skip_if_no_dt()
r = self.call("data_table_actions", "ue_get_column_names", asset_path=self._dt_path)
self.assertSuccess(r)
self.assertIsInstance(r["columns"], list)
self.assertIsNotNone(r["row_struct"])
def test_get_rows_as_json(self):
self._skip_if_no_dt()
r = self.call("data_table_actions", "ue_get_rows_as_json", asset_path=self._dt_path)
self.assertSuccess(r)
self.assertIn("rows", r)
self.assertTrue(r["rows"].strip().startswith("["))
def test_export_to_csv(self):
self._skip_if_no_dt()
r = self.call("data_table_actions", "ue_export_to_csv", asset_path=self._dt_path)
self.assertSuccess(r)
self.assertIn("csv", r)
def test_does_row_exist(self):
self._skip_if_no_dt()
names = self.call("data_table_actions", "ue_get_row_names", asset_path=self._dt_path)["row_names"]
r = self.call("data_table_actions", "ue_does_row_exist",
asset_path=self._dt_path, row_name=names[0])
self.assertSuccess(r)
self.assertTrue(r["exists"])
r = self.call("data_table_actions", "ue_does_row_exist",
asset_path=self._dt_path, row_name="NoSuchRow_XYZ")
self.assertFalse(r["exists"])
def test_remove_row(self):
self._skip_if_no_dt()
names = self.call("data_table_actions", "ue_get_row_names", asset_path=self._dt_path)["row_names"]
before = len(names)
r = self.call("data_table_actions", "ue_remove_row",
asset_path=self._dt_path, row_name=names[0])
self.assertSuccess(r)
after = self.call("data_table_actions", "ue_get_row_names", asset_path=self._dt_path)["count"]
self.assertEqual(after, before - 1)
def test_remove_row_missing(self):
self._skip_if_no_dt()
r = self.call("data_table_actions", "ue_remove_row",
asset_path=self._dt_path, row_name="NoSuchRow_XYZ")
self.assertFalse(r.get("success"))
def test_set_rows_from_json(self):
self._skip_if_no_dt()
original = self.call("data_table_actions", "ue_get_rows_as_json", asset_path=self._dt_path)["rows"]
r = self.call("data_table_actions", "ue_set_rows_from_json",
asset_path=self._dt_path, json_string=original)
self.assertSuccess(r)
self.assertGreater(r["row_count"], 0)
def test_create_data_table(self):
self._skip_if_no_dt()
# Reuse the source table's row struct to create a fresh, empty DataTable.
struct_path = self.call("data_table_actions", "ue_get_column_names",
asset_path=self._dt_path)["row_struct"]
new_path = f"{TEST_ROOT}/MCP_CreatedDT"
self.delete_asset(new_path)
try:
r = self.call("data_table_actions", "ue_create_data_table",
asset_path=new_path, row_struct_path=struct_path)
self.assertSuccess(r)
self.assertTrue(unreal.EditorAssetLibrary.does_asset_exist(new_path))
finally:
self.delete_asset(new_path)