Skip to content

Commit ac83aa5

Browse files
Speedup CI (#2352)
* Test refactoring exercises via solution * Test using solution and in-place
1 parent 03de5bc commit ac83aa5

File tree

3 files changed

+140
-62
lines changed

3 files changed

+140
-62
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@ build/
2424

2525
# Other files
2626
.DS_Store
27+
28+
# Temporary files
29+
exercises/**/*.tmp

bin/test.ps1

Lines changed: 96 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -26,97 +26,131 @@ param (
2626
$ErrorActionPreference = "Stop"
2727
$PSNativeCommandUseErrorActionPreference = $true
2828

29-
function Invoke-Build-Generators {
30-
Write-Output "Building generators"
31-
& dotnet build ./generators
29+
function Invoke-Tests($Path) {
30+
& dotnet test $Path
3231
}
3332

34-
function Clean($BuildDir) {
35-
Write-Output "Cleaning previous build"
36-
Remove-Item -Recurse -Force $BuildDir -ErrorAction Ignore
37-
}
33+
function Prepare-Exercise($Path) {
34+
$files = Get-Content (Join-Path $Path ".meta" "config.json") -Raw | ConvertFrom-Json | Select-Object -ExpandProperty files
3835

39-
function Copy-Exercise($SourceDir, $BuildDir) {
40-
Write-Output "Copying exercises"
41-
Copy-Item $SourceDir -Destination $BuildDir -Recurse
42-
}
36+
foreach ($fileType in @("example", "exemplar")) {
37+
for (($i = 0); $i -lt $files.$fileType.length; $i++) {
38+
$exampleFile = Join-Path $Path $files.$fileType[$i]
39+
$solutionFile = Join-Path $Path $files.solution[$i]
4340

44-
function Enable-All-UnitTests($BuildDir) {
45-
Write-Output "Enabling all tests"
46-
Get-ChildItem -Path $BuildDir -Include "*Tests.cs" -Recurse | ForEach-Object {
47-
(Get-Content $_.FullName) -replace "Skip = ""Remove this Skip property to run this test""", "" | Set-Content $_.FullName
41+
Copy-Item -Path $solutionFile -Destination "${solutionFile}.tmp"
42+
Copy-Item -Path $exampleFile -Destination $solutionFile
43+
}
4844
}
49-
}
5045

51-
function Test-Refactoring-Projects($PracticeExercisesDir) {
52-
Write-Output "Testing refactoring projects"
53-
@("tree-building", "ledger", "markdown") | ForEach-Object {
54-
Invoke-Tests -Path "${PracticeExercisesDir}/${_}"
46+
foreach ($testFile in $files.test) {
47+
$testFile = Join-Path $Path $testFile
48+
Copy-Item -Path $testFile -Destination "${testFile}.tmp"
49+
(Get-Content $testFile) -replace "Skip = ""Remove this Skip property to run this test""", "" | Set-Content $testFile
5550
}
5651
}
5752

58-
function Set-ExampleImplementation {
59-
[CmdletBinding(SupportsShouldProcess)]
60-
param($ExercisesDir, $ReplaceFileName)
61-
62-
if ($PSCmdlet.ShouldProcess("Exercise ${ReplaceFileName}", "replace solution with example")) {
63-
Get-ChildItem -Path $ExercisesDir -Include "*.csproj" -Recurse | ForEach-Object {
64-
$stub = Join-Path -Path $_.Directory ($_.BaseName + ".cs")
65-
$example = Join-Path -Path $_.Directory ".meta" $ReplaceFileName
53+
function Restore-Exercise($Path) {
54+
Get-ChildItem -Path $Path -Include "*.tmp" -Recurse | ForEach-Object {
55+
$tmpFile = $_.FullName
56+
$originalFile = ($tmpFile -replace "\.tmp$", "")
57+
Move-Item -Path $tmpFile -Destination $originalFile -Force
58+
}
59+
}
6660

67-
Move-Item -Path $example -Destination $stub -Force
61+
function Process-Exercises($Exercises, [ScriptBlock]$Action) {
62+
foreach ($ExerciseType in @("practice", "concept")) {
63+
$Exercises.$ExerciseType | ForEach-Object {
64+
&$Action (Join-Path "exercises" $ExerciseType $_)
6865
}
6966
}
7067
}
7168

72-
function Use-ExampleImplementation {
73-
[CmdletBinding(SupportsShouldProcess)]
74-
param($ConceptExercisesDir, $PracticeExercisesDir)
75-
76-
if ($PSCmdlet.ShouldProcess("Exercises directory", "replace all solutions with corresponding examples")) {
77-
Write-Output "Replacing concept exercise stubs with exemplar"
78-
Set-ExampleImplementation $ConceptExercisesDir "Exemplar.cs"
69+
function Prepare-Exercises($Exercises) {
70+
Process-Exercises $Exercises {
71+
param($Path)
72+
Prepare-Exercise $Path
73+
}
74+
}
7975

80-
Write-Output "Replacing practice exercise stubs with example"
81-
Set-ExampleImplementation $PracticeExercisesDir "Example.cs"
76+
function Restore-Exercises($Exercises) {
77+
Process-Exercises $Exercises {
78+
param($Path)
79+
Restore-Exercise $Path
8280
}
8381
}
8482

85-
function Test-ExerciseImplementation($Exercise, $BuildDir, $ConceptExercisesDir, $PracticeExercisesDir) {
86-
Write-Output "Running tests"
83+
function Run-Tests($Path) {
84+
& dotnet test $Path
85+
}
8786

88-
if (-Not $Exercise) {
89-
Invoke-Tests -Path $BuildDir
87+
function Find-Exercise-Path($Exercise, $Exercises) {
88+
if ($Exercises.practice.Contains($Exercise)) {
89+
Join-Path "exercises" "practice" $Exercise
90+
}
91+
elseif ($Exercises.concept.Contains($Exercise)) {
92+
Join-Path "exercises" "concept" $Exercise
93+
} else {
94+
throw "Could not find exercise '${Exercise}'"
9095
}
91-
elseif (Test-Path "${ConceptExercisesDir}/${Exercise}") {
92-
Invoke-Tests -Path "${ConceptExercisesDir}/${Exercise}"
96+
}
97+
98+
function Test-Single-Exercise($Exercise, $Exercises) {
99+
$path = Find-Exercise-Path $Exercise $Exercises
100+
101+
try {
102+
Prepare-Exercise $path
103+
Run-Tests $path
104+
} finally {
105+
Restore-Exercise $path
93106
}
94-
elseif (Test-Path "${PracticeExercisesDir}/${Exercise}") {
95-
Invoke-Tests -Path "${PracticeExercisesDir}/${Exercise}"
107+
}
108+
109+
function Test-All-Exercises($Exercises) {
110+
try {
111+
Prepare-Exercises $Exercises
112+
Run-Tests "exercises/Exercises.sln"
113+
} finally {
114+
Restore-Exercises $Exercises
96115
}
97-
else {
98-
throw "Could not find exercise '${Exercise}'"
116+
}
117+
118+
function Parse-Exercises {
119+
Get-Content .\config.json -Raw |
120+
ConvertFrom-Json |
121+
Select-Object -ExpandProperty exercises |
122+
ForEach-Object {
123+
@{
124+
concept = $_.concept | Select-Object -ExpandProperty slug | Sort-Object
125+
practice = $_.practice | Select-Object -ExpandProperty slug | Sort-Object
126+
}
99127
}
100128
}
101129

102-
function Invoke-Tests($Path) {
103-
& dotnet test $Path
130+
function Build-Generators {
131+
Write-Output "Build generators"
132+
& dotnet build generators
133+
}
134+
135+
function Test-Refactoring-Exercise-Default-Implementations {
136+
Write-Output "Testing refactoring exercises"
137+
& dotnet test (Join-Path "exercises" "Refactoring.sln")
104138
}
105139

140+
function Test-Exercise-Example-Implementations($Exercise) {
141+
Write-Output "Testing example implementations"
142+
$exercises = Parse-Exercises
106143

107-
$buildDir = "${PSScriptRoot}/build"
108-
$practiceExercisesDir = "${buildDir}/practice"
109-
$conceptExercisesDir = "${buildDir}/concept"
110-
$sourceDir = Resolve-Path "exercises"
144+
if ($Exercise) {
145+
Test-Single-Exercise $Exercise $Exercises
146+
} else {
147+
Test-All-Exercises $Exercises
148+
}
149+
}
111150

112-
Clean $buildDir
113-
Copy-Exercise $sourceDir $buildDir
114-
Enable-All-UnitTests $buildDir
151+
Test-Exercise-Example-Implementations $Exercise
115152

116153
if (!$Exercise) {
117-
Invoke-Build-Generators
118-
Test-Refactoring-Projects $practiceExercisesDir
154+
Build-Generators
155+
Test-Refactoring-Exercise-Default-Implementations
119156
}
120-
121-
Use-ExampleImplementation $conceptExercisesDir $practiceExercisesDir
122-
Test-ExerciseImplementation -Exercise $Exercise -BuildDir $buildDir -ConceptExercisesDir $conceptExercisesDir -PracticeExercisesDir $practiceExercisesDir

exercises/Refactoring.sln

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.0.31903.59
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "practice", "practice", "{9CE64A98-EA82-4784-93E4-2C14222C5FDD}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TreeBuilding", "practice\tree-building\TreeBuilding.csproj", "{202A66E7-F0BB-4B0D-A7C0-AE92B3B48B7F}"
9+
EndProject
10+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ledger", "practice\ledger\Ledger.csproj", "{11EBF5DF-CE22-40D8-B96E-687461A16C1E}"
11+
EndProject
12+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Markdown", "practice\markdown\Markdown.csproj", "{CB0F19FE-C1B9-4EC6-B969-C0F74B70E134}"
13+
EndProject
14+
Global
15+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
16+
Debug|Any CPU = Debug|Any CPU
17+
Release|Any CPU = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
23+
{202A66E7-F0BB-4B0D-A7C0-AE92B3B48B7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24+
{202A66E7-F0BB-4B0D-A7C0-AE92B3B48B7F}.Debug|Any CPU.Build.0 = Debug|Any CPU
25+
{202A66E7-F0BB-4B0D-A7C0-AE92B3B48B7F}.Release|Any CPU.ActiveCfg = Release|Any CPU
26+
{202A66E7-F0BB-4B0D-A7C0-AE92B3B48B7F}.Release|Any CPU.Build.0 = Release|Any CPU
27+
{11EBF5DF-CE22-40D8-B96E-687461A16C1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
28+
{11EBF5DF-CE22-40D8-B96E-687461A16C1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
29+
{11EBF5DF-CE22-40D8-B96E-687461A16C1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
30+
{11EBF5DF-CE22-40D8-B96E-687461A16C1E}.Release|Any CPU.Build.0 = Release|Any CPU
31+
{CB0F19FE-C1B9-4EC6-B969-C0F74B70E134}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
32+
{CB0F19FE-C1B9-4EC6-B969-C0F74B70E134}.Debug|Any CPU.Build.0 = Debug|Any CPU
33+
{CB0F19FE-C1B9-4EC6-B969-C0F74B70E134}.Release|Any CPU.ActiveCfg = Release|Any CPU
34+
{CB0F19FE-C1B9-4EC6-B969-C0F74B70E134}.Release|Any CPU.Build.0 = Release|Any CPU
35+
EndGlobalSection
36+
GlobalSection(NestedProjects) = preSolution
37+
{202A66E7-F0BB-4B0D-A7C0-AE92B3B48B7F} = {9CE64A98-EA82-4784-93E4-2C14222C5FDD}
38+
{11EBF5DF-CE22-40D8-B96E-687461A16C1E} = {9CE64A98-EA82-4784-93E4-2C14222C5FDD}
39+
{CB0F19FE-C1B9-4EC6-B969-C0F74B70E134} = {9CE64A98-EA82-4784-93E4-2C14222C5FDD}
40+
EndGlobalSection
41+
EndGlobal

0 commit comments

Comments
 (0)