{"record":{"id":"aef8fe4ecb1abfff","repo":"stride3d/stride","slug":"stride-games-autotesting-registeredtest-gettype-fullname-is","errorCode":null,"errorMessage":"Stride.Games.AutoTesting: '{RegisteredTest.GetType().FullName}' is already registered; exactly one [ScreenshotTest] per sample is allowed (tried to register '{test.GetType().FullName}').","messagePattern":"Stride\\.Games\\.AutoTesting: '(.+?)' is already registered; exactly one \\[ScreenshotTest\\] per sample is allowed \\(tried to register '(.+?)'\\)\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Games.AutoTesting/ScreenshotTestRunner.cs","lineNumber":43,"sourceCode":"/// before exiting the game.\n/// </summary>\npublic static class AutoTestingBootstrap\n{\n    /// <summary>The test registered for this run, or null if none (non-test build).</summary>\n    internal static IScreenshotTest? RegisteredTest { get; private set; }\n\n    /// <summary>\n    /// Registers the screenshot-test driver for this sample. Called from a [ModuleInitializer] in\n    /// the test fixture: invoking a method here force-loads this assembly (so the\n    /// <see cref=\"ScreenshotTestRunner\"/>'s [ModuleInitializer] runs and hooks\n    /// <see cref=\"Game.GameStarted\"/>), and hands over the concrete instance directly — no reflection,\n    /// keeping the discovery path trim/AOT-clean.\n    /// </summary>\n    public static void RegisterTest(IScreenshotTest test)\n    {\n        ArgumentNullException.ThrowIfNull(test);\n        if (RegisteredTest is not null && RegisteredTest.GetType() != test.GetType())\n            throw new InvalidOperationException(\n                $\"Stride.Games.AutoTesting: '{RegisteredTest.GetType().FullName}' is already registered; \" +\n                $\"exactly one [ScreenshotTest] per sample is allowed (tried to register '{test.GetType().FullName}').\");\n        RegisteredTest = test;\n    }\n}\n\n/// <summary>\n/// Installs native-crash diagnostics for the sample run from a [ModuleInitializer].\n/// See <see cref=\"NativeCrashHandler\"/> (shared with Stride.Graphics.Regression).\n/// </summary>\ninternal static class CrashDiagnostics\n{\n    [ModuleInitializer]\n    internal static void Initialize()\n    {\n        NativeCrashHandler.Install();\n\n        // Crash-report popups must never interrupt a test run: unless the caller chose a mode, tools","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Games.AutoTesting/ScreenshotTestRunner.cs#L25-L61","documentation":"ScreenshotTestRunner.RegisterTest enforces that exactly one IScreenshotTest instance type is registered per process. If a test with a different type is registered while one is already held, it throws InvalidOperationException naming both types.","triggerScenarios":"An app assembly containing two or more classes marked [ScreenshotTest], each triggering static registration on startup.","commonSituations":"Adding a second sample screen with [ScreenshotTest] to an existing sample project; copy-pasting a test class without removing the old one; merging branches that each added a screenshot test.","solutions":["Remove [ScreenshotTest] from all but one test class in the project","Delete the redundant/obsolete test class","If both tests are needed, split them into separate sample projects/executables"],"exampleFix":"// before\n[ScreenshotTest]\npublic class ScreenATest : IScreenshotTest { ... }\n[ScreenshotTest]\npublic class ScreenBTest : IScreenshotTest { ... }\n// after\n[ScreenshotTest]\npublic class ScreenATest : IScreenshotTest { ... }\npublic class ScreenBTest : IScreenshotTest { ... } // attribute removed","handlingStrategy":"validation","validationCode":"if (ScreenshotTestRunner.RegisteredTest is not null && ScreenshotTestRunner.RegisteredTest.GetType() != test.GetType())\n    throw new InvalidOperationException(\"Multiple [ScreenshotTest] classes in this project\");\nScreenshotTestRunner.RegisterTest(test);","typeGuard":"bool IsFirstOrSame(IScreenshotTest t) => ScreenshotTestRunner.RegisteredTest is null || ScreenshotTestRunner.RegisteredTest.GetType() == t.GetType();","tryCatchPattern":"try { ScreenshotTestRunner.RegisterTest(test); } catch (InvalidOperationException ex) { /* log duplicate test type and skip */ }","preventionTips":["Keep exactly one [ScreenshotTest] class per sample project","Grep the project for [ScreenshotTest] before adding a new one"],"tags":["testing","screenshots","duplicate-registration"],"backgroundTag":"invalid-state-transition","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}