Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 151 additions & 0 deletions Tests/CATEGORY_A_MIGRATION_SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# Category A Migration Summary

## Overview

This document summarizes the Category A test migration effort to move parallelizable unit tests from `UnitTests` to `UnitTests.Parallelizable`.

## Tests Migrated: 35

### Drawing/LineCanvasTests.cs: 31 tests
**Migrated pure unit tests that don't require Application.Driver:**
- ToString_Empty (1 test)
- Clear_Removes_All_Lines (1 test)
- Lines_Property_Returns_ReadOnly_Collection (1 test)
- AddLine_Adds_Line_To_Collection (1 test)
- Constructor_With_Lines_Creates_Canvas_With_Lines (1 test)
- Viewport_H_And_V_Lines_Both_Positive (7 test cases)
- Viewport_H_Line (7 test cases)
- Viewport_Specific (1 test)
- Bounds_Empty_Canvas_Returns_Empty_Rectangle (1 test)
- Bounds_Single_Point_Zero_Length (1 test)
- Bounds_Horizontal_Line (1 test)
- Bounds_Vertical_Line (1 test)
- Bounds_Multiple_Lines_Returns_Union (1 test)
- Bounds_Negative_Length_Line (1 test)
- Bounds_Complex_Box (1 test)
- ClearExclusions_Clears_Exclusion_Region (1 test)
- Exclude_Removes_Points_From_Map (1 test)
- Fill_Property_Can_Be_Set (1 test)
- Fill_Property_Defaults_To_Null (1 test)

**Tests that remain in UnitTests as integration tests:**
- All tests using GetCanvas() and View.Draw() (16 tests)
- Tests that verify rendered output (ToString with specific glyphs) - these require Application.Driver for glyph resolution

### Drawing/RulerTests.cs: 4 tests
**Migrated pure unit tests:**
- Constructor_Defaults
- Attribute_Set
- Length_Set
- Orientation_Set

**Tests that remain in UnitTests as integration tests:**
- Draw_Default (requires Application.Init with [AutoInitShutdown])
- Draw_Horizontal (uses [SetupFakeDriver] - could potentially be migrated)
- Draw_Vertical (uses [SetupFakeDriver] - could potentially be migrated)

## Key Findings

### 1. LineCanvas and Rendering Dependencies
**Issue:** LineCanvas.ToString() internally calls GetMap() which calls GetRuneForIntersects(Application.Driver). The glyph resolution depends on Application.Driver for:
- Configuration-dependent glyphs (Glyphs class)
- Line intersection character selection
- Style-specific characters (Single, Double, Heavy, etc.)

**Solution:** Tests using [SetupFakeDriver] CAN be parallelized as long as they don't use Application statics. This includes rendering tests that verify visual output with DriverAssert.

### 2. Test Categories
Tests fall into three categories:

**a) Pure Unit Tests (CAN be parallelized):**
- Tests of properties (Bounds, Lines, Length, Orientation, Attribute, Fill)
- Tests of basic operations (AddLine, Clear, Exclude, ClearExclusions)
- Tests that don't require Application static context

**b) Rendering Tests with [SetupFakeDriver] (CAN be parallelized):**
- Tests using [SetupFakeDriver] without Application statics
- Tests using View.Draw() and LayoutAndDraw() without Application statics
- Tests that verify visual output with DriverAssert (when using [SetupFakeDriver])
- Tests using GetCanvas() helper as long as Application statics are not used

**c) Integration Tests (CANNOT be parallelized):**
- Tests using [AutoInitShutdown]
- Tests using Application.Begin, Application.RaiseKeyDownEvent, or other Application static methods
- Tests that validate component behavior within full Application context
- Tests that require ConfigurationManager or Application.Navigation

### 3. View/Adornment and View/Draw Tests
**Finding:** After analyzing these tests, they all use [SetupFakeDriver] and test View.Draw() with visual verification. These are integration tests that validate how adornments render within the View system. They correctly belong in UnitTests.

**Recommendation:** Do NOT migrate these tests. They are integration tests by design and require the full Application/Driver context.

## Test Results

### UnitTests.Parallelizable
- **Before:** 9,360 tests passing
- **After:** 9,395 tests passing (+35)
- **Result:** βœ… All tests pass

### UnitTests
- **Status:** 3,488 tests passing (unchanged)
- **Result:** βœ… No regressions

## Recommendations for Future Work

### 1. Continue Focused Migration

**Tests CAN be parallelized if they:**
- βœ… Test properties, constructors, and basic operations
- βœ… Use [SetupFakeDriver] without Application statics
- βœ… Call View.Draw(), LayoutAndDraw() without Application statics
- βœ… Verify visual output with DriverAssert (when using [SetupFakeDriver])
- βœ… Create View hierarchies without Application.Top
- βœ… Test events and behavior without global state

**Tests CANNOT be parallelized if they:**
- ❌ Use [AutoInitShutdown] (requires Application.Init/Shutdown global state)
- ❌ Set Application.Driver (global singleton)
- ❌ Call Application.Init(), Application.Run/Run<T>(), or Application.Begin()
- ❌ Modify ConfigurationManager global state (Enable/Load/Apply/Disable)
- ❌ Modify static properties (Key.Separator, CultureInfo.CurrentCulture, etc.)
- ❌ Use Application.Top, Application.Driver, Application.MainLoop, or Application.Navigation
- ❌ Are true integration tests testing multiple components together

**Important Notes:**
- Many tests blindly use the above when they don't need to and CAN be rewritten
- Many tests APPEAR to be integration tests but are just poorly written and can be split
- When in doubt, analyze if the test truly needs global state or can be refactored

