diff --git a/GFramework.Core.Tests/Packaging/TransitiveGlobalUsingsPackagingTests.cs b/GFramework.Core.Tests/Packaging/TransitiveGlobalUsingsPackagingTests.cs index 2ca6a9c..78bda4b 100644 --- a/GFramework.Core.Tests/Packaging/TransitiveGlobalUsingsPackagingTests.cs +++ b/GFramework.Core.Tests/Packaging/TransitiveGlobalUsingsPackagingTests.cs @@ -1,4 +1,7 @@ using System.IO; +using System.Runtime.CompilerServices; +using GFramework.Core.Architectures; +using GFramework.Core.Coroutine.Extensions; namespace GFramework.Core.Tests.Packaging; @@ -9,6 +12,27 @@ namespace GFramework.Core.Tests.Packaging; [TestFixture] public class TransitiveGlobalUsingsPackagingTests { + /// + /// 使用真实类型派生架构命名空间,避免测试断言和命名空间重构脱节。 + /// + private static readonly string ArchitectureNamespace = typeof(Architecture).Namespace + ?? throw new InvalidOperationException( + "Architecture namespace should not be null."); + + /// + /// 使用真实类型派生扩展命名空间,避免对字面量命名空间字符串的重复维护。 + /// + private static readonly string ExtensionsNamespace = typeof(ContextAwareEnvironmentExtensions).Namespace + ?? throw new InvalidOperationException( + "Extensions namespace should not be null."); + + /// + /// 使用真实类型派生协程扩展命名空间,确保断言和源码自动发现保持一致。 + /// + private static readonly string CoroutineExtensionsNamespace = typeof(CoroutineExtensions).Namespace + ?? throw new InvalidOperationException( + "Coroutine extensions namespace should not be null."); + /// /// 验证 GFramework.Core 在构建后会生成 transitive global usings props, /// 且 props 内容来自源码自动发现,并保留消费者侧排除机制。 @@ -16,7 +40,7 @@ public class TransitiveGlobalUsingsPackagingTests [Test] public void CoreBuild_Should_Generate_AutoDiscovered_TransitiveGlobalUsingsProps() { - var repositoryRoot = FindRepositoryRoot(); + var repositoryRoot = ResolveRepositoryRoot(); var propsPath = Path.Combine( repositoryRoot, "GFramework.Core", @@ -27,30 +51,30 @@ public class TransitiveGlobalUsingsPackagingTests Assert.That(File.Exists(propsPath), Is.True, $"Expected generated props to exist: {propsPath}"); var propsContent = File.ReadAllText(propsPath); - Assert.That(propsContent, Does.Contain("GFramework.Core.Extensions")); - Assert.That(propsContent, Does.Contain("GFramework.Core.Architectures")); - Assert.That(propsContent, Does.Contain("GFramework.Core.Coroutine.Extensions")); + Assert.That(propsContent, Does.Contain(ExtensionsNamespace)); + Assert.That(propsContent, Does.Contain(ArchitectureNamespace)); + Assert.That(propsContent, Does.Contain(CoroutineExtensionsNamespace)); Assert.That(propsContent, Does.Contain("Remove=\"@(GFrameworkExcludedUsing)\"")); Assert.That(propsContent, Does.Not.Contain("System.Runtime.CompilerServices")); } /// - /// 从测试输出目录向上回溯,定位包含解决方案文件的仓库根目录。 + /// 基于当前测试源文件的已知位置解析仓库根目录。 + /// 这里不扫描解决方案文件,避免测试对仓库布局演进产生额外脆弱性。 /// + /// 由编译器注入的当前测试源文件绝对路径。 /// 仓库根目录绝对路径。 - private static string FindRepositoryRoot() + private static string ResolveRepositoryRoot([CallerFilePath] string sourceFilePath = "") { - var currentDirectory = new DirectoryInfo(TestContext.CurrentContext.TestDirectory); - - while (currentDirectory != null) + if (string.IsNullOrWhiteSpace(sourceFilePath)) { - var solutionPath = Path.Combine(currentDirectory.FullName, "GFramework.sln"); - if (File.Exists(solutionPath)) - return currentDirectory.FullName; - - currentDirectory = currentDirectory.Parent; + throw new InvalidOperationException("Caller file path is required to resolve the repository root."); } - throw new DirectoryNotFoundException("Could not locate the repository root for GFramework."); + var sourceDirectory = Path.GetDirectoryName(sourceFilePath) + ?? throw new DirectoryNotFoundException( + $"Could not determine the directory for source file path: {sourceFilePath}"); + + return Path.GetFullPath(Path.Combine(sourceDirectory, "..", "..")); } } \ No newline at end of file