If you’re knee-deep in a Unity project and pulling your hair out trying to set up unit testing, you’re not alone. The two biggest challenges are dealing with Assembly Definitions
and Editor
folders. Here’s a guide to overcome these issues and make your life easier.
The Problem
Unity, in its infinite wisdom, doesn’t allow writing tests on the default Assembly-CSharp
and Assembly-CSharp-Editor
assemblies. Frustrating, right?
To fix this, you need to add Assembly Definitions
for both your game code and editor code. Here’s how:
-
Game Code:
- Add an
Assembly Definition
at the root of your project. - Update the dependencies in the Inspector until there are no compiler errors. Off to the races!
- Add an
-
Editor Code:
- Here’s where it gets tricky. In a big project, you’ll have lots of external dependencies and plugins, some with
Assembly Definitions
, some without. - Without
Assembly Definitions
, Unity sees theseEditor
folders as game code and tries to build them into your final game, which inevitably fails.
- Here’s where it gets tricky. In a big project, you’ll have lots of external dependencies and plugins, some with
The Solution
-
Create a Top-Level Editor Folder:
- At the top level of your project, create an
Editor
folder. - Add an
Assembly Definition
inside this folder. Name it similarly to your game codeAssembly Definition
but with a.Editor
postfix (or whatever you prefer).
- At the top level of your project, create an
-
Link Editor Folders:
- For each
Editor
folder in your project, create anAssembly Definition Reference
and link it to the top-levelEditor
folderAssembly Definition
. - This process can be incredibly tedious in a large project, so here’s a Python script to save you from hours of mind-numbing work:
- For each
import os
import json
import yaml
def get_guid_from_meta(meta_file_path):
with open(meta_file_path, 'r') as meta_file:
meta_content = yaml.safe_load(meta_file)
return meta_content.get('guid')
def create_reference_json(editor_path, source_file_name, guid):
json_content = {
"reference": "GUID:" + guid
}
asmref_file_name = os.path.splitext(source_file_name)[0] + '.asmref'
json_file_path = os.path.join(editor_path, asmref_file_name)
with open(json_file_path, 'w') as json_file:
json.dump(json_content, json_file, indent=4)
print(f"Created {json_file_path} with GUID reference.")
def copy_file_to_editor_folders(unity_project_path, source_file):
if not os.path.isdir(unity_project_path):
print(f"The project path {unity_project_path} does not exist.")
return
meta_file_path = source_file + '.meta'
if not os.path.isfile(meta_file_path):
print(f"The meta file {meta_file_path} does not exist.")
return
guid = get_guid_from_meta(meta_file_path)
source_file_name = os.path.basename(source_file)
for root, dirs, files in os.walk(unity_project_path):
if 'Editor' in dirs:
editor_path = os.path.join(root, 'Editor')
asmdef_exists = any(file.endswith('.asmdef') for file in os.listdir(editor_path))
if not asmdef_exists:
create_reference_json(editor_path, source_file_name, guid)
else:
print(f"A .asmdef file already exists in the folder {editor_path}.")
# Example usage
unity_project_path = r"PATH\TO\ASSETS\FOLDER"
source_file = r"PATH\TO\Editor.asmdef"
copy_file_to_editor_folders(unity_project_path, source_file)
This script requires pyyaml
to run:
pip install pyyaml
- Set
unity_project_path
to your Unity project’s assets folder. - Set
source_file
to the path of yourEditor
Assembly Definition
.
The script will:
- Crawl your project for all
Editor
folders. - Check if an
Assembly Definition
is present. - Add an
Assembly Definition Reference
if none exists.
After setting this up, follow the Unity Testing Framework tutorial to start writing tests.
Additional Tips
Consider splitting your code with Assembly Definitions
to create logical boundaries and improve maintainability. It might be a pain now, but your future self will thank you!
Happy testing!
Top comments (0)