|
@@ -0,0 +1,205 @@
|
|
|
|
|
+# FakeDriver Testing Guide
|
|
|
|
|
+
|
|
|
|
|
+## Overview
|
|
|
|
|
+
|
|
|
|
|
+Terminal.Gui provides testing infrastructure through two complementary driver implementations:
|
|
|
|
|
+
|
|
|
|
|
+1. **FakeDriver** (this directory) - Legacy ConsoleDriver-based fake driver for backward compatibility
|
|
|
|
|
+2. **FakeConsoleDriver** (in TerminalGuiFluentTesting) - Modern component-based fake driver for fluent testing
|
|
|
|
|
+
|
|
|
|
|
+## FakeDriver Architecture
|
|
|
|
|
+
|
|
|
|
|
+`FakeDriver` extends the abstract `ConsoleDriver` base class and is designed for:
|
|
|
|
|
+- Backward compatibility with existing tests
|
|
|
|
|
+- Use with `AutoInitShutdownAttribute` in traditional unit tests
|
|
|
|
|
+- Direct driver manipulation and state inspection
|
|
|
|
|
+
|
|
|
|
|
+### Key Components
|
|
|
|
|
+
|
|
|
|
|
+- **FakeDriver.cs** - Main driver implementation
|
|
|
|
|
+- **FakeConsole.cs** - Static mock console for input/output simulation
|
|
|
|
|
+- **FakeComponentFactory.cs** - Component factory for modern initialization path
|
|
|
|
|
+- **FakeConsoleInput.cs** - Input simulation
|
|
|
|
|
+- **FakeConsoleOutput.cs** - Output capture and validation
|
|
|
|
|
+- **FakeWindowSizeMonitor.cs** - Window resize simulation
|
|
|
|
|
+
|
|
|
|
|
+## Usage Patterns
|
|
|
|
|
+
|
|
|
|
|
+### Basic Test Setup
|
|
|
|
|
+
|
|
|
|
|
+```csharp
|
|
|
|
|
+[Fact]
|
|
|
|
|
+[AutoInitShutdown] // Automatically initializes and shuts down Application
|
|
|
|
|
+public void My_Test()
|
|
|
|
|
+{
|
|
|
|
|
+ // Application is already initialized with FakeDriver
|
|
|
|
|
+ Assert.NotNull(Application.Driver);
|
|
|
|
|
+ Assert.True(Application.Initialized);
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Simulating Screen Resizes
|
|
|
|
|
+
|
|
|
|
|
+```csharp
|
|
|
|
|
+[Fact]
|
|
|
|
|
+[AutoInitShutdown]
|
|
|
|
|
+public void Test_Resize_Behavior()
|
|
|
|
|
+{
|
|
|
|
|
+ // Start with default size (80x25)
|
|
|
|
|
+ Assert.Equal(80, Application.Driver.Cols);
|
|
|
|
|
+ Assert.Equal(25, Application.Driver.Rows);
|
|
|
|
|
+
|
|
|
|
|
+ // Simulate a terminal resize
|
|
|
|
|
+ AutoInitShutdownAttribute.FakeResize(new Size(120, 40));
|
|
|
|
|
+
|
|
|
|
|
+ // Verify the resize took effect
|
|
|
|
|
+ Assert.Equal(120, Application.Driver.Cols);
|
|
|
|
|
+ Assert.Equal(40, Application.Driver.Rows);
|
|
|
|
|
+ Assert.Equal(new Rectangle(0, 0, 120, 40), Application.Screen);
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Subscribing to Resize Events
|
|
|
|
|
+
|
|
|
|
|
+```csharp
|
|
|
|
|
+[Fact]
|
|
|
|
|
+[AutoInitShutdown]
|
|
|
|
|
+public void Test_Resize_Events()
|
|
|
|
|
+{
|
|
|
|
|
+ bool eventFired = false;
|
|
|
|
|
+ Size? newSize = null;
|
|
|
|
|
+
|
|
|
|
|
+ Application.Driver.SizeChanged += (sender, args) =>
|
|
|
|
|
+ {
|
|
|
|
|
+ eventFired = true;
|
|
|
|
|
+ newSize = args.Size;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ AutoInitShutdownAttribute.FakeResize(new Size(100, 30));
|
|
|
|
|
+
|
|
|
|
|
+ Assert.True(eventFired);
|
|
|
|
|
+ Assert.Equal(100, newSize.Value.Width);
|
|
|
|
|
+ Assert.Equal(30, newSize.Value.Height);
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Simulating Keyboard Input
|
|
|
|
|
+
|
|
|
|
|
+```csharp
|
|
|
|
|
+[Fact]
|
|
|
|
|
+[AutoInitShutdown]
|
|
|
|
|
+public void Test_Keyboard_Input()
|
|
|
|
|
+{
|
|
|
|
|
+ // Queue keyboard input before it's processed
|
|
|
|
|
+ FakeConsole.PushMockKeyPress(new ConsoleKeyInfo('a', ConsoleKey.A, false, false, false));
|
|
|
|
|
+ FakeConsole.PushMockKeyPress(new ConsoleKeyInfo('\r', ConsoleKey.Enter, false, false, false));
|
|
|
|
|
+
|
|
|
|
|
+ // Your test logic that processes the input
|
|
|
|
|
+ // ...
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Verifying Screen Output
|
|
|
|
|
+
|
|
|
|
|
+```csharp
|
|
|
|
|
+[Fact]
|
|
|
|
|
+[AutoInitShutdown]
|
|
|
|
|
+public void Test_Screen_Output()
|
|
|
|
|
+{
|
|
|
|
|
+ Application.Top = new Toplevel();
|
|
|
|
|
+ var label = new Label { Text = "Hello", X = 0, Y = 0 };
|
|
|
|
|
+ Application.Top.Add(label);
|
|
|
|
|
+
|
|
|
|
|
+ Application.Begin(Application.Top);
|
|
|
|
|
+ AutoInitShutdownAttribute.RunIteration();
|
|
|
|
|
+
|
|
|
|
|
+ // Access driver contents to verify output
|
|
|
|
|
+ var contents = Application.Driver.Contents;
|
|
|
|
|
+ Assert.NotNull(contents);
|
|
|
|
|
+
|
|
|
|
|
+ // Verify specific characters were drawn
|
|
|
|
|
+ // contents[row, col] gives you access to individual cells
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Relationship Between Driver Properties
|
|
|
|
|
+
|
|
|
|
|
+Understanding the relationship between key driver properties:
|
|
|
|
|
+
|
|
|
|
|
+- **Screen** - `Rectangle` representing the full console area. Always starts at (0,0) with size (Cols, Rows).
|
|
|
|
|
+- **Cols** - Number of columns (width) in the console.
|
|
|
|
|
+- **Rows** - Number of rows (height) in the console.
|
|
|
|
|
+- **Contents** - 2D array `[rows, cols]` containing the actual screen buffer cells.
|
|
|
|
|
+
|
|
|
|
|
+When you resize:
|
|
|
|
|
+1. `SetBufferSize(width, height)` or `FakeResize(Size)` is called
|
|
|
|
|
+2. `Cols` and `Rows` are updated
|
|
|
|
|
+3. `Contents` buffer is reallocated to match new dimensions
|
|
|
|
|
+4. `Screen` property returns updated rectangle
|
|
|
|
|
+5. `SizeChanged` event fires with new size
|
|
|
|
|
+6. Application propagates resize to top-level views
|
|
|
|
|
+
|
|
|
|
|
+## Thread Safety
|
|
|
|
|
+
|
|
|
|
|
+⚠️ **Important**: FakeDriver is **not thread-safe**. Tests that use FakeDriver should:
|
|
|
|
|
+- Not run in parallel with other tests that access the driver
|
|
|
|
|
+- Not share driver state between test methods
|
|
|
|
|
+- Use `AutoInitShutdownAttribute` to ensure clean initialization/shutdown per test
|
|
|
|
|
+
|
|
|
|
|
+For parallel-safe tests, use the UnitTestsParallelizable project with its own test infrastructure.
|
|
|
|
|
+
|
|
|
|
|
+## Differences from Production Drivers
|
|
|
|
|
+
|
|
|
|
|
+FakeDriver differs from production drivers (WindowsDriver, UnixDriver, DotNetDriver) in several ways:
|
|
|
|
|
+
|
|
|
|
|
+| Aspect | FakeDriver | Production Drivers |
|
|
|
|
|
+|--------|------------|-------------------|
|
|
|
|
|
+| Screen Size | Programmatically set via `SetBufferSize` | Determined by actual terminal size |
|
|
|
|
|
+| Input | Queued via `FakeConsole.PushMockKeyPress` | Reads from actual stdin |
|
|
|
|
|
+| Output | Captured in memory buffer | Written to actual terminal |
|
|
|
|
|
+| Resize | Triggered by test code | Triggered by OS (SIGWINCH, WINDOW_BUFFER_SIZE_EVENT) |
|
|
|
|
|
+| Buffer vs Window | Always equal (no scrollback) | Can differ (scrollback support) |
|
|
|
|
|
+
|
|
|
|
|
+## Advanced: Direct Driver Access
|
|
|
|
|
+
|
|
|
|
|
+For tests that need more control, you can access the driver directly:
|
|
|
|
|
+
|
|
|
|
|
+```csharp
|
|
|
|
|
+[Fact]
|
|
|
|
|
+public void Test_With_Direct_Driver_Access()
|
|
|
|
|
+{
|
|
|
|
|
+ // Create and initialize driver manually
|
|
|
|
|
+ Application.ResetState(true);
|
|
|
|
|
+ var driver = new FakeDriver();
|
|
|
|
|
+ Application.Driver = driver;
|
|
|
|
|
+ Application.SubscribeDriverEvents();
|
|
|
|
|
+
|
|
|
|
|
+ // Use driver directly
|
|
|
|
|
+ driver.SetBufferSize(100, 50);
|
|
|
|
|
+
|
|
|
|
|
+ Assert.Equal(100, driver.Cols);
|
|
|
|
|
+ Assert.Equal(50, driver.Rows);
|
|
|
|
|
+
|
|
|
|
|
+ // Cleanup
|
|
|
|
|
+ Application.ResetState(true);
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Modern Component-Based Architecture
|
|
|
|
|
+
|
|
|
|
|
+For new test infrastructure, consider using the modern component factory approach via `FakeComponentFactory`:
|
|
|
|
|
+
|
|
|
|
|
+```csharp
|
|
|
|
|
+var factory = new FakeComponentFactory();
|
|
|
|
|
+// Modern driver initialization through component factory pattern
|
|
|
|
|
+// This is used internally by the fluent testing infrastructure
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+The fluent testing project (`TerminalGuiFluentTesting`) provides a higher-level API built on this architecture.
|
|
|
|
|
+
|
|
|
|
|
+## See Also
|
|
|
|
|
+
|
|
|
|
|
+- **AutoInitShutdownAttribute** - Attribute for automatic test setup/teardown
|
|
|
|
|
+- **TerminalGuiFluentTesting** - Modern fluent testing infrastructure
|
|
|
|
|
+- **FakeConsole** - Static mock console used by FakeDriver
|
|
|
|
|
+- **ConsoleDriver** - Base class documentation for all drivers
|