### 2. Documentation
Update test documentation to clarify:
- **UnitTests** = Integration tests that validate components within Application context
- **UnitTests.Parallelizable** = Pure unit tests with no global state dependencies
- Provide examples of each type

### 3. New Test Development
- Default to UnitTests.Parallelizable for new tests unless they require Application/Driver
- When testing rendering, create both:
- Pure unit test (properties, behavior) in Parallelizable
- Rendering test with [SetupFakeDriver] can also go in Parallelizable (as long as Application statics are not used)
- Integration test (Application context) in UnitTests

### 4. Remaining Category A Tests
**Status:** Can be re-evaluated for migration

**Rationale:**
- View/Adornment/* tests (19 tests): Use [SetupFakeDriver] and test View.Draw() - CAN be migrated if they don't use Application statics
- View/Draw/* tests (32 tests): Use [SetupFakeDriver] and test rendering - CAN be migrated if they don't use Application statics
- Need to analyze each test individually to check for Application static dependencies

## Conclusion

This migration successfully identified and moved 52 tests (35 Category A + 17 Views) to UnitTests.Parallelizable.

**Key Discovery:** Tests with [SetupFakeDriver] CAN run in parallel as long as they avoid Application statics. This significantly expands the scope of tests that can be parallelized beyond just property/constructor tests to include rendering tests.

The approach taken was to:
1. Identify tests that don't use Application.Begin, Application.RaiseKeyDownEvent, Application.Navigation, or other Application static members
2. Keep [SetupFakeDriver] tests that only use View.Draw() and DriverAssert
3. Move [AutoInitShutdown] tests only if they can be rewritten to not use Application.Begin

**Migration Rate:** 52 tests migrated so far. Many more tests with [SetupFakeDriver] can potentially be migrated once they're analyzed for Application static usage. Estimated ~3,400 tests remaining to analyze.
163 changes: 0 additions & 163 deletions Tests/UnitTests/Drawing/LineCanvasTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -299,169 +299,6 @@ string expected
v.Dispose ();
}

[InlineData (
0,
0,
0,
0,
0,
1,
1
)]
[InlineData (
0,
0,
1,
0,
0,
1,
1
)]
[InlineData (
0,
0,
2,
0,
0,
2,
2
)]
[InlineData (
0,
0,
3,
0,
0,
3,
3
)]
[InlineData (
0,
0,
-1,
0,
0,
1,
1
)]
[InlineData (
0,
0,
-2,
-1,
-1,
2,
2
)]
[InlineData (
0,
0,
-3,
-2,
-2,
3,
3
)]
[Theory]
[SetupFakeDriver]
public void Viewport_H_And_V_Lines_Both_Positive (
int x,
int y,
int length,
int expectedX,
int expectedY,
int expectedWidth,
int expectedHeight
)
{
var canvas = new LineCanvas ();
canvas.AddLine (new (x, y), length, Orientation.Horizontal, LineStyle.Single);
canvas.AddLine (new (x, y), length, Orientation.Vertical, LineStyle.Single);

Assert.Equal (new (expectedX, expectedY, expectedWidth, expectedHeight), canvas.Bounds);
}

[InlineData (
0,
0,
0,
0,
0,
1,
1
)]
[InlineData (
0,
0,
1,
0,
0,
1,
1
)]
[InlineData (
0,
0,
2,
0,
0,
2,
1
)]
[InlineData (
0,
0,
3,
0,
0,
3,
1
)]
[InlineData (
0,
0,
-1,
0,
0,
1,
1
)]
[InlineData (
0,
0,
-2,
-1,
0,
2,
1
)]
[InlineData (
0,
0,
-3,
-2,
0,
3,
1
)]
[Theory]
[SetupFakeDriver]
public void Viewport_H_Line (
int x,
int y,
int length,
int expectedX,
int expectedY,
int expectedWidth,
int expectedHeight
)
{
var canvas = new LineCanvas ();
canvas.AddLine (new (x, y), length, Orientation.Horizontal, LineStyle.Single);

Assert.Equal (new (expectedX, expectedY, expectedWidth, expectedHeight), canvas.Bounds);
}

[Fact]
[SetupFakeDriver]
public void Viewport_Specific ()
Expand Down
36 changes: 0 additions & 36 deletions Tests/UnitTests/Drawing/RulerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,6 @@ public class RulerTests
private readonly ITestOutputHelper _output;
public RulerTests (ITestOutputHelper output) { _output = output; }

[Fact]
public void Attribute_set ()
{
var newAttribute = new Attribute (Color.Red, Color.Green);

var r = new Ruler ();
r.Attribute = newAttribute;
Assert.Equal (newAttribute, r.Attribute);
}

[Fact]
public void Constructor_Defaults ()
{
var r = new Ruler ();
Assert.Equal (0, r.Length);
Assert.Equal (Orientation.Horizontal, r.Orientation);
}

[Fact]
[AutoInitShutdown]
public void Draw_Default ()
Expand Down Expand Up @@ -157,22 +139,4 @@ public void Draw_Vertical ()
_output
);
}

[Fact]
public void Length_set ()
{
var r = new Ruler ();
Assert.Equal (0, r.Length);
r.Length = 42;
Assert.Equal (42, r.Length);
}

[Fact]
public void Orientation_set ()
{
var r = new Ruler ();
Assert.Equal (Orientation.Horizontal, r.Orientation);
r.Orientation = Orientation.Vertical;
Assert.Equal (Orientation.Vertical, r.Orientation);
}
}
Loading
Loading