Skip to content

Commit 3bfb155

Browse files
committed
✨ [feat] Add code coverage reporting with Codecov
✨ [feat] Adds comprehensive code coverage reporting to the project. This enhances quality assurance by tracking the percentage of code executed during tests. 👷 [ci] Updates the `test.yml` workflow to: - Enable Pester's code coverage feature during test runs for both PowerShell 5.1 and pwsh. - Generate coverage reports in `JaCoCo` XML format. - Upload these reports to Codecov using the `codecov/codecov-action` for analysis and badge generation. 🧪 [test] Introduces a new PowerShell script `scripts/Test-Coverage.ps1` to streamline local testing: - Runs Pester tests with coverage analysis. - Displays a detailed coverage summary in the console. - Enforces a minimum coverage threshold to maintain code quality. - Includes an option to generate and open a local HTML coverage report using `ReportGenerator`. 🔧 [build] Adds new npm scripts for convenience: - `npm run test:coverage` to execute the coverage script. - `npm run test:coverage:report` to generate the HTML report. 📝 [docs] Updates `README.md` to: - Add the new Codecov badge. - Include a new "Testing" section detailing how to run tests and generate coverage reports. - Add a project mascot image. 🧹 [chore] Modifies `.gitignore` to exclude generated test results and coverage report files. Signed-off-by: Nick2bad4u <20943337+Nick2bad4u@users.noreply.github.com>
1 parent 061fcda commit 3bfb155

7 files changed

Lines changed: 225 additions & 6 deletions

File tree

.github/workflows/test.yml

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737
Install-Module -Name PSScriptAnalyzer -Force -SkipPublisherCheck
3838
}
3939
40-
- name: Run Pester tests
40+
- name: Run Pester tests with coverage
4141
shell: powershell
4242
run: |
4343
Import-Module Pester
@@ -46,6 +46,10 @@ jobs:
4646
$configuration.Output.Verbosity = 'Detailed'
4747
$configuration.TestResult.Enabled = $true
4848
$configuration.TestResult.OutputPath = 'test-results.xml'
49+
$configuration.CodeCoverage.Enabled = $true
50+
$configuration.CodeCoverage.Path = './ColorScripts-Enhanced/*.psm1'
51+
$configuration.CodeCoverage.OutputPath = 'coverage.xml'
52+
$configuration.CodeCoverage.OutputFormat = 'JaCoCo'
4953
Invoke-Pester -Configuration $configuration
5054
5155
- name: Upload test results
@@ -55,6 +59,13 @@ jobs:
5559
name: test-results-windows-51
5660
path: test-results.xml
5761

62+
- name: Upload coverage to Codecov
63+
uses: codecov/codecov-action@7f8b4b4bde536c465e797be725718b88c5d95e0e # v5.1.2
64+
with:
65+
files: ./coverage.xml
66+
flags: windows-powershell-51
67+
name: windows-powershell-51
68+
5869
- name: Validate help topics
5970
shell: powershell
6071
run: |
@@ -98,7 +109,7 @@ jobs:
98109
Install-Module -Name PSScriptAnalyzer -Force -SkipPublisherCheck
99110
}
100111
101-
- name: Run Pester tests
112+
- name: Run Pester tests with coverage
102113
shell: pwsh
103114
run: |
104115
Import-Module Pester
@@ -107,6 +118,10 @@ jobs:
107118
$configuration.Output.Verbosity = 'Detailed'
108119
$configuration.TestResult.Enabled = $true
109120
$configuration.TestResult.OutputPath = 'test-results.xml'
121+
$configuration.CodeCoverage.Enabled = $true
122+
$configuration.CodeCoverage.Path = './ColorScripts-Enhanced/*.psm1'
123+
$configuration.CodeCoverage.OutputPath = 'coverage.xml'
124+
$configuration.CodeCoverage.OutputFormat = 'JaCoCo'
110125
Invoke-Pester -Configuration $configuration
111126
112127
- name: Upload test results
@@ -116,6 +131,13 @@ jobs:
116131
name: test-results-${{ matrix.os }}-pwsh
117132
path: test-results.xml
118133

134+
- name: Upload coverage to Codecov
135+
uses: codecov/codecov-action@7f8b4b4bde536c465e797be725718b88c5d95e0e # v5.1.2
136+
with:
137+
files: ./coverage.xml
138+
flags: pwsh-${{ matrix.os }}
139+
name: pwsh-${{ matrix.os }}
140+
119141
- name: Run script analyzer
120142
shell: pwsh
121143
run: |

