{"record":{"id":"3dfaf47ea6153758","repo":"stride3d/stride","slug":"uitest-class-chosen-fullname-must-implement-iuitest","errorCode":null,"errorMessage":"[UITest] class {chosen.FullName} must implement IUITest.","messagePattern":"\\[UITest\\] class (.+?) must implement IUITest\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/editor/Stride.GameStudio.AutoTesting/UITestHost.cs","lineNumber":174,"sourceCode":"            throw new InvalidOperationException($\"No [UITest] class found in '{testDllPath}'.\");\n\n        Type chosen;\n        if (testClassName is not null)\n        {\n            chosen = candidates.FirstOrDefault(t => t.Name == testClassName || t.FullName == testClassName)\n                ?? throw new InvalidOperationException($\"No [UITest] class named '{testClassName}' in '{testDllPath}'. Available: {string.Join(\", \", candidates.Select(t => t.FullName))}\");\n        }\n        else if (candidates.Count == 1)\n        {\n            chosen = candidates[0];\n        }\n        else\n        {\n            throw new InvalidOperationException($\"Multiple [UITest] classes in '{testDllPath}'; pass --test-name to select. Available: {string.Join(\", \", candidates.Select(t => t.FullName))}\");\n        }\n\n        if (!typeof(IUITest).IsAssignableFrom(chosen))\n            throw new InvalidOperationException($\"[UITest] class {chosen.FullName} must implement IUITest.\");\n\n        return (IUITest)Activator.CreateInstance(chosen)!;\n    }\n\n    private void RunTest(IUITest test, Context ctx)\n    {\n        Task.Run(async () =>\n        {\n            var status = \"ok\";\n            object? exceptionInfo = null;\n            try\n            {\n                await test.Run(ctx);\n            }\n            catch (Exception ex)\n            {\n                status = \"error\";\n                exceptionInfo = SerializeException(ex);","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/editor/Stride.GameStudio.AutoTesting/UITestHost.cs#L156-L192","documentation":"After choosing the [UITest] class, LoadTest verifies it implements IUITest. If the annotated class does not implement the interface, it throws InvalidOperationException with the class's full name. The attribute alone is not sufficient; the type must be instantiable as an IUITest to be run.","triggerScenarios":"Annotating a class with [UITest] that does not implement IUITest (interface dropped during refactor, or attribute applied to a helper/model class by mistake).","commonSituations":"Renaming or refactoring removed the IUITest base; a developer copies [UITest] onto the wrong class; a partial implementation class only satisfies the interface in another assembly.","solutions":["Make the annotated class implement IUITest and rebuild.","Remove [UITest] from classes that are not actual runnable tests.","Point --test-name at the correct test class instead of the mis-annotated one.","Add a compile-time check (e.g. where T : IUITest pattern or unit test asserting all [UITest] types implement IUITest)."],"exampleFix":"// before\n[UITest]\npublic class SmokeTest { public void Run(Context ctx) { ... } }\n// after\n[UITest]\npublic class SmokeTest : IUITest { public void Run(Context ctx) { ... } }","handlingStrategy":"validation","validationCode":"var bad = asm.GetTypes()\n    .Where(t => t.GetCustomAttribute<UITestAttribute>() is not null && !typeof(IUITest).IsAssignableFrom(t))\n    .ToList();\nif (bad.Count > 0) throw new InvalidOperationException($\"[UITest] types not implementing IUITest: {string.Join(\", \", bad.Select(t => t.FullName))}\");","typeGuard":null,"tryCatchPattern":"try { test = LoadTest(dll, testName); }\ncatch (InvalidOperationException ex) { Console.Error.WriteLine(ex.Message); return 1; }","preventionTips":["Always derive test classes from IUITest","Never put [UITest] on non-test classes","Add a unit test asserting attribute/interface consistency"],"tags":["testing","interface","uitest"],"backgroundTag":"type-mismatch","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}