// MIT License - Copyright (c) 2025 wallstop
// Full license text: https://github.com/wallstop/unity-helpers/blob/main/LICENSE
namespace WallstopStudios.UnityHelpers.Core.Helper
{
using System;
using System.Reflection;
///
/// Internal helpers for detecting Unity test assemblies and types by name markers or attributes.
///
internal static class TestAssemblyHelper
{
private static readonly StringComparison Comparison = StringComparison.OrdinalIgnoreCase;
///
/// Heuristically determines if an assembly is a test assembly by name markers or Unity test attributes.
///
internal static bool IsTestAssembly(Assembly assembly)
{
if (assembly == null || assembly.IsDynamic)
{
return false;
}
string name = assembly.GetName().Name;
if (!string.IsNullOrEmpty(name) && ContainsTestMarker(name))
{
return true;
}
if (HasUnityTestAttribute(assembly))
{
return true;
}
return false;
}
///
/// Heuristically determines if a type belongs to a test assembly or a namespace with test markers.
///
internal static bool IsTestType(Type type)
{
if (type == null)
{
return false;
}
string ns = type.Namespace;
if (string.IsNullOrEmpty(ns))
{
return ContainsTestMarker(type.Name) || IsTestAssembly(type.Assembly);
}
if (ContainsTestMarker(ns))
{
return true;
}
return IsTestAssembly(type.Assembly);
}
///
/// Returns true if the string contains common test markers (e.g., Test, Tests, prefixes/suffixes/segments).
///
internal static bool ContainsTestMarker(string value)
{
if (string.IsNullOrEmpty(value))
{
return false;
}
if (
value.IndexOf(".Tests", Comparison) >= 0
|| value.IndexOf(".Test", Comparison) >= 0
|| value.IndexOf("Tests.", Comparison) >= 0
|| value.IndexOf("Tests_", Comparison) >= 0
|| value.IndexOf("Test.", Comparison) >= 0
|| value.IndexOf("Test_", Comparison) >= 0
)
{
return true;
}
if (value.EndsWith("Tests", Comparison) || value.EndsWith("Test", Comparison))
{
return true;
}
if (value.StartsWith("Tests", Comparison) || value.StartsWith("Test", Comparison))
{
return true;
}
if (value.IndexOf("Test", Comparison) >= 0)
{
return true;
}
return false;
}
private static bool HasUnityTestAttribute(Assembly assembly)
{
try
{
foreach (Attribute attribute in assembly.GetAllAttributesSafe(inherit: false))
{
Type attributeType = attribute?.GetType();
if (attributeType == null)
{
continue;
}
string fullName = attributeType.FullName;
if (
string.Equals(
fullName,
"UnityEngine.TestTools.UnityTestAssemblyAttribute",
Comparison
)
|| string.Equals(
fullName,
"UnityEditor.TestTools.TestRunner.UnityTestAssemblyAttribute",
Comparison
)
)
{
return true;
}
}
}
catch
{
return false;
}
return false;
}
}
}