From 407c863cb9a8d600c333bb1ce4b098deab5b7f94 Mon Sep 17 00:00:00 2001 From: tznind Date: Wed, 19 Mar 2025 19:51:51 +0000 Subject: [PATCH] Add support for outputting logs from tests #3972 --- TerminalGuiFluentTesting/GuiTestContext.cs | 67 ++++++++++++++----- TerminalGuiFluentTesting/With.cs | 2 +- .../FluentTests/BasicFluentAssertionTests.cs | 3 +- 3 files changed, 54 insertions(+), 18 deletions(-) diff --git a/TerminalGuiFluentTesting/GuiTestContext.cs b/TerminalGuiFluentTesting/GuiTestContext.cs index c623d9762..9f37fc045 100644 --- a/TerminalGuiFluentTesting/GuiTestContext.cs +++ b/TerminalGuiFluentTesting/GuiTestContext.cs @@ -1,10 +1,28 @@  +using System.Text; +using Microsoft.Extensions.Logging; using Terminal.Gui; using Terminal.Gui.ConsoleDrivers; namespace TerminalGuiFluentTesting; -public class GuiTestContext : IDisposable where T : Toplevel, new () + +class TextWriterLoggerProvider (TextWriter writer) : ILoggerProvider +{ + public ILogger CreateLogger (string category) => new TextWriterLogger (writer); + public void Dispose () => writer.Dispose (); +} + +class TextWriterLogger (TextWriter writer) : ILogger +{ + public IDisposable? BeginScope (TState state) => null; + public bool IsEnabled (LogLevel logLevel) => true; + public void Log (LogLevel logLevel, EventId eventId, TState state, + Exception? ex, Func formatter) => + writer.WriteLine (formatter (state, ex)); +} + +public class GuiTestContext : IDisposable { private readonly CancellationTokenSource _cts = new (); private readonly CancellationTokenSource _hardStop = new (With.Timeout); @@ -13,11 +31,14 @@ public class GuiTestContext : IDisposable where T : Toplevel, new () private readonly FakeOutput _output = new (); private readonly FakeWindowsInput _winInput; private readonly FakeNetInput _netInput; - private View _lastView; + private View? _lastView; + private readonly StringBuilder _logsSb; - internal GuiTestContext (int width, int height) + internal GuiTestContext(Func topLevelBuilder, int width, int height) { IApplication origApp = ApplicationImpl.Instance; + var origLogger = Logging.Logger; + _logsSb = new StringBuilder (); _netInput = new (_cts.Token); _winInput = new (_cts.Token); @@ -40,11 +61,18 @@ public class GuiTestContext : IDisposable where T : Toplevel, new () { ApplicationImpl.ChangeInstance (v2); + var logger = LoggerFactory.Create (builder => + builder.AddProvider (new TextWriterLoggerProvider (new StringWriter (_logsSb)))) + .CreateLogger ("Test Logging"); + Logging.Logger = logger; + v2.Init (null, "v2win"); booting.Release (); - Application.Run (); // This will block, but it's on a background thread now + var t = topLevelBuilder (); + + Application.Run(t); // This will block, but it's on a background thread now Application.Shutdown (); } @@ -57,6 +85,7 @@ public class GuiTestContext : IDisposable where T : Toplevel, new () finally { ApplicationImpl.ChangeInstance (origApp); + Logging.Logger = origLogger; } }, _cts.Token); @@ -73,7 +102,7 @@ public class GuiTestContext : IDisposable where T : Toplevel, new () /// /// Stops the application and waits for the background thread to exit. /// - public GuiTestContext Stop () + public GuiTestContext Stop () { if (_runTask.IsCompleted) { @@ -123,7 +152,7 @@ public class GuiTestContext : IDisposable where T : Toplevel, new () /// /// /// - public GuiTestContext Add (View v) + public GuiTestContext Add (View v) { WaitIteration ( () => @@ -137,14 +166,14 @@ public class GuiTestContext : IDisposable where T : Toplevel, new () return this; } - public GuiTestContext ResizeConsole (int width, int height) + public GuiTestContext ResizeConsole (int width, int height) { _output.Size = new (width, height); return WaitIteration (); } - public GuiTestContext ScreenShot (string title, TextWriter writer) + public GuiTestContext ScreenShot (string title, TextWriter writer) { writer.WriteLine (title + ":"); var text = Application.ToString (); @@ -154,7 +183,13 @@ public class GuiTestContext : IDisposable where T : Toplevel, new () return WaitIteration (); } - public GuiTestContext WaitIteration (Action? a = null) + public GuiTestContext WriteOutLogs (TextWriter writer) + { + writer.WriteLine (_logsSb.ToString()); + return WaitIteration (); + } + + public GuiTestContext WaitIteration (Action? a = null) { a ??= () => { }; var ctsLocal = new CancellationTokenSource (); @@ -178,17 +213,17 @@ public class GuiTestContext : IDisposable where T : Toplevel, new () return this; } - public GuiTestContext Then (Action doAction) + public GuiTestContext Then (Action doAction) { doAction (); return this; } - public GuiTestContext RightClick (int screenX, int screenY) { return Click (WindowsConsole.ButtonState.Button3Pressed, screenX, screenY); } + public GuiTestContext RightClick (int screenX, int screenY) { return Click (WindowsConsole.ButtonState.Button3Pressed, screenX, screenY); } - public GuiTestContext LeftClick (int screenX, int screenY) { return Click (WindowsConsole.ButtonState.Button1Pressed, screenX, screenY); } + public GuiTestContext LeftClick (int screenX, int screenY) { return Click (WindowsConsole.ButtonState.Button1Pressed, screenX, screenY); } - private GuiTestContext Click (WindowsConsole.ButtonState btn, int screenX, int screenY) + private GuiTestContext Click (WindowsConsole.ButtonState btn, int screenX, int screenY) { _winInput.InputBuffer.Enqueue ( new() @@ -217,7 +252,7 @@ public class GuiTestContext : IDisposable where T : Toplevel, new () return this; } - public GuiTestContext Down () + public GuiTestContext Down () { _winInput.InputBuffer.Enqueue ( new() @@ -254,7 +289,7 @@ public class GuiTestContext : IDisposable where T : Toplevel, new () return this; } - public GuiTestContext Enter () + public GuiTestContext Enter () { _winInput.InputBuffer.Enqueue ( new() @@ -291,7 +326,7 @@ public class GuiTestContext : IDisposable where T : Toplevel, new () return this; } - public GuiTestContext WithContextMenu (ContextMenu ctx, MenuBarItem menuItems) + public GuiTestContext WithContextMenu (ContextMenu ctx, MenuBarItem menuItems) { LastView.MouseEvent += (s, e) => { diff --git a/TerminalGuiFluentTesting/With.cs b/TerminalGuiFluentTesting/With.cs index 73165fbf8..dd5b0a233 100644 --- a/TerminalGuiFluentTesting/With.cs +++ b/TerminalGuiFluentTesting/With.cs @@ -13,7 +13,7 @@ public static class With /// /// /// - public static GuiTestContext A (int width, int height) where T : Toplevel, new () { return new (width, height); } + public static GuiTestContext A (int width, int height) where T : Toplevel, new () { return new (()=>new T(), width, height); } /// /// The global timeout to allow for any given application to run for before shutting down. diff --git a/Tests/IntegrationTests/FluentTests/BasicFluentAssertionTests.cs b/Tests/IntegrationTests/FluentTests/BasicFluentAssertionTests.cs index f4e825e09..a167f856d 100644 --- a/Tests/IntegrationTests/FluentTests/BasicFluentAssertionTests.cs +++ b/Tests/IntegrationTests/FluentTests/BasicFluentAssertionTests.cs @@ -73,7 +73,8 @@ public class BasicFluentAssertionTests .RightClick(1,1) .ScreenShot ("After open menu",_out) .LeftClick (3, 3) - .Stop (); + .Stop () + .WriteOutLogs (_out); Assert.True (clicked); } }