.gitignore

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ obj/
114114
.LSOverride
115115

116116
# Icon must end with two \r
117-
Icon
117+
Icon
118+
118119

119120
# Thumbnails
120121
._*
@@ -341,3 +342,10 @@ ps-color-scripts/*.psd1
341342
ps-color-scripts/cache/
342343
.prettier-cache
343344
node_modules/
345+
346+
# Code coverage reports
347+
coverage.xml
348+
coverage-report/
349+
testResults.xml
350+
test-results.xml
351+
*.coverage

README.md

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<!-- CI/CD & Quality Badges -->
1414

1515
[![Tests](https://github.com/Nick2bad4u/ps-color-scripts-enhanced/actions/workflows/test.yml/badge.svg)](https://github.com/Nick2bad4u/ps-color-scripts-enhanced/actions/workflows/test.yml)
16+
[![codecov](https://codecov.io/gh/Nick2bad4u/ps-color-scripts-enhanced/branch/main/graph/badge.svg)](https://codecov.io/gh/Nick2bad4u/ps-color-scripts-enhanced)
1617
[![Publish](https://github.com/Nick2bad4u/ps-color-scripts-enhanced/actions/workflows/publish.yml/badge.svg)](https://github.com/Nick2bad4u/ps-color-scripts-enhanced/actions/workflows/publish.yml)
1718
[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/Nick2bad4u/PS-Color-Scripts-Enhanced/badge)](https://scorecard.dev/viewer/?uri=github.com/Nick2bad4u/PS-Color-Scripts-Enhanced)
1819
[![Dependency Review](https://github.com/Nick2bad4u/PS-Color-Scripts-Enhanced/actions/workflows/dependency-review.yml/badge.svg)](https://github.com/Nick2bad4u/PS-Color-Scripts-Enhanced/actions/workflows/dependency-review.yml)
@@ -26,11 +27,15 @@
2627

2728
<!-- License & Contributing -->
2829

29-
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
30+
[![License: UnLicense](https://img.shields.io/badge/License-UnLicense-yellow.svg)](LICENSE)
3031
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md)
3132

3233
A high-performance PowerShell module for displaying beautiful ANSI colorscripts in your terminal with intelligent caching for 6-19x faster load times.
3334

35+
<p align="center">
36+
<img src="assets/ColorScripts-Mascot-Dark.jpeg" alt="ColorScripts mascot" width="60%" />
37+
</p>
38+
3439
## Table of Contents
3540

3641
- [Features](#features)
@@ -639,7 +644,7 @@ Contributions welcome! When adding new colorscripts:
639644

640645
## License
641646

642-
MIT License – see [LICENSE](https://github.com/Nick2bad4u/ps-color-scripts-enhanced/blob/main/LICENSE) file for details
647+
UnLicense License – see [LICENSE](https://github.com/Nick2bad4u/ps-color-scripts-enhanced/blob/main/LICENSE) file for details
643648

644649
## Version History
645650

@@ -668,9 +673,33 @@ See [CHANGELOG.md](https://github.com/Nick2bad4u/ps-color-scripts-enhanced/blob/
668673
## CI/CD & Workflows
669674

670675
- ⚙️ [Test Workflow](https://github.com/Nick2bad4u/ps-color-scripts-enhanced/blob/main/.github/workflows/test.yml)
671-
- 📦 [Publish Workflow](https://github.com/Nick2bad4u/ps-color-scripts-enhanced/blob/main/.github/workflows/publish.yml)
676+
-[Code Coverage](https://codecov.io/gh/Nick2bad4u/ps-color-scripts-enhanced) - Automated via Codecov
677+
- �📦 [Publish Workflow](https://github.com/Nick2bad4u/ps-color-scripts-enhanced/blob/main/.github/workflows/publish.yml)
672678
- 🤖 [Dependabot Updates](https://github.com/Nick2bad4u/ps-color-scripts-enhanced/blob/main/.github/dependabot.yml)
673679

680+
## Testing
681+
682+
This module uses [Pester](https://pester.dev/) for testing with code coverage tracking:
683+
684+
```powershell
685+
# Run all tests
686+
npm run test
687+
688+
# Run tests with coverage report
689+
npm run test:coverage
690+
691+
# Generate HTML coverage report (requires ReportGenerator)
692+
npm run test:coverage:report
693+
694+
# Run tests directly with Pester
695+
Invoke-Pester -Path ./Tests
696+
697+
# Run with coverage using the script
698+
./scripts/Test-Coverage.ps1 -ShowReport
699+
```
700+
701+
Coverage reports are automatically uploaded to [Codecov](https://codecov.io/gh/Nick2bad4u/ps-color-scripts-enhanced) on every push.
702+
674703
## Support
675704

676705
For support options, response targets, and contact channels, review the [Support Policy](https://github.com/Nick2bad4u/ps-color-scripts-enhanced/blob/main/docs/SUPPORT.md). Bug reports and feature ideas live in the [issue tracker](https://github.com/Nick2bad4u/ps-color-scripts-enhanced/issues).
1.18 MB
Loading

assets/ColorScripts-Mascot.jpeg

1.31 MB
Loading

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
"test": "npm run test:custom && npm run test:pester",
2323
"test:custom": "pwsh -NoProfile -File ./scripts/Test-Module.ps1",
2424
"test:pester": "pwsh -NoProfile -Command \"Invoke-Pester -Path ./Tests\"",
25+
"test:coverage": "pwsh -NoProfile -File ./scripts/Test-Coverage.ps1",
26+
"test:coverage:report": "pwsh -NoProfile -File ./scripts/Test-Coverage.ps1 -ShowReport",
2527
"docs:update-counts": "pwsh -NoProfile -File ./scripts/Update-DocumentationCounts.ps1",
2628
"package:metadata": "pwsh -NoProfile -File ./scripts/Update-NuGetPackageMetadata.ps1",
2729
"scripts:convert": "node ./scripts/Convert-AnsiToColorScript.js",

scripts/Test-Coverage.ps1

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# Run Pester tests with code coverage
2+
# Generates coverage reports in multiple formats
3+
4+
#Requires -Version 5.1
5+
6+
[CmdletBinding()]
7+
param(
8+
[Parameter()]
9+
[switch]$ShowReport,
10+
11+
[Parameter()]
12+
[int]$MinimumCoverage = 70,
13+
14+
[Parameter()]
15+
[switch]$CI
16+
)
17+
18+
$ErrorActionPreference = 'Stop'
19+
20+
# Ensure Pester v5+ is available
21+
$pesterModule = Get-Module -ListAvailable -Name Pester | Where-Object { $_.Version -ge '5.0.0' } | Select-Object -First 1
22+
if (-not $pesterModule) {
23+
Write-Host "Installing Pester v5..." -ForegroundColor Yellow
24+
Install-Module -Name Pester -MinimumVersion 5.0.0 -Force -SkipPublisherCheck -Scope CurrentUser
25+
Import-Module Pester -MinimumVersion 5.0.0 -Force
26+
}
27+
else {
28+
Import-Module Pester -MinimumVersion 5.0.0 -Force
29+
}
30+
31+
$repoRoot = Split-Path -Parent $PSScriptRoot
32+
$testsPath = Join-Path $repoRoot 'Tests'
33+
$modulePath = Join-Path $repoRoot 'ColorScripts-Enhanced'
34+
$coverageOutputPath = Join-Path $repoRoot 'coverage.xml'
35+
$coverageReportPath = Join-Path $repoRoot 'coverage-report'
36+
37+
Write-Host "`n=== ColorScripts-Enhanced Code Coverage ===" -ForegroundColor Cyan
38+
Write-Host "Module Path: $modulePath" -ForegroundColor Gray
39+
Write-Host "Tests Path: $testsPath" -ForegroundColor Gray
40+
Write-Host "Coverage Output: $coverageOutputPath`n" -ForegroundColor Gray
41+
42+
# Configure Pester
43+
$config = New-PesterConfiguration
44+
45+
# Test discovery
46+
$config.Run.Path = $testsPath
47+
$config.Run.Exit = $CI.IsPresent
48+
49+
# Code coverage settings
50+
$config.CodeCoverage.Enabled = $true
51+
$config.CodeCoverage.Path = @(
52+
(Join-Path $modulePath 'ColorScripts-Enhanced.psm1')
53+
)
54+
$config.CodeCoverage.OutputPath = $coverageOutputPath
55+
$config.CodeCoverage.OutputFormat = 'JaCoCo'
56+
$config.CodeCoverage.CoveragePercentTarget = $MinimumCoverage
57+
58+
# Output settings
59+
$config.Output.Verbosity = 'Detailed'
60+
61+
# TestResult settings for CI
62+
if ($CI) {
63+
$config.TestResult.Enabled = $true
64+
$config.TestResult.OutputPath = Join-Path $repoRoot 'testResults.xml'
65+
$config.TestResult.OutputFormat = 'NUnitXml'
66+
}
67+
68+
# Run tests with coverage
69+
Write-Host "Running Pester tests with code coverage analysis..." -ForegroundColor Cyan
70+
$result = Invoke-Pester -Configuration $config
71+
72+
# Display coverage summary
73+
if ($result.CodeCoverage) {
74+
$coverage = $result.CodeCoverage
75+
$commandsExecuted = $coverage.CommandsExecuted.Count
76+
$commandsAnalyzed = $coverage.CommandsAnalyzed.Count
77+
78+
if ($commandsAnalyzed -gt 0) {
79+
$percentage = [math]::Round(($commandsExecuted / $commandsAnalyzed) * 100, 2)
80+
81+
Write-Host "`n=== Code Coverage Summary ===" -ForegroundColor Cyan
82+
Write-Host "Commands Covered: $commandsExecuted / $commandsAnalyzed" -ForegroundColor White
83+
84+
$color = if ($percentage -ge 80) { 'Green' } elseif ($percentage -ge 60) { 'Yellow' } else { 'Red' }
85+
Write-Host "Coverage: $percentage%" -ForegroundColor $color
86+
87+
if ($coverage.MissedCommands -and $coverage.MissedCommands.Count -gt 0) {
88+
Write-Host "`nTop 10 Missed Commands:" -ForegroundColor Yellow
89+
$coverage.MissedCommands | Select-Object -First 10 | Format-Table File, Line, Command -AutoSize
90+
}
91+
92+
# Check minimum coverage threshold
93+
if ($percentage -lt $MinimumCoverage) {
94+
Write-Warning "Coverage ($percentage%) is below minimum threshold ($MinimumCoverage%)"
95+
if ($CI) {
96+
exit 1
97+
}
98+
}
99+
else {
100+
Write-Host "`n✓ Coverage meets minimum threshold ($MinimumCoverage%)" -ForegroundColor Green
101+
}
102+
}
103+
}
104+
105+
# Generate HTML report if requested
106+
if ($ShowReport -and (Test-Path $coverageOutputPath)) {
107+
Write-Host "`nGenerating HTML coverage report..." -ForegroundColor Cyan
108+
109+
# Check if reportgenerator is available
110+
$reportGenerator = Get-Command reportgenerator -ErrorAction SilentlyContinue
111+
112+
if (-not $reportGenerator) {
113+
Write-Host "Installing ReportGenerator..." -ForegroundColor Yellow
114+
dotnet tool install -g dotnet-reportgenerator-globaltool
115+
$reportGenerator = Get-Command reportgenerator -ErrorAction SilentlyContinue
116+
}
117+
118+
if ($reportGenerator) {
119+
& reportgenerator `
120+
-reports:$coverageOutputPath `
121+
-targetdir:$coverageReportPath `
122+
-reporttypes:Html
123+
124+
$indexPath = Join-Path $coverageReportPath 'index.html'
125+
if (Test-Path $indexPath) {
126+
Write-Host "✓ HTML report generated: $indexPath" -ForegroundColor Green
127+
128+
# Open in browser
129+
if (-not $CI) {
130+
Start-Process $indexPath
131+
}
132+
}
133+
}
134+
else {
135+
Write-Warning "ReportGenerator not available. Install .NET SDK and run: dotnet tool install -g dotnet-reportgenerator-globaltool"
136+
}
137+
}
138+
139+
# Display test results summary
140+
Write-Host "`n=== Test Results Summary ===" -ForegroundColor Cyan
141+
Write-Host "Total Tests: $($result.TotalCount)" -ForegroundColor White
142+
Write-Host "Passed: $($result.PassedCount)" -ForegroundColor Green
143+
Write-Host "Failed: $($result.FailedCount)" -ForegroundColor $(if ($result.FailedCount -gt 0) { 'Red' } else { 'Green' })
144+
Write-Host "Skipped: $($result.SkippedCount)" -ForegroundColor Yellow
145+
146+
if ($result.FailedCount -gt 0) {
147+
Write-Host "`nFailed Tests:" -ForegroundColor Red
148+
$result.Failed | ForEach-Object {
149+
Write-Host " - $($_.ExpandedPath)" -ForegroundColor Red
150+
}
151+
}
152+
153+
Write-Host ""
154+
155+
# Exit with appropriate code
156+
if ($CI) {
157+
exit $result.FailedCount
158+
}

0 commit comments

Comments
 (0)