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
363 changes: 363 additions & 0 deletions Tests/PERFORMANCE_ANALYSIS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,363 @@
# UnitTests Performance Analysis Report

## Executive Summary

This report provides a comprehensive performance analysis of the `UnitTests` project, identifying the highest-impact opportunities for test migration to improve CI/CD performance.

**Key Findings:**
- **Total tests analyzed:** 3,260 tests across 121 test files
- **Top bottleneck:** Views folder (962 tests, 59.6s, 50% of total runtime)
- **Highest average time per test:** Input/ folder (0.515s/test)
- **Tests with AutoInitShutdown:** 449 tests (35.4%) - these are the slowest
- **Tests with SetupFakeDriver:** 198 tests (15.6%)
- **Tests with no attributes:** 622 tests (49.0%) - easiest to migrate

## Performance Analysis by Folder

### Folder-Level Timing Results (Ranked by Total Duration)

| Folder | Tests | Duration | Avg/Test | Impact Score |
|--------|-------|----------|----------|--------------|
| **Views/** | 962 | 59.64s | 0.062s | ⭐⭐⭐⭐⭐ CRITICAL |
| **View/** | 739 | 27.14s | 0.036s | ⭐⭐⭐⭐ HIGH |
| **Application/** | 187 | 14.82s | 0.079s | ⭐⭐⭐ MEDIUM |
| **Dialogs/** | 116 | 13.42s | 0.115s | ⭐⭐⭐ MEDIUM |
| **Text/** | 467 | 10.18s | 0.021s | ⭐⭐ LOW |
| **ConsoleDrivers/** | 475 | 5.74s | 0.012s | ⭐ VERY LOW |
| **FileServices/** | 35 | 5.56s | 0.158s | ⭐⭐ LOW |
| **Drawing/** | 173 | 5.35s | 0.030s | ⭐ VERY LOW |
| **Configuration/** | 98 | 5.05s | 0.051s | ⭐ VERY LOW |
| **Input/** | 8 | 4.12s | 0.515s | ⭐⭐ LOW |

**Total:** 3,260 tests, ~150s total runtime

### Folder-Level Static Analysis

| Folder | Files | Tests | AutoInit | SetupDrv | App.Begin | App.Top |
|--------|-------|-------|----------|----------|-----------|---------|
| Views | 33 | 612 | 232 (37.9%) | 104 (17.0%) | 139 | 219 |
| Application | 12 | 120 | 27 (22.5%) | 6 (5.0%) | 20 | 145 |
| Configuration | 9 | 82 | 0 (0.0%) | 0 (0.0%) | 0 | 0 |
| ConsoleDrivers | 17 | 75 | 15 (20.0%) | 3 (4.0%) | 8 | 34 |
| Drawing | 4 | 58 | 21 (36.2%) | 32 (55.2%) | 1 | 0 |
| Dialogs | 3 | 50 | 40 (80.0%) | 0 (0.0%) | 6 | 7 |
| View/Draw | 7 | 37 | 15 (40.5%) | 17 (45.9%) | 15 | 0 |

## High-Impact Migration Targets

### 🎯 Priority 1: CRITICAL Impact (50-60s potential savings)

#### Views/ Folder - 59.6s (50% of total runtime)
**Profile:**
- 962 tests total
- 232 with AutoInitShutdown (37.9%)
- 104 with SetupFakeDriver (17.0%)
- **~380 tests with no attributes** (potential quick wins)

**Top Individual Files:**
1. **TextViewTests.cs** - 105 tests, 9.26s, 0.088s/test
- 41 AutoInitShutdown (39%)
- 64 tests are potentially migratable

2. **TableViewTests.cs** - 80 tests, 5.38s, 0.055s/test
- 45 SetupFakeDriver (56%)
- 8 AutoInitShutdown
- Many rendering tests that may need refactoring

3. **TileViewTests.cs** - 45 tests, 9.25s, 0.197s/test ⚠️ SLOWEST AVG
- 42 AutoInitShutdown (93%)
- High overhead per test - prime candidate for optimization

4. **TextFieldTests.cs** - 43 tests
- 8 AutoInitShutdown (19%)
- 3 SetupFakeDriver
- ~32 tests likely migratable

5. **GraphViewTests.cs** - 42 tests
- 24 AutoInitShutdown (57%)
- ~18 tests potentially migratable

**Recommendation:** Focus on Views/ folder first
- Extract simple property/event tests from TextViewTests
- Refactor TileViewTests to reduce AutoInitShutdown usage
- Split TableViewTests into unit vs integration tests

### 🎯 Priority 2: HIGH Impact (20-30s potential savings)

#### View/ Folder - 27.14s
**Profile:**
- 739 tests total
- Wide distribution across subdirectories
- Mix of layout, drawing, and behavioral tests

**Key subdirectories:**
- View/Layout - 35 tests (6 AutoInit, 1 SetupDriver)
- View/Draw - 37 tests (15 AutoInit, 17 SetupDriver)
- View/Adornment - 25 tests (9 AutoInit, 10 SetupDriver)

**Top Files:**
1. **GetViewsUnderLocationTests.cs** - 21 tests, NO attributes ✅
- Easy migration candidate

2. **DrawTests.cs** - 17 tests
- 10 AutoInitShutdown
- 6 SetupFakeDriver
- Mix that needs analysis

**Recommendation:**
- Migrate GetViewsUnderLocationTests.cs immediately
- Analyze layout tests for unnecessary Application dependencies

### 🎯 Priority 3: MEDIUM Impact (10-15s potential savings)

#### Dialogs/ Folder - 13.42s
**Profile:**
- 116 tests, 0.115s/test average (SLOW)
- 40 AutoInitShutdown (80% usage rate!)
- Heavy Application.Begin usage

**Files:**
1. **DialogTests.cs** - 23 tests, all with AutoInitShutdown
2. **MessageBoxTests.cs** - 11 tests, all with AutoInitShutdown

**Recommendation:**
- These are true integration tests that likely need Application
- Some could be refactored to test dialog construction separately from display
- Lower priority for migration

#### Application/ Folder - 14.82s
**Profile:**
- 187 tests
- 27 AutoInitShutdown (22.5%)
- Heavy Application.Top usage (145 occurrences)

**Easy wins:**
1. **MainLoopTests.cs** - 23 tests, NO attributes ✅ (already migrated)
2. **ApplicationImplTests.cs** - 13 tests, NO attributes ✅
3. **ApplicationPopoverTests.cs** - 10 tests, NO attributes ✅

**Recommendation:**
- Migrate the remaining files with no attributes
- Many Application tests genuinely need Application static state

## Performance by Test Pattern

### AutoInitShutdown Tests (449 tests, ~35% of total)

**Characteristics:**
- Average 0.115s per test (vs 0.051s for no-attribute tests)
- **2.25x slower than tests without attributes**
- Creates Application singleton, initializes driver, sets up MainLoop
- Calls Application.Shutdown after each test

**Top Files Using AutoInitShutdown:**
1. TileViewTests.cs - 42 tests (93% usage)
2. TextViewTests.cs - 41 tests (39% usage)
3. MenuBarv1Tests.cs - 40 tests (95% usage)
4. GraphViewTests.cs - 24 tests (57% usage)
5. DialogTests.cs - 23 tests (100% usage)
6. MenuBarTests.cs - 20 tests (111% - multiple per test method)

**Estimated Impact:** If 50% of AutoInitShutdown tests can be refactored:
- ~225 tests × 0.064s overhead = **~14.4s savings**

### SetupFakeDriver Tests (198 tests, ~16% of total)

**Characteristics:**
- Average 0.055s per test
- Sets up Application.Driver globally
- Many test visual output with DriverAssert
- Less overhead than AutoInitShutdown but still blocks parallelization

**Top Files Using SetupFakeDriver:**
1. TableViewTests.cs - 45 tests (56% usage)
2. LineCanvasTests.cs - 30 tests (86% usage)
3. TabViewTests.cs - 18 tests (53% usage)
4. TextFormatterTests.cs - 18 tests (78% usage)
5. ColorPickerTests.cs - 16 tests (100% usage)

**Estimated Impact:** If 30% can be refactored to remove driver dependency:
- ~60 tests × 0.025s overhead = **~1.5s savings**

### Tests with No Attributes (622 tests, ~49% of total)

**Characteristics:**
- Average 0.051s per test (fastest)
- Should be immediately migratable
- Many already identified in previous migration

**Top Remaining Files:**
1. ConfigurationMangerTests.cs - 27 tests ✅ (already migrated)
2. MainLoopTests.cs - 23 tests ✅ (already migrated)
3. GetViewsUnderLocationTests.cs - 21 tests ⭐ **HIGH PRIORITY**
4. ConfigPropertyTests.cs - 18 tests (partial migration done)
5. SchemeManagerTests.cs - 14 tests (partial migration done)

## Recommendations: Phased Approach

### Phase 1: Quick Wins (Estimated 15-20s savings, 1-2 days)

**Target:** 150-200 tests with no attributes

1. **Immediate migrations** (no refactoring needed):
- GetViewsUnderLocationTests.cs (21 tests)
- ApplicationImplTests.cs (13 tests)
- ApplicationPopoverTests.cs (10 tests)
- HexViewTests.cs (12 tests)
- TimeFieldTests.cs (6 tests)
- Various smaller files with no attributes

2. **Complete partial migrations**:
- ConfigPropertyTests.cs (add 14 more tests)
- SchemeManagerTests.cs (add 4 more tests)
- SettingsScopeTests.cs (add 9 more tests)

**Expected Impact:** ~20s runtime reduction in UnitTests

### Phase 2: TextViewTests Refactoring (Estimated 4-5s savings, 2-3 days)

**Target:** Split 64 tests from TextViewTests.cs

1. Extract simple tests (no AutoInitShutdown needed):
- Property tests (Text, Enabled, Visible, etc.)
- Event tests (TextChanged, etc.)
- Constructor tests

2. Extract tests that can use BeginInit/EndInit instead of Application.Begin:
- Basic layout tests
- Focus tests
- Some selection tests

3. Leave integration tests in UnitTests:
- Tests that verify rendering output
- Tests that need actual driver interaction
- Multi-component interaction tests

**Expected Impact:** ~4-5s runtime reduction

### Phase 3: TileViewTests Optimization (Estimated 4-5s savings, 2-3 days)

**Target:** Reduce TileViewTests from 9.25s to ~4s

TileViewTests has the highest average time per test (0.197s) - nearly 4x the normal rate!

**Analysis needed:**
1. Why are these tests so slow?
2. Are they testing multiple things per test?
3. Can Application.Begin calls be replaced with BeginInit/EndInit?
4. Are there setup/teardown inefficiencies?

**Approach:**
1. Profile individual test methods
2. Look for common patterns causing slowness
3. Refactor to reduce overhead
4. Consider splitting into multiple focused test classes

**Expected Impact:** ~5s runtime reduction

### Phase 4: TableViewTests Refactoring (Estimated 2-3s savings, 2-3 days)

**Target:** Extract ~35 tests from TableViewTests.cs

TableViewTests has 45 SetupFakeDriver usages for visual testing. However:
- Some tests may only need basic View hierarchy (BeginInit/EndInit)
- Some tests may be testing properties that don't need rendering
- Some tests may be duplicating coverage

**Approach:**
1. Categorize tests: pure unit vs rendering verification
2. Extract pure unit tests to Parallelizable
3. Keep rendering verification tests in UnitTests
4. Look for duplicate coverage

**Expected Impact:** ~3s runtime reduction

### Phase 5: Additional View Tests (Estimated 10-15s savings, 1-2 weeks)

**Target:** 200-300 tests across multiple View test files

Focus on files with mix of attribute/no-attribute tests:
- TextFieldTests.cs (43 tests, only 11 with attributes)
- GraphViewTests.cs (42 tests, 24 AutoInit - can some be refactored?)
- ListViewTests.cs (27 tests, 6 AutoInit)
- LabelTests.cs (24 tests, 16 AutoInit + 3 SetupDriver)
- TreeViewTests.cs (38 tests, 1 AutoInit + 9 SetupDriver)

**Expected Impact:** ~15s runtime reduction

## Summary of Potential Savings

| Phase | Tests Migrated | Estimated Savings | Effort | Priority |
|-------|----------------|-------------------|--------|----------|
| Phase 1: Quick Wins | 150-200 | 15-20s | 1-2 days | ⭐⭐⭐⭐⭐ |
| Phase 2: TextViewTests | 64 | 4-5s | 2-3 days | ⭐⭐⭐⭐ |
| Phase 3: TileViewTests | 20-30 | 4-5s | 2-3 days | ⭐⭐⭐⭐ |
| Phase 4: TableViewTests | 35 | 2-3s | 2-3 days | ⭐⭐⭐ |
| Phase 5: Additional Views | 200-300 | 10-15s | 1-2 weeks | ⭐⭐⭐ |
| **TOTAL** | **469-623 tests** | **35-48s** | **3-4 weeks** | |

**Target Runtime:**
- Current: ~90s (UnitTests)
- After all phases: **~42-55s (38-47% reduction)**
- Combined with Parallelizable: **~102-115s total (vs 150s current = 23-32% reduction)**

## Key Insights

### Why Some Tests Are Slow

1. **AutoInitShutdown overhead** (0.064s per test):
- Creates Application singleton
- Initializes FakeDriver
- Sets up MainLoop
- Teardown and cleanup

2. **Application.Begin overhead** (varies):
- Initializes view hierarchy
- Runs layout engine
- Sets up focus/navigation
- Creates event loops

3. **Integration test nature**:
- Dialogs/ tests average 0.115s/test
- FileServices/ tests average 0.158s/test
- Input/ tests average 0.515s/test (!)
- These test full workflows, not units

### Migration Difficulty Assessment

**Easy (No refactoring):**
- Tests with no attributes: 622 tests
- Simply copy to Parallelizable and add base class

**Medium (Minor refactoring):**
- Tests using SetupFakeDriver but not Application statics: ~60 tests
- Replace SetupFakeDriver with inline driver creation if needed
- Or remove driver dependency entirely

**Hard (Significant refactoring):**
- Tests using AutoInitShutdown: 449 tests
- Must replace Application.Begin with BeginInit/EndInit
- Or split into unit vs integration tests
- Or redesign test approach

**Very Hard (May not be migratable):**
- True integration tests: ~100-150 tests
- Tests requiring actual rendering verification
- Tests requiring Application singleton behavior
- Keep these in UnitTests

## Conclusion

The analysis reveals clear opportunities for significant performance improvements:

1. **Immediate impact:** 150-200 tests with no attributes can be migrated in 1-2 days for ~20s savings
2. **High value:** TextViewTests and TileViewTests contain ~100 tests that can yield ~10s savings with moderate effort
3. **Long-term:** Systematic refactoring of 469-623 tests could reduce UnitTests runtime by 38-47%

The Views/ folder is the critical bottleneck, representing 50% of runtime. Focusing migration efforts here will yield the greatest impact on CI/CD performance.

---

**Report Generated:** 2025-10-20
**Analysis Method:** Static analysis + runtime profiling
**Total Tests Analyzed:** 3,260 tests across 121 files
Loading
Loading