From bb81f7954f46f63492de4ec1feecd704aef3b3c9 Mon Sep 17 00:00:00 2001 From: Florian Eiden Date: Thu, 10 Sep 2020 14:30:16 -0700 Subject: [PATCH 01/18] Revert hotfix --- asa.unittest/private/Install-AutToolset.ps1 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/asa.unittest/private/Install-AutToolset.ps1 b/asa.unittest/private/Install-AutToolset.ps1 index 2ea7832..59a1109 100644 --- a/asa.unittest/private/Install-AutToolset.ps1 +++ b/asa.unittest/private/Install-AutToolset.ps1 @@ -56,9 +56,7 @@ Function Install-AutToolset{ foreach ($nugetPackage in $nugetPackages){ Write-Verbose "002 - Installing nuget package : $nugetPackage" - #Hotfix for release 1.0.10 - #Invoke-External -l "$installPath\nuget.exe" install $nugetPackage -OutputDirectory $installPath | - Invoke-External -l "$installPath\nuget.exe" install "Microsoft.Azure.StreamAnalytics.CICD" -version "2.4.1" -OutputDirectory $installPath | + Invoke-External -l "$installPath\nuget.exe" install $nugetPackage -OutputDirectory $installPath | Out-Null } From 55504ca6e69ff1454f1e8cd13c318d49fde94487 Mon Sep 17 00:00:00 2001 From: Florian Eiden Date: Thu, 10 Sep 2020 14:50:37 -0700 Subject: [PATCH 02/18] Add failing test for 3.0.0 support --- .../New-AutRunFixture.Tests.ps1 | 123 +++++++++++++----- 1 file changed, 93 insertions(+), 30 deletions(-) diff --git a/asa.unittest.tests/New-AutRunFixture.Tests.ps1 b/asa.unittest.tests/New-AutRunFixture.Tests.ps1 index 7a095b2..dd80990 100644 --- a/asa.unittest.tests/New-AutRunFixture.Tests.ps1 +++ b/asa.unittest.tests/New-AutRunFixture.Tests.ps1 @@ -99,16 +99,6 @@ Describe "New-AutRunFixture nominal" { Assert-MockCalled Copy-Item -Times 3 -Exactly -Scope It -ParameterFilter {$Path -like "*.as*"} } - It "copies ASA cs code behind files in each test case folders" { - New-AutRunFixture ` - -solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - -testID $t_testID - - Assert-MockCalled Copy-Item -Times 3 -Exactly -Scope It -ParameterFilter {$Path -like "*.cs"} - } - Mock Test-Path {return $false} -ParameterFilter {$Path -like "*.asaproj"} It "calls New-AUTAsaprojXML if needed" { New-AutRunFixture ` @@ -142,6 +132,99 @@ Describe "New-AutRunFixture nominal" { Assert-MockCalled Copy-Item -Times 3 -Exactly -Scope It -ParameterFilter {$Path -like "*Local*.json"} } + It "copies test files from 1_arrange in each test case folders" { + New-AutRunFixture ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID + + Assert-MockCalled Copy-Item -Times 4 -Exactly -Scope It -ParameterFilter {$Path -like "foobar*"} + } + + It "edit the ASA conf file for each input files" { + New-AutRunFixture ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID + + Assert-MockCalled Out-File -Times 2 -Exactly -Scope It + } + + } +} +Describe "New-AutRunFixture ASA cs code behind files handling" { + InModuleScope $moduleName { + + $t_solutionPath = "TestDrive:\foo" + $t_asaProjectName = "bar" + $t_unittestFolder = "bar.Tests" + $t_testID = "yyyymmddhhmmss" + + $t_tests = @( + [PSCustomObject] @{Basename0="003";FilePath="foobar";Basename1="Input";FullName="fb"}, + [PSCustomObject] @{Basename0="001";FilePath="foobar1";Basename1="Input";FullName="fb"}, + [PSCustomObject] @{Basename0="001";FilePath="foobar2"}, + [PSCustomObject] @{Basename0="002";FilePath="foobar"} + ) + + Mock Get-ChildItem {1} + Mock Get-AutFieldFromFileInfo {return $t_tests} + Mock New-Item {} + Mock Copy-Item {} + Mock Test-Path {return $true} + Mock New-AUTAsaprojXML {} + Mock Get-Content {return (@{FilePath="foobar"} | ConvertTo-Json)} + Mock Out-File {} + + It "copies ASA cs code behind files in each test case folders" { + New-AutRunFixture ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID + + Assert-MockCalled Copy-Item -Times 3 -Exactly -Scope It -ParameterFilter {$Path -like "*.cs"} + } + + Mock Test-Path {return $false} -ParameterFilter {$Path -and ($Path -like "*$t_asaProjectName.asaql.cs")} + It "creates an empty file if there's none"{ + New-AutRunFixture ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID + + Assert-MockCalled New-Item -Times 3 -Exactly -Scope It -ParameterFilter {$Path -like "*$t_asaProjectName.asaql.cs"} + } + } +} + +Describe "New-AutRunFixture ASA functions handling" { + InModuleScope $moduleName { + + $t_solutionPath = "TestDrive:\foo" + $t_asaProjectName = "bar" + $t_unittestFolder = "bar.Tests" + $t_testID = "yyyymmddhhmmss" + + $t_tests = @( + [PSCustomObject] @{Basename0="003";FilePath="foobar";Basename1="Input";FullName="fb"}, + [PSCustomObject] @{Basename0="001";FilePath="foobar1";Basename1="Input";FullName="fb"}, + [PSCustomObject] @{Basename0="001";FilePath="foobar2"}, + [PSCustomObject] @{Basename0="002";FilePath="foobar"} + ) + + Mock Get-ChildItem {1} + Mock Get-AutFieldFromFileInfo {return $t_tests} + Mock New-Item {} + Mock Copy-Item {} + Mock Test-Path {return $true} + Mock New-AUTAsaprojXML {} + Mock Get-Content {return (@{FilePath="foobar"} | ConvertTo-Json)} + Mock Out-File {} + Mock Test-Path {return $true} -ParameterFilter {$Path -and ($Path -like "*\Functions\")} It "creates function subfolder in each test case folder" { New-AutRunFixture ` @@ -220,26 +303,6 @@ Describe "New-AutRunFixture nominal" { } Mock Test-Path {return $true} - It "copies test files from 1_arrange in each test case folders" { - New-AutRunFixture ` - -solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - -testID $t_testID - - Assert-MockCalled Copy-Item -Times 4 -Exactly -Scope It -ParameterFilter {$Path -like "foobar*"} - } - - It "edit the ASA conf file for each input files" { - New-AutRunFixture ` - -solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - -testID $t_testID - - Assert-MockCalled Out-File -Times 2 -Exactly -Scope It - } - } } From cd37f00a7095f9c3e922bd9ed6f657d379190561 Mon Sep 17 00:00:00 2001 From: Florian Eiden Date: Thu, 10 Sep 2020 15:00:47 -0700 Subject: [PATCH 03/18] Fix test syntax --- asa.unittest.tests/New-AutRunFixture.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asa.unittest.tests/New-AutRunFixture.Tests.ps1 b/asa.unittest.tests/New-AutRunFixture.Tests.ps1 index dd80990..945a107 100644 --- a/asa.unittest.tests/New-AutRunFixture.Tests.ps1 +++ b/asa.unittest.tests/New-AutRunFixture.Tests.ps1 @@ -196,7 +196,7 @@ Describe "New-AutRunFixture ASA cs code behind files handling" { -unittestFolder $t_unittestFolder ` -testID $t_testID - Assert-MockCalled New-Item -Times 3 -Exactly -Scope It -ParameterFilter {$Path -like "*$t_asaProjectName.asaql.cs"} + Assert-MockCalled New-Item -Times 3 -Exactly -Scope It -ParameterFilter {$Name -like "$t_asaProjectName.asaql.cs"} } } } From e360d387a52d6559f3cbcebd9d8e873f2293d233 Mon Sep 17 00:00:00 2001 From: Florian Eiden Date: Thu, 10 Sep 2020 15:00:55 -0700 Subject: [PATCH 04/18] Pass test --- asa.unittest/private/New-AutRunFixture.ps1 | 40 +++++++++++++--------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/asa.unittest/private/New-AutRunFixture.ps1 b/asa.unittest/private/New-AutRunFixture.ps1 index ba67fd4..134451f 100644 --- a/asa.unittest/private/New-AutRunFixture.ps1 +++ b/asa.unittest/private/New-AutRunFixture.ps1 @@ -79,6 +79,7 @@ Function New-AutRunFixture{ Out-Null ## Copy .asaql, .asaql.cs, .asaproj (XML) and JobConfig, asaproj (JSON) required for run in each test case folder + ## If there's no asaql.cs, dummy ones will created be later $testFolders | Select-Object @{Name="Destination"; Expression = {"$($_.Path)\$asaProjectName\"}} | Copy-Item -Path "$asaProjectPath\*.as*","$asaProjectPath\*.cs","$asaProjectPath\*.json" -recurse | @@ -107,23 +108,28 @@ Function New-AutRunFixture{ Out-Null if (Test-Path("$asaProjectPath\Functions\")) { - ## Create an ASA function folder in test case folder - $testFolders | - Select-Object @{Name = "Path"; Expression = {"$($_.Path)\$asaProjectName\Functions\"}} | - New-Item -ItemType Directory | - Out-Null - - ## Copy the local JS function files required for run in each test case folder - $testFolders | - Select-Object @{Name="Destination"; Expression = {"$($_.Path)\$asaProjectName\Functions\"}} | - Copy-Item -Path "$asaProjectPath\Functions\*.js" -recurse | - Out-Null - - ## Copy the local JS function definition files (JSON) required for run in each test case folder - $testFolders | - Select-Object @{Name="Destination"; Expression = {"$($_.Path)\$asaProjectName\Functions\"}} | - Copy-Item -Path "$asaProjectPath\Functions\*.js.json" -recurse | - Out-Null + ## Create an ASA function folder in test case folder + $testFolders | + Select-Object @{Name = "Path"; Expression = {"$($_.Path)\$asaProjectName\Functions\"}} | + New-Item -ItemType Directory | + Out-Null + + ## Copy the local JS function files required for run in each test case folder + $testFolders | + Select-Object @{Name="Destination"; Expression = {"$($_.Path)\$asaProjectName\Functions\"}} | + Copy-Item -Path "$asaProjectPath\Functions\*.js" -recurse | + Out-Null + + ## Copy the local JS function definition files (JSON) required for run in each test case folder + $testFolders | + Select-Object @{Name="Destination"; Expression = {"$($_.Path)\$asaProjectName\Functions\"}} | + Copy-Item -Path "$asaProjectPath\Functions\*.js.json" -recurse | + Out-Null + } + + ## If there's no asaql.cs in the source folder, create dummy ones + if (-not (Test-Path("$asaProjectPath\$asaProjectName.asaql.cs"))) { + $testFolders | New-Item -Name "$asaProjectName.asaql.cs" -ItemType file } ################################################################################################################################ From a909f9d4168e78994170399ffba89239c0a5473d Mon Sep 17 00:00:00 2001 From: Florian Eiden Date: Thu, 10 Sep 2020 15:06:57 -0700 Subject: [PATCH 05/18] Update test to correct subfolder --- asa.unittest.tests/New-AutRunFixture.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asa.unittest.tests/New-AutRunFixture.Tests.ps1 b/asa.unittest.tests/New-AutRunFixture.Tests.ps1 index 945a107..1fa1604 100644 --- a/asa.unittest.tests/New-AutRunFixture.Tests.ps1 +++ b/asa.unittest.tests/New-AutRunFixture.Tests.ps1 @@ -196,7 +196,7 @@ Describe "New-AutRunFixture ASA cs code behind files handling" { -unittestFolder $t_unittestFolder ` -testID $t_testID - Assert-MockCalled New-Item -Times 3 -Exactly -Scope It -ParameterFilter {$Name -like "$t_asaProjectName.asaql.cs"} + Assert-MockCalled New-Item -Times 3 -Exactly -Scope It -ParameterFilter {($Name -like "$t_asaProjectName.asaql.cs") -and ($Path -like "*\$t_asaProjectName")} } } } From a0ebe8e2b0db220230418575d985941ff832dd8e Mon Sep 17 00:00:00 2001 From: Florian Eiden Date: Thu, 10 Sep 2020 15:07:04 -0700 Subject: [PATCH 06/18] Pass tests --- asa.unittest/private/New-AutRunFixture.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asa.unittest/private/New-AutRunFixture.ps1 b/asa.unittest/private/New-AutRunFixture.ps1 index 134451f..acc99ff 100644 --- a/asa.unittest/private/New-AutRunFixture.ps1 +++ b/asa.unittest/private/New-AutRunFixture.ps1 @@ -129,7 +129,7 @@ Function New-AutRunFixture{ ## If there's no asaql.cs in the source folder, create dummy ones if (-not (Test-Path("$asaProjectPath\$asaProjectName.asaql.cs"))) { - $testFolders | New-Item -Name "$asaProjectName.asaql.cs" -ItemType file + $testFolders | New-Item -Path "$($_.Path)\$asaProjectName" -Name "$asaProjectName.asaql.cs" -ItemType file } ################################################################################################################################ From 1298a8cd11fd804f24a6263df0d5525e591c8544 Mon Sep 17 00:00:00 2001 From: Florian Eiden Date: Thu, 10 Sep 2020 15:08:30 -0700 Subject: [PATCH 07/18] Update subfolder syntax --- asa.unittest.tests/New-AutRunFixture.Tests.ps1 | 2 +- asa.unittest/private/New-AutRunFixture.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/asa.unittest.tests/New-AutRunFixture.Tests.ps1 b/asa.unittest.tests/New-AutRunFixture.Tests.ps1 index 1fa1604..94fd55e 100644 --- a/asa.unittest.tests/New-AutRunFixture.Tests.ps1 +++ b/asa.unittest.tests/New-AutRunFixture.Tests.ps1 @@ -196,7 +196,7 @@ Describe "New-AutRunFixture ASA cs code behind files handling" { -unittestFolder $t_unittestFolder ` -testID $t_testID - Assert-MockCalled New-Item -Times 3 -Exactly -Scope It -ParameterFilter {($Name -like "$t_asaProjectName.asaql.cs") -and ($Path -like "*\$t_asaProjectName")} + Assert-MockCalled New-Item -Times 3 -Exactly -Scope It -ParameterFilter {($Name -like "$t_asaProjectName.asaql.cs") -and ($Path -like "*\$t_asaProjectName\")} } } } diff --git a/asa.unittest/private/New-AutRunFixture.ps1 b/asa.unittest/private/New-AutRunFixture.ps1 index acc99ff..f616452 100644 --- a/asa.unittest/private/New-AutRunFixture.ps1 +++ b/asa.unittest/private/New-AutRunFixture.ps1 @@ -129,7 +129,7 @@ Function New-AutRunFixture{ ## If there's no asaql.cs in the source folder, create dummy ones if (-not (Test-Path("$asaProjectPath\$asaProjectName.asaql.cs"))) { - $testFolders | New-Item -Path "$($_.Path)\$asaProjectName" -Name "$asaProjectName.asaql.cs" -ItemType file + $testFolders | New-Item -Path "$($_.Path)\$asaProjectName\" -Name "$asaProjectName.asaql.cs" -ItemType file } ################################################################################################################################ From 25673de864d12d2583567bc19e5529bb73a198cf Mon Sep 17 00:00:00 2001 From: Florian Eiden Date: Thu, 10 Sep 2020 15:13:10 -0700 Subject: [PATCH 08/18] Update parameter syntax --- asa.unittest/private/New-AutRunFixture.ps1 | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/asa.unittest/private/New-AutRunFixture.ps1 b/asa.unittest/private/New-AutRunFixture.ps1 index f616452..f64d8c1 100644 --- a/asa.unittest/private/New-AutRunFixture.ps1 +++ b/asa.unittest/private/New-AutRunFixture.ps1 @@ -110,26 +110,28 @@ Function New-AutRunFixture{ if (Test-Path("$asaProjectPath\Functions\")) { ## Create an ASA function folder in test case folder $testFolders | - Select-Object @{Name = "Path"; Expression = {"$($_.Path)\$asaProjectName\Functions\"}} | - New-Item -ItemType Directory | - Out-Null + Select-Object @{Name = "Path"; Expression = {"$($_.Path)\$asaProjectName\Functions\"}} | + New-Item -ItemType Directory | + Out-Null ## Copy the local JS function files required for run in each test case folder $testFolders | - Select-Object @{Name="Destination"; Expression = {"$($_.Path)\$asaProjectName\Functions\"}} | - Copy-Item -Path "$asaProjectPath\Functions\*.js" -recurse | - Out-Null + Select-Object @{Name="Destination"; Expression = {"$($_.Path)\$asaProjectName\Functions\"}} | + Copy-Item -Path "$asaProjectPath\Functions\*.js" -recurse | + Out-Null ## Copy the local JS function definition files (JSON) required for run in each test case folder $testFolders | - Select-Object @{Name="Destination"; Expression = {"$($_.Path)\$asaProjectName\Functions\"}} | - Copy-Item -Path "$asaProjectPath\Functions\*.js.json" -recurse | - Out-Null + Select-Object @{Name="Destination"; Expression = {"$($_.Path)\$asaProjectName\Functions\"}} | + Copy-Item -Path "$asaProjectPath\Functions\*.js.json" -recurse | + Out-Null } ## If there's no asaql.cs in the source folder, create dummy ones if (-not (Test-Path("$asaProjectPath\$asaProjectName.asaql.cs"))) { - $testFolders | New-Item -Path "$($_.Path)\$asaProjectName\" -Name "$asaProjectName.asaql.cs" -ItemType file + $testFolders | + Select-Object @{Name = "Path"; Expression = {"$($_.Path)\$asaProjectName\"}} | + New-Item -Name "$asaProjectName.asaql.cs" -ItemType file } ################################################################################################################################ From 004f373b4f3375e726f31b50d9ae5ef90f0adea6 Mon Sep 17 00:00:00 2001 From: Florian Eiden Date: Thu, 10 Sep 2020 20:16:48 -0700 Subject: [PATCH 09/18] Comment obsolete parameter --- README_DEV.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_DEV.md b/README_DEV.md index 3af6faf..cc82403 100644 --- a/README_DEV.md +++ b/README_DEV.md @@ -63,7 +63,7 @@ Scripts should be isolated in atomic .ps1 file, written as advanced functions. T Common parameters: ```PowerShell -$ASAnugetVersion = "2.4.0" +#$ASAnugetVersion = "2.4.0" $solutionPath = "C:\Users\fleide\Repos\asa.unittest\examples" $asaProjectName = "ASAHelloWorld" $unittestFolder = "ASAHelloWorld.Tests" From 8a8690ac86db44e5161e5e36570b539147797ab5 Mon Sep 17 00:00:00 2001 From: Florian Eiden Date: Fri, 11 Sep 2020 14:33:22 -0700 Subject: [PATCH 10/18] Add support for dependency versioning --- .../Install-AutToolset.Tests.ps1 | 256 +++++++----------- asa.unittest/private/Install-AutToolset.ps1 | 46 ++-- 2 files changed, 108 insertions(+), 194 deletions(-) diff --git a/asa.unittest.tests/Install-AutToolset.Tests.ps1 b/asa.unittest.tests/Install-AutToolset.Tests.ps1 index 09f277a..aa13e3e 100644 --- a/asa.unittest.tests/Install-AutToolset.Tests.ps1 +++ b/asa.unittest.tests/Install-AutToolset.Tests.ps1 @@ -1,165 +1,93 @@ -### If tests are in ModuleRoot\Whatever, and scripts reachable via a module at ModuleRoot\Module\Module.psm1 - -$projectRoot = Resolve-Path "$PSScriptRoot\.." #ModuleRoot\Whatever becomes \ModuleRoot with .. -$moduleRoot = Split-Path (Resolve-Path "$projectRoot\*\*.psd1") #Look for the manifest to get to ModuleRoot\Module -$moduleName = Split-Path $moduleRoot -Leaf #Extract the module name from above -Import-Module (Join-Path $moduleRoot "$moduleName.psm1") -force - -############################################################################################################# -# Invoke-Pester .\Install-AutToolset.Tests.ps1 -CodeCoverage .\..\asa.unittest\private\Install-AutToolset.ps1 - -Describe "Install-AutToolset paramater installPath" { - InModuleScope $moduleName { - - $t_installPath = "foo" - - Mock Test-Path {return $true} -ParameterFilter {$Path -eq $t_installPath} - Mock Test-Path {return $true} -ParameterFilter { $PathType -and $PathType -eq "Leaf" } - Mock New-Item {} - Mock Invoke-WebRequest {} - Mock Invoke-External {} -ParameterFilter {$LiteralPath -like "*nuget*"} - Mock Invoke-External {} -ParameterFilter {$LiteralPath -eq "npm"} - - It "fails if installPath is missing" { - { Install-AutToolset } | - Should -throw "-installPath is required" - } - - It "doesn't create a folder if it exists" { - Install-AutToolset -installPath $t_installPath | - Assert-MockCalled New-Item -Times 0 -Exactly -Scope It -ParameterFilter {$Path -eq $t_installPath} - } - - Mock Test-Path {return $false} -ParameterFilter {$Path -eq $t_installPath} - It "does create a folder it doesn't" { - Install-AutToolset -installPath $t_installPath | - Assert-MockCalled New-Item -Times 1 -Exactly -Scope It -ParameterFilter {$Path -eq $t_installPath} - } - - } -} - -Describe "Install-AutToolset behavior nuget" { - InModuleScope $moduleName { - - $t_installPath = "foo" - $t_nugetPackages = "bar" - - # The test folder exists - Mock Test-Path {return $true} -ParameterFilter { $Path -and $Path -eq $t_installPath } - # Nuget.exe is not there - Mock Test-Path {return $false} -ParameterFilter { $PathType -and $PathType -eq "Leaf" } - Mock New-Item {} - Mock Invoke-WebRequest {} #Nuget download - Mock Invoke-External {} - - It "does not download nuget on default parameter" { - Install-AutToolset -installPath $t_installPath | - Assert-MockCalled Invoke-WebRequest -Times 0 -Exactly -Scope It - } - - $t_nugetPackages = "bar" - It "does download nuget once for 1 package" { - Install-AutToolset -installPath $t_installPath -nugetPackages $t_nugetPackages | - Assert-MockCalled Invoke-WebRequest -Times 1 -Exactly -Scope It - } - - $t_nugetPackages = "bar1","bar2" - It "does download nuget once for N packages" { - Install-AutToolset -installPath $t_installPath -nugetPackages $t_nugetPackages | - Assert-MockCalled Invoke-WebRequest -Times 1 -Exactly -Scope It - } - - $t_nugetPackages = "bar" - # Nuget.exe is already there - Mock Test-Path {return $true} -ParameterFilter { $PathType -and $PathType -eq "Leaf" } - It "does not download nuget when needed but already there" { - Install-AutToolset -installPath $t_installPath -nugetPackages $t_nugetPackages | - Assert-MockCalled Invoke-WebRequest -Times 0 -Exactly -Scope It - } - - $t_nugetPackages = - It "does not invoke nuget on default parameter" { - Install-AutToolset -installPath $t_installPath | - Assert-MockCalled Invoke-External -Times 0 -Exactly -Scope It -ParameterFilter { $LiteralPath -like "$t_installPath\nuget*" } - } - - $t_nugetPackages = "bar" - It "does invoke nuget once for 1 package" { - Install-AutToolset -installPath $t_installPath -nugetPackages $t_nugetPackages | - Assert-MockCalled Invoke-External -Times 1 -Exactly -Scope It -ParameterFilter { $LiteralPath -like "$t_installPath\nuget*" } - } - - $t_nugetPackages = "bar1","bar2" - It "does invoke nuget N times for N packages (N=2)" { - Install-AutToolset -installPath $t_installPath -nugetPackages $t_nugetPackages | - Assert-MockCalled Invoke-External -Times 2 -Exactly -Scope It -ParameterFilter { $LiteralPath -like "$t_installPath\nuget*" } - } - - - } -} - -Describe "Install-AutToolset npm" { - InModuleScope $moduleName { - - $t_installPath = "foo" - - # The test folder exists - Mock Test-Path {return $true} -ParameterFilter { $Path -and $Path -eq $t_installPath } - Mock New-Item {} - Mock Invoke-WebRequest {} #Nuget download - Mock Invoke-External {} - - It "does not invoke npm on default parameter" { - Install-AutToolset -installPath $t_installPath | - Assert-MockCalled Invoke-External -Times 0 -Exactly -Scope It -ParameterFilter { $LiteralPath -like "npm*" } - } - - $t_npmPackages = "bar" - It "does invoke npm once for 1 package" { - Install-AutToolset -installPath $t_installPath -npmPackages $t_npmPackages | - Assert-MockCalled Invoke-External -Times 1 -Exactly -Scope It -ParameterFilter { $LiteralPath -like "npm*" } - } - - $t_npmPackages = "bar1","bar2" - It "does invoke npm N times for N packages (N=2)" { - Install-AutToolset -installPath $t_installPath -npmPackages $t_npmPackages | - Assert-MockCalled Invoke-External -Times 2 -Exactly -Scope It -ParameterFilter { $LiteralPath -like "npm*" } - } - - Mock Invoke-External {Throw "npm: The term 'npm' is not"} -ParameterFilter { $LiteralPath -like "npm*" } - $t_npmPackages = "bar" - It "fails if npm is not installed" { - {Install-AutToolset -installPath $t_installPath -npmPackages $t_npmPackages} | - Should -throw "npm: The term 'npm' is not" - } - Mock Invoke-External {} #Nuget or npm executions - } -} - -Describe "Install-AutToolset nuget + npm" { - InModuleScope $moduleName { - - $installPath = "foo" - - # The test folder exists - Mock Test-Path {return $true} -ParameterFilter { $Path -and $Path -eq $installPath } - # Nuget.exe is not there - Mock Test-Path {return $false} -ParameterFilter { $PathType -and $PathType -eq "Leaf" } - Mock New-Item {} - Mock Invoke-WebRequest {} #Nuget download - Mock Invoke-External {} - - It "does invoke nuget for nuget + npm" { - Install-AutToolset -installPath $installPath -nugetPackages "bar1","bar2" -npmPackages "bar1","bar2" | - Assert-MockCalled Invoke-External -Times 2 -Exactly -Scope It -ParameterFilter { $LiteralPath -like "*nuget*" } - } - - It "does invoke npm for nuget + npm" { - Install-AutToolset -installPath $installPath -nugetPackages "bar1","bar2" -npmPackages "bar1","bar2" | - Assert-MockCalled Invoke-External -Times 2 -Exactly -Scope It -ParameterFilter { $LiteralPath -like "npm*" } - } - - } +### If tests are in ModuleRoot\Whatever, and scripts reachable via a module at ModuleRoot\Module\Module.psm1 + +$projectRoot = Resolve-Path "$PSScriptRoot\.." #ModuleRoot\Whatever becomes \ModuleRoot with .. +$moduleRoot = Split-Path (Resolve-Path "$projectRoot\*\*.psd1") #Look for the manifest to get to ModuleRoot\Module +$moduleName = Split-Path $moduleRoot -Leaf #Extract the module name from above +Import-Module (Join-Path $moduleRoot "$moduleName.psm1") -force + +############################################################################################################# +# Invoke-Pester .\Install-AutToolset.Tests.ps1 -CodeCoverage .\..\asa.unittest\private\Install-AutToolset.ps1 + +Describe "Install-AutToolset paramater installPath" { + InModuleScope $moduleName { + + $t_installPath = "foo" + + Mock Test-Path {return $true} -ParameterFilter {$Path -eq $t_installPath} + Mock Test-Path {return $true} -ParameterFilter { $PathType -and $PathType -eq "Leaf" } + Mock New-Item {} + Mock Invoke-WebRequest {} + Mock Invoke-External {} -ParameterFilter {$LiteralPath -like "*nuget*"} + + It "fails if installPath is missing" { + { Install-AutToolset } | + Should -throw "-installPath is required" + } + + It "doesn't create a folder if it exists" { + Install-AutToolset -installPath $t_installPath | + Assert-MockCalled New-Item -Times 0 -Exactly -Scope It -ParameterFilter {$Path -eq $t_installPath} + } + + Mock Test-Path {return $false} -ParameterFilter {$Path -eq $t_installPath} + It "does create a folder it doesn't" { + Install-AutToolset -installPath $t_installPath | + Assert-MockCalled New-Item -Times 1 -Exactly -Scope It -ParameterFilter {$Path -eq $t_installPath} + } + + } +} + +Describe "Install-AutToolset hashtable" { + InModuleScope $moduleName { + + $t_installPath = "foo" + + $t_nuget_version = @{type="nuget";Package="bar";version="1.x.version.y"} + $t_nuget_noversion = @{type="nuget";Package="foo"} + + # The test folder exists + Mock Test-Path {return $true} -ParameterFilter { $Path -and $Path -eq $t_installPath } + # Nuget.exe is not there + Mock Test-Path {return $false} -ParameterFilter { $PathType -and $PathType -eq "Leaf" } + Mock New-Item {} + Mock Invoke-WebRequest {} #Nuget download + Mock Invoke-External {} + + ### Nuget Download + + It "does not download nuget on default parameter" { + Install-AutToolset -installPath $t_installPath | + Assert-MockCalled Invoke-WebRequest -Times 0 -Exactly -Scope It + } + + It "does download nuget once for 1 package" { + Install-AutToolset -installPath $t_installPath -packageHash $t_nuget_version | + Assert-MockCalled Invoke-WebRequest -Times 1 -Exactly -Scope It + } + + # Nuget.exe is already there + Mock Test-Path {return $true} -ParameterFilter { $PathType -and $PathType -eq "Leaf" } + It "does not download nuget when needed but already there" { + Install-AutToolset -installPath $t_installPath -packageHash $t_nuget_version | + Assert-MockCalled Invoke-WebRequest -Times 0 -Exactly -Scope It + } + + ### Nuget Invokation + + It "does not invoke nuget on default parameter" { + Install-AutToolset -installPath $t_installPath | + Assert-MockCalled Invoke-External -Times 0 -Exactly -Scope It -ParameterFilter { $LiteralPath -like "$t_installPath\nuget*" } + } + + It "does invoke nuget once for 1 package with version" { + Install-AutToolset -installPath $t_installPath -packageHash $t_nuget_version | + Assert-MockCalled Invoke-External -Times 1 -Exactly -Scope It -ParameterFilter { ($LiteralPath -like "$t_installPath\nuget*") } + } + + It "does invoke nuget once for 1 package with no version" { + Install-AutToolset -installPath $t_installPath -packageHash $t_nuget_noversion | + Assert-MockCalled Invoke-External -Times 1 -Exactly -Scope It -ParameterFilter { ($LiteralPath -like "$t_installPath\nuget*") } + } + } } \ No newline at end of file diff --git a/asa.unittest/private/Install-AutToolset.ps1 b/asa.unittest/private/Install-AutToolset.ps1 index 59a1109..89fcdee 100644 --- a/asa.unittest/private/Install-AutToolset.ps1 +++ b/asa.unittest/private/Install-AutToolset.ps1 @@ -1,6 +1,6 @@ <# .SYNOPSIS -Companion script used to install the dependencies required for the main package +Companion script used to install a nuget package required for the main module In case of issues with PowerShell Execution Policies, see https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scripts?view=powershell-7 PS: VSCode has a weird behavior on that topic, use Terminal : https://github.com/PowerShell/vscode-powershell/issues/1217 @@ -9,23 +9,16 @@ PS: VSCode has a weird behavior on that topic, use Terminal : https://github.com See documentation for more information : https://github.com/Fleid/asa.unittest This script will first download nuget.exe, the Nuget CLI tool for Windows. See https://docs.microsoft.com/en-us/nuget/install-nuget-client-tools#nugetexe-cli -After that nuget.exe will be invoked to install the required packages from nuget. - -Finally the script will invoke npm to install the npm packages. -These packages will be installed globally (npm install -g). -If npm is not available, please download node.js. See https://nodejs.org/en/download/ +After that nuget.exe will be invoked to install the required package from nuget. .PARAMETER installPath Path to the folder in the fixture that will contain the dependencies, usually (solutionPath\asaProjectName.Tests\2_act) -.PARAMETER npmPackages -List of npm packages to install - -.PARAMETER nugetPackages -List of nuget packages to install +.PARAMETER packageHash +Hashtable of the package to install with the format @{type="nuget";package="Microsoft.Azure.StreamAnalytics.CICD";version="3.0.0"} .EXAMPLE -Install-AutToolset -installPath C:\Users\fleide\Repos\asa.unittest\examples\ASAHelloWorld.Tests\2_act -npmpackages jsondiffpatch -nugetpackages Microsoft.Azure.StreamAnalytics.CICD +Install-AutToolset -installPath C:\Users\fleide\Repos\asa.unittest\examples\ASAHelloWorld.Tests\2_act -packageHash @{type="nuget";package="Microsoft.Azure.StreamAnalytics.CICD";version="3.0.0"} #> Function Install-AutToolset{ @@ -33,8 +26,7 @@ Function Install-AutToolset{ [CmdletBinding()] param ( [string]$installPath = $(Throw "-installPath is required"), - [string[]]$npmPackages, # = @("jsondiffpatch"), - [string[]]$nugetPackages # = @("Microsoft.Azure.StreamAnalytics.CICD") + [hashtable]$packageHash # = @{type="nuget";package="Microsoft.Azure.StreamAnalytics.CICD";version="3.0.0"} ) BEGIN { @@ -43,7 +35,7 @@ Function Install-AutToolset{ PROCESS { - if ($nugetPackages.Count -gt 0){ + if ($packageHash.type -eq "nuget"){ if (-not (Test-Path -Path "$installPath\nuget.exe" -PathType Leaf)){ # Windows - get nuget.exe from https://www.nuget.org/downloads @@ -54,23 +46,17 @@ Function Install-AutToolset{ Out-Null } - foreach ($nugetPackage in $nugetPackages){ - Write-Verbose "002 - Installing nuget package : $nugetPackage" - Invoke-External -l "$installPath\nuget.exe" install $nugetPackage -OutputDirectory $installPath | - Out-Null - } - - - - } #IF nuget - - if ($npmPackages.Count -gt 0){ - foreach ($npmPackage in $npmPackages){ - Write-Verbose "003 - Installing npm package : $npmPackage" - Invoke-External -l "npm" install -g $npmPackage | Out-Null + Write-Verbose "002 - Installing nuget package : $($packageHash.package)" + if ($packageHash.version) { + Invoke-External -l "$installPath\nuget.exe" install $packageHash.package -version $packageHash.version -OutputDirectory $installPath | + Out-Null + } + else { + Invoke-External -l "$installPath\nuget.exe" install $packageHash.package -OutputDirectory $installPath | + Out-Null } - } #IF npm + } } # PROCESS END {} From 94e74857f4d2a96b576343e9684440201f85108c Mon Sep 17 00:00:00 2001 From: Florian Eiden Date: Fri, 11 Sep 2020 14:33:58 -0700 Subject: [PATCH 11/18] Update call to import dependency with a version --- asa.unittest.tests/New-AutProject.Tests.ps1 | 236 ++++++++++---------- asa.unittest/Public/New-AutProject.ps1 | 119 +++++----- 2 files changed, 179 insertions(+), 176 deletions(-) diff --git a/asa.unittest.tests/New-AutProject.Tests.ps1 b/asa.unittest.tests/New-AutProject.Tests.ps1 index 94d1661..468bd65 100644 --- a/asa.unittest.tests/New-AutProject.Tests.ps1 +++ b/asa.unittest.tests/New-AutProject.Tests.ps1 @@ -1,118 +1,120 @@ -### If tests are in ModuleRoot\Whatever, and scripts reachable via a module at ModuleRoot\Module\Module.psm1 - -$projectRoot = Resolve-Path "$PSScriptRoot\.." #ModuleRoot\Whatever becomes \ModuleRoot with .. -$moduleRoot = Split-Path (Resolve-Path "$projectRoot\*\*.psd1") #Look for the manifest to get to ModuleRoot\Module -$moduleName = Split-Path $moduleRoot -Leaf #Extract the module name from above -Import-Module (Join-Path $moduleRoot "$moduleName.psm1") -force - -############################################################################################################# -# Invoke-Pester .\New-AutProject.Tests.ps1 -CodeCoverage .\..\asa.unittest\public\New-AutProject.ps1 - -Describe "New-AutProject paramater installPath" { - InModuleScope $moduleName { - - $t_installPath = "foo" - - Mock Test-Path {return $true} - Mock New-Item {} - Mock Install-AutToolset {} - Mock Out-File {} - - It "fails if installPath is missing" { - { New-AutProject } | - Should -throw "-installPath is required" - } - - It "doesn't create a folder if it exists" { - New-AutProject -installPath $t_installPath | - Assert-MockCalled New-Item -Times 0 -Exactly -Scope It -ParameterFilter {$Path -eq $t_installPath} - } - - Mock Test-Path {return $false} -ParameterFilter {$Path -eq $t_installPath} - It "does create a folder it doesn't" { - New-AutProject -installPath $t_installPath | - Assert-MockCalled New-Item -Times 1 -Exactly -Scope It -ParameterFilter {$Path -eq $t_installPath} - } - - } -} - -Describe "New-AutProject behavior folder structure" { - InModuleScope $moduleName { - - $t_installPath = "foo" - - Mock Test-Path {return $true} - Mock New-Item {} - Mock Install-AutToolset {} - Mock Out-File {} - - Mock Test-Path {return $false} -ParameterFilter {$Path -eq "$t_installPath\1_arrange"} - It "does create a folder 1_arrange" { - New-AutProject -installPath $t_installPath | - Assert-MockCalled New-Item -Times 1 -Exactly -Scope It -ParameterFilter {$Path -eq "$t_installPath\1_arrange"} - } - Mock Test-Path {return $true} - - Mock Test-Path {return $false} -ParameterFilter {$Path -eq "$t_installPath\2_act"} - It "does create a folder 2_act" { - New-AutProject -installPath $t_installPath | - Assert-MockCalled New-Item -Times 1 -Exactly -Scope It -ParameterFilter {$Path -eq "$t_installPath\2_act"} - } - Mock Test-Path {return $true} - - Mock Test-Path {return $false} -ParameterFilter {$Path -eq "$t_installPath\3_assert"} - It "does create a folder 3_assert" { - New-AutProject -installPath $t_installPath | - Assert-MockCalled New-Item -Times 1 -Exactly -Scope It -ParameterFilter {$Path -eq "$t_installPath\3_assert"} - } - Mock Test-Path {return $true} - - } -} - -Describe "New-AutProject behavior dependencies" { - InModuleScope $moduleName { - - $t_installPath = "foo" - - Mock Test-Path {return $true} - Mock New-Item {} - Mock Install-AutToolset {} - Mock Out-File {} - - It "calls Install-AutToolset with the right parameters" { - New-AutProject -installPath $t_installPath | - Assert-MockCalled Install-AutToolset -Times 1 -Exactly -Scope It -ParameterFilter { - ($installPath -eq "$t_installPath\2_act") ` - -and ` - ($nugetpackages -eq "Microsoft.Azure.StreamAnalytics.CICD") - } - } - - } -} - -Describe "New-AutProject behavior gitignore" { - InModuleScope $moduleName { - - $t_installPath = "foo" - - Mock Test-Path {return $true} - Mock New-Item {} - Mock Install-AutToolset {} - Mock Out-File {} - - It "doesn't create a gitignore if there's one already" { - New-AutProject -installPath $t_installPath | - Assert-MockCalled Out-File -Times 0 -Exactly -Scope It - } - - Mock Test-Path {return $false} -ParameterFilter {$Path -eq "$t_installPath\.gitignore"} - It "does create a gitignore if there's none" { - New-AutProject -installPath $t_installPath | - Assert-MockCalled Out-File -Times 1 -Exactly -Scope It - } - - } +### If tests are in ModuleRoot\Whatever, and scripts reachable via a module at ModuleRoot\Module\Module.psm1 + +$projectRoot = Resolve-Path "$PSScriptRoot\.." #ModuleRoot\Whatever becomes \ModuleRoot with .. +$moduleRoot = Split-Path (Resolve-Path "$projectRoot\*\*.psd1") #Look for the manifest to get to ModuleRoot\Module +$moduleName = Split-Path $moduleRoot -Leaf #Extract the module name from above +Import-Module (Join-Path $moduleRoot "$moduleName.psm1") -force + +############################################################################################################# +# Invoke-Pester .\New-AutProject.Tests.ps1 -CodeCoverage .\..\asa.unittest\public\New-AutProject.ps1 + +Describe "New-AutProject paramater installPath" { + InModuleScope $moduleName { + + $t_installPath = "foo" + + Mock Test-Path {return $true} + Mock New-Item {} + Mock Install-AutToolset {} + Mock Out-File {} + + It "fails if installPath is missing" { + { New-AutProject } | + Should -throw "-installPath is required" + } + + It "doesn't create a folder if it exists" { + New-AutProject -installPath $t_installPath | + Assert-MockCalled New-Item -Times 0 -Exactly -Scope It -ParameterFilter {$Path -eq $t_installPath} + } + + Mock Test-Path {return $false} -ParameterFilter {$Path -eq $t_installPath} + It "does create a folder it doesn't" { + New-AutProject -installPath $t_installPath | + Assert-MockCalled New-Item -Times 1 -Exactly -Scope It -ParameterFilter {$Path -eq $t_installPath} + } + + } +} + +Describe "New-AutProject behavior folder structure" { + InModuleScope $moduleName { + + $t_installPath = "foo" + + Mock Test-Path {return $true} + Mock New-Item {} + Mock Install-AutToolset {} + Mock Out-File {} + + Mock Test-Path {return $false} -ParameterFilter {$Path -eq "$t_installPath\1_arrange"} + It "does create a folder 1_arrange" { + New-AutProject -installPath $t_installPath | + Assert-MockCalled New-Item -Times 1 -Exactly -Scope It -ParameterFilter {$Path -eq "$t_installPath\1_arrange"} + } + Mock Test-Path {return $true} + + Mock Test-Path {return $false} -ParameterFilter {$Path -eq "$t_installPath\2_act"} + It "does create a folder 2_act" { + New-AutProject -installPath $t_installPath | + Assert-MockCalled New-Item -Times 1 -Exactly -Scope It -ParameterFilter {$Path -eq "$t_installPath\2_act"} + } + Mock Test-Path {return $true} + + Mock Test-Path {return $false} -ParameterFilter {$Path -eq "$t_installPath\3_assert"} + It "does create a folder 3_assert" { + New-AutProject -installPath $t_installPath | + Assert-MockCalled New-Item -Times 1 -Exactly -Scope It -ParameterFilter {$Path -eq "$t_installPath\3_assert"} + } + Mock Test-Path {return $true} + + } +} + +Describe "New-AutProject behavior dependencies" { + InModuleScope $moduleName { + + $t_installPath = "foo" + + Mock Test-Path {return $true} + Mock New-Item {} + Mock Install-AutToolset {} + Mock Out-File {} + + It "calls Install-AutToolset with the right parameters" { + New-AutProject -installPath $t_installPath | + Assert-MockCalled Install-AutToolset -Times 1 -Exactly -Scope It -ParameterFilter { + ($installPath -eq "$t_installPath\2_act") ` + -and ` + ($packageHash.package -eq "Microsoft.Azure.StreamAnalytics.CICD") ` + -and ` + ($packageHash.type -eq "nuget") + } + } + + } +} + +Describe "New-AutProject behavior gitignore" { + InModuleScope $moduleName { + + $t_installPath = "foo" + + Mock Test-Path {return $true} + Mock New-Item {} + Mock Install-AutToolset {} + Mock Out-File {} + + It "doesn't create a gitignore if there's one already" { + New-AutProject -installPath $t_installPath | + Assert-MockCalled Out-File -Times 0 -Exactly -Scope It + } + + Mock Test-Path {return $false} -ParameterFilter {$Path -eq "$t_installPath\.gitignore"} + It "does create a gitignore if there's none" { + New-AutProject -installPath $t_installPath | + Assert-MockCalled Out-File -Times 1 -Exactly -Scope It + } + + } } \ No newline at end of file diff --git a/asa.unittest/Public/New-AutProject.ps1 b/asa.unittest/Public/New-AutProject.ps1 index e1a0d99..cede193 100644 --- a/asa.unittest/Public/New-AutProject.ps1 +++ b/asa.unittest/Public/New-AutProject.ps1 @@ -1,59 +1,60 @@ -<# -.SYNOPSIS -Companion script used to initialize an Azure Stream Analytics - Unit Testing test project - -In case of issues with PowerShell Execution Policies, see https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scripts?view=powershell-7 -PS: VSCode has a weird behavior on that topic, use Terminal : https://github.com/PowerShell/vscode-powershell/issues/1217 - -.DESCRIPTION -See documentation for more information : https://github.com/Fleid/asa.unittest - -This script will create the required folder fixture, download the dependencies and add a gitignore file to protect against repo sprawl - -.PARAMETER installPath -Path to the folder in the fixture that will contain the dependencies, usually (solutionPath\asaProjectName.Tests\2_act) - -.EXAMPLE -Create-AutToolset -installPath C:\Users\fleide\Repos\asa.unittest\examples\ASAHelloWorld.Tests\ -#> - -Function New-AutProject{ - - [CmdletBinding( - SupportsShouldProcess=$true, - ConfirmImpact="Low" - )] - param ( - [string]$installPath = $(Throw "-installPath is required") - ) - - BEGIN { - if (-not (Test-Path $installPath)) {New-Item -ItemType Directory -Path $installPath | Out-Null} - } - - PROCESS { - if ($pscmdlet.ShouldProcess("Creating a new AUT project at $installPath")) - { - # Create folder structure - if (-not (Test-Path "$installPath\1_arrange")) {New-Item -ItemType Directory -Path "$installPath\1_arrange" | Out-Null} - if (-not (Test-Path "$installPath\2_act")) {New-Item -ItemType Directory -Path "$installPath\2_act" | Out-Null} - if (-not (Test-Path "$installPath\3_assert")) {New-Item -ItemType Directory -Path "$installPath\3_assert" | Out-Null} - - # Install dependencies - Install-AutToolset -installPath "$installPath\2_act" -nugetpackages Microsoft.Azure.StreamAnalytics.CICD - - $gitIgnoreContent = ` -" -# testing dependencies -2_act/nuget.exe -2_act/Microsoft.Azure.StreamAnalytics.CICD.*/ - -# local test results -3_assert/* -" - if (-not (Test-Path "$installPath\.gitignore" -PathType Leaf)) {$gitIgnoreContent | Out-File "$installPath\.gitignore"} - - } # SHOULD - } # PROCESS - END {} -} +<# +.SYNOPSIS +Companion script used to initialize an Azure Stream Analytics - Unit Testing test project + +In case of issues with PowerShell Execution Policies, see https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scripts?view=powershell-7 +PS: VSCode has a weird behavior on that topic, use Terminal : https://github.com/PowerShell/vscode-powershell/issues/1217 + +.DESCRIPTION +See documentation for more information : https://github.com/Fleid/asa.unittest + +This script will create the required folder fixture, download the dependencies and add a gitignore file to protect against repo sprawl + +.PARAMETER installPath +Path to the folder in the fixture that will contain the dependencies, usually (solutionPath\asaProjectName.Tests\2_act) + +.EXAMPLE +Create-AutToolset -installPath C:\Users\fleide\Repos\asa.unittest\examples\ASAHelloWorld.Tests\ +#> + +Function New-AutProject{ + + [CmdletBinding( + SupportsShouldProcess=$true, + ConfirmImpact="Low" + )] + param ( + [string]$installPath = $(Throw "-installPath is required"), + [string]$ASAnugetVersion="3.0.0" + ) + + BEGIN { + if (-not (Test-Path $installPath)) {New-Item -ItemType Directory -Path $installPath | Out-Null} + } + + PROCESS { + if ($pscmdlet.ShouldProcess("Creating a new AUT project at $installPath")) + { + # Create folder structure + if (-not (Test-Path "$installPath\1_arrange")) {New-Item -ItemType Directory -Path "$installPath\1_arrange" | Out-Null} + if (-not (Test-Path "$installPath\2_act")) {New-Item -ItemType Directory -Path "$installPath\2_act" | Out-Null} + if (-not (Test-Path "$installPath\3_assert")) {New-Item -ItemType Directory -Path "$installPath\3_assert" | Out-Null} + + # Install dependencies + Install-AutToolset -installPath "$installPath\2_act" -packageHash @{type="nuget";package="Microsoft.Azure.StreamAnalytics.CICD";version=$ASAnugetVersion} + + $gitIgnoreContent = ` +" +# testing dependencies +2_act/nuget.exe +2_act/Microsoft.Azure.StreamAnalytics.CICD.*/ + +# local test results +3_assert/* +" + if (-not (Test-Path "$installPath\.gitignore" -PathType Leaf)) {$gitIgnoreContent | Out-File "$installPath\.gitignore"} + + } # SHOULD + } # PROCESS + END {} +} From ad7a8cecf0415a672074cdc47da1ea7956028d33 Mon Sep 17 00:00:00 2001 From: Florian Eiden Date: Tue, 15 Sep 2020 12:47:44 -0700 Subject: [PATCH 12/18] Hotfix - undesired output in the pipeline --- asa.unittest/private/New-AutRunFixture.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/asa.unittest/private/New-AutRunFixture.ps1 b/asa.unittest/private/New-AutRunFixture.ps1 index f64d8c1..9b1f47d 100644 --- a/asa.unittest/private/New-AutRunFixture.ps1 +++ b/asa.unittest/private/New-AutRunFixture.ps1 @@ -131,7 +131,8 @@ Function New-AutRunFixture{ if (-not (Test-Path("$asaProjectPath\$asaProjectName.asaql.cs"))) { $testFolders | Select-Object @{Name = "Path"; Expression = {"$($_.Path)\$asaProjectName\"}} | - New-Item -Name "$asaProjectName.asaql.cs" -ItemType file + New-Item -Name "$asaProjectName.asaql.cs" -ItemType file | + Out-Null } ################################################################################################################################ From 309725dca81ad5777d51730ea42150898e198d7f Mon Sep 17 00:00:00 2001 From: Florian Eiden Date: Tue, 15 Sep 2020 12:48:11 -0700 Subject: [PATCH 13/18] Update for 3.0.0 --- README_DEV.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_DEV.md b/README_DEV.md index cc82403..410c1e4 100644 --- a/README_DEV.md +++ b/README_DEV.md @@ -69,7 +69,7 @@ $asaProjectName = "ASAHelloWorld" $unittestFolder = "ASAHelloWorld.Tests" $testID = (Get-Date -Format "yyyyMMddHHmmss") -$exePath = "C:\Users\fleide\Repos\asa.unittest\examples\ASAHelloWorld.Tests\2_act\Microsoft.Azure.StreamAnalytics.CICD.2.4.0\tools\sa.exe" +$exePath = "C:\Users\fleide\Repos\asa.unittest\examples\ASAHelloWorld.Tests\2_act\Microsoft.Azure.StreamAnalytics.CICD.3.0.0\tools\sa.exe" ``` ## Testing From 30d1d68b405a3a142b723e26276724a6936a7663 Mon Sep 17 00:00:00 2001 From: Florian Eiden Date: Tue, 15 Sep 2020 12:52:17 -0700 Subject: [PATCH 14/18] Update parsing to support 3.0.0 format --- asa.unittest/private/Get-AutRunResult.ps1 | 234 +++++++++++----------- 1 file changed, 118 insertions(+), 116 deletions(-) diff --git a/asa.unittest/private/Get-AutRunResult.ps1 b/asa.unittest/private/Get-AutRunResult.ps1 index 8b8da5b..ac8ff4d 100644 --- a/asa.unittest/private/Get-AutRunResult.ps1 +++ b/asa.unittest/private/Get-AutRunResult.ps1 @@ -1,117 +1,119 @@ -<# -.SYNOPSIS -Controller script used to generate results of a test run - -.DESCRIPTION -See documentation for more information : https://github.com/Fleid/asa.unittest - -.PARAMETER solutionPath -Path to the solution (folder) containing both the Azure Stream Analytics folder and the unittest folder - -.PARAMETER asaProjectName -Name of the Azure Stream Analytics project = name of the project folder = name of the query in that folder (.asaql) = name of the project description file (.asaproj) - -.PARAMETER unittestFolder -Name of the folder containing the test fixture (folders 1_arrange, 2_act, 3_assert), usually "asaProjectName.Tests" - -.PARAMETER testId -Timestamp of the test run (yyyyMMddHHmmss), will be used in the folder structure - -.PARAMETER testCase -Current test to be run (001, 002, 003...) - -.EXAMPLE -Get-AutRunResult -solutionPath $solutionPath -asaProjectName $asaProjectName -unittestFolder $unittestFolder -testID $testID -testCase $testCase -#> - -Function Get-AutRunResult{ - - [CmdletBinding()] - [OutputType([int])] - param ( - [string]$solutionPath = $(Throw "-solutionPath is required"), - [string]$asaProjectName = $(Throw "-asaProjectName is required"), - [string]$unittestFolder = $(Throw "-unittestFolder is required"), - [string]$testID = $(Throw "-testID is required"), - [string]$testCase = $(Throw "-testCase is required") - ) - - BEGIN { - if (-not (Test-Path($solutionPath))) {throw "$solutionPath is not a valid path"} - - $testPath = "$solutionPath\$unittestFolder\3_assert\$testID\$testCase" - if (-not (Test-Path($testPath))) {throw "$testPath is not a valid path"} - - $outputSourcePath = "$testPath\$asaProjectName\Inputs" - if (-not (Test-Path($outputSourcePath))) {throw "$outputSourcePath is not a valid path"} - } - - PROCESS { - $errorCounter = 0 - - $testDetails = (Get-ChildItem -Path $outputSourcePath -File) | - Get-AutFieldFromFileInfo -s "~" -n 4 | - Select-Object ` - FullName, ` - FilePath, ` - Basename, ` - @{Name = "TestCase"; Expression = {$_.Basename0}}, ` - @{Name = "FileType"; Expression = {$_.Basename1}}, ` - @{Name = "SourceName"; Expression = {$_.Basename2}}, ` - @{Name = "TestLabel"; Expression = {$_.Basename3}} - - $testDetails | Where-Object { $_.FileType -eq "Output" } | - Select-Object ` - FullName, - SourceName, - TestCase, - @{Name = "rawContent"; Expression = {"$testPath\$($_.SourceName).json"}}, #sa.exe output - @{Name = "testableFilePath"; Expression = {"$testPath\$($_.SourceName).testable.json"}}, #to be generated - @{Name = "sortedTestCaseOutputFilePath"; Expression = {"$testPath\$($_.Basename).sorted.json"}}, #to be generated - @{Name = "testCaseOutputFile"; Expression = {"$testPath\$asaProjectName\Inputs\$($_.FullName)"}} | - Foreach-Object -process { - - # Prepare input content (sorting) - $referenceContent = Get-Content -Path $_.testCaseOutputFile | ConvertFrom-Json - - $referenceContentProperties = ` - $referenceContent | ` - Get-Member -MemberType NoteProperty | ` - Sort-Object -Property Name | ` - Select-Object -ExpandProperty Name - - $referenceSortedContent = $referenceContent | Sort-Object -Property $referenceContentProperties | ConvertTo-JSON - - Add-Content -Path $_.sortedTestCaseOutputFilePath -Value $referenceSortedContent - - # Prepare output content (format, sorting) - $testableContent = ("[$(Get-Content -Path $_.rawContent)]") | ConvertFrom-Json - - $testableContentProperties = ` - $testableContent | ` - Get-Member -MemberType NoteProperty | ` - Sort-Object -Property Name | ` - Select-Object -ExpandProperty Name - - $testableSortedContent = $testableContent | Sort-Object -Property $testableContentProperties | ConvertTo-JSON - - Add-Content -Path $_.testableFilePath -Value $testableSortedContent - - # Actual testing - $left = Get-Content $_.sortedTestCaseOutputFilePath - $right = Get-Content $_.testableFilePath - $testResult = Compare-Object $left $right - - if ($testResult) { - $testResult | Out-File "$testPath\$($_.SourceName).Result.txt" - Write-Verbose ">> Errors on test $($_.TestCase)\$($_.SourceName):" - $testResult | Foreach-Object {Write-Verbose "$($_.SideIndicator) $($_.InputObject)"} - $errorCounter++ - } - } - - $errorCounter - - } #PROCESS - END {} +<# +.SYNOPSIS +Controller script used to generate results of a test run + +.DESCRIPTION +See documentation for more information : https://github.com/Fleid/asa.unittest + +.PARAMETER solutionPath +Path to the solution (folder) containing both the Azure Stream Analytics folder and the unittest folder + +.PARAMETER asaProjectName +Name of the Azure Stream Analytics project = name of the project folder = name of the query in that folder (.asaql) = name of the project description file (.asaproj) + +.PARAMETER unittestFolder +Name of the folder containing the test fixture (folders 1_arrange, 2_act, 3_assert), usually "asaProjectName.Tests" + +.PARAMETER testId +Timestamp of the test run (yyyyMMddHHmmss), will be used in the folder structure + +.PARAMETER testCase +Current test to be run (001, 002, 003...) + +.EXAMPLE +Get-AutRunResult -solutionPath $solutionPath -asaProjectName $asaProjectName -unittestFolder $unittestFolder -testID $testID -testCase $testCase +#> + +Function Get-AutRunResult{ + + [CmdletBinding()] + [OutputType([int])] + param ( + [string]$solutionPath = $(Throw "-solutionPath is required"), + [string]$asaProjectName = $(Throw "-asaProjectName is required"), + [string]$unittestFolder = $(Throw "-unittestFolder is required"), + [string]$testID = $(Throw "-testID is required"), + [string]$testCase = $(Throw "-testCase is required") + ) + + BEGIN { + if (-not (Test-Path($solutionPath))) {throw "$solutionPath is not a valid path"} + + $testPath = "$solutionPath\$unittestFolder\3_assert\$testID\$testCase" + if (-not (Test-Path($testPath))) {throw "$testPath is not a valid path"} + + $outputSourcePath = "$testPath\$asaProjectName\Inputs" + if (-not (Test-Path($outputSourcePath))) {throw "$outputSourcePath is not a valid path"} + } + + PROCESS { + $errorCounter = 0 + + $testDetails = (Get-ChildItem -Path $outputSourcePath -File) | + Get-AutFieldFromFileInfo -s "~" -n 4 | + Select-Object ` + FullName, ` + FilePath, ` + Basename, ` + @{Name = "TestCase"; Expression = {$_.Basename0}}, ` + @{Name = "FileType"; Expression = {$_.Basename1}}, ` + @{Name = "SourceName"; Expression = {$_.Basename2}}, ` + @{Name = "TestLabel"; Expression = {$_.Basename3}} + + $testDetails | Where-Object { $_.FileType -eq "Output" } | + Select-Object ` + FullName, + SourceName, + TestCase, + @{Name = "rawContent"; Expression = {"$testPath\$($_.SourceName).json"}}, #sa.exe output + @{Name = "testableFilePath"; Expression = {"$testPath\$($_.SourceName).testable.json"}}, #to be generated + @{Name = "sortedTestCaseOutputFilePath"; Expression = {"$testPath\$($_.Basename).sorted.json"}}, #to be generated + @{Name = "testCaseOutputFile"; Expression = {"$testPath\$asaProjectName\Inputs\$($_.FullName)"}} | + Foreach-Object -process { + + # Prepare input content (sorting) + $referenceContent = Get-Content -Path $_.testCaseOutputFile | ConvertFrom-Json + + $referenceContentProperties = ` + $referenceContent | ` + Get-Member -MemberType NoteProperty | ` + Sort-Object -Property Name | ` + Select-Object -ExpandProperty Name + + $referenceSortedContent = $referenceContent | Sort-Object -Property $referenceContentProperties | ConvertTo-JSON + + Add-Content -Path $_.sortedTestCaseOutputFilePath -Value $referenceSortedContent + + # Prepare output content (format, sorting) + # $testableContent = ("[$(Get-Content -Path $_.rawContent)]") | ConvertFrom-Json + # New format after CICD 3.0.0 + $testableContent = ("[$(Get-Content -Path $_.rawContent)]").split(" ").replace("[","").replace("]","") | ConvertFrom-Json + + $testableContentProperties = ` + $testableContent | ` + Get-Member -MemberType NoteProperty | ` + Sort-Object -Property Name | ` + Select-Object -ExpandProperty Name + + $testableSortedContent = $testableContent | Sort-Object -Property $testableContentProperties | ConvertTo-JSON + + Add-Content -Path $_.testableFilePath -Value $testableSortedContent + + # Actual testing + $left = Get-Content $_.sortedTestCaseOutputFilePath + $right = Get-Content $_.testableFilePath + $testResult = Compare-Object $left $right + + if ($testResult) { + $testResult | Out-File "$testPath\$($_.SourceName).Result.txt" + Write-Verbose ">> Errors on test $($_.TestCase)\$($_.SourceName):" + $testResult | Foreach-Object {Write-Verbose "$($_.SideIndicator) $($_.InputObject)"} + $errorCounter++ + } + } + + $errorCounter + + } #PROCESS + END {} } \ No newline at end of file From a1fe0027a8502773eb5f7a66413b15c077dcef1f Mon Sep 17 00:00:00 2001 From: Florian Eiden Date: Tue, 15 Sep 2020 13:11:04 -0700 Subject: [PATCH 15/18] Update manifest to 1.0.11 --- asa.unittest/asa.unittest.psd1 | Bin 8946 -> 8976 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/asa.unittest/asa.unittest.psd1 b/asa.unittest/asa.unittest.psd1 index f5f2db3443a48fbd9745340e0e7fce3370153be5..61afaa1e42f013b1a6752df2376cad507ec8cc5d 100644 GIT binary patch delta 113 zcmez5I>Bv&9uuSCW__lEvYMt03Jg|29Li9@kiwA2P{NQ3(DL~a_K)ML1Cle@|$DlcxQC4_!lEMTg09CUV A{r~^~ delta 83 zcmbQ>_Q`dF9uuR%W__lEvg!s53Jg|2?7@)FP{NSLkjYTNpabM*FeEY*F{Cgg1I1Gq gQYT9)X!4f;*$NCs40;SEKx{afQC4_!gTe$R00|-yO#lD@ From c70af117e8fb1f7abbd3fd985a121f095796035d Mon Sep 17 00:00:00 2001 From: Florian Eiden Date: Tue, 15 Sep 2020 13:26:43 -0700 Subject: [PATCH 16/18] Fix syntax to properly parse CRLF --- asa.unittest/private/Get-AutRunResult.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asa.unittest/private/Get-AutRunResult.ps1 b/asa.unittest/private/Get-AutRunResult.ps1 index ac8ff4d..5e2fbca 100644 --- a/asa.unittest/private/Get-AutRunResult.ps1 +++ b/asa.unittest/private/Get-AutRunResult.ps1 @@ -87,7 +87,7 @@ Function Get-AutRunResult{ # Prepare output content (format, sorting) # $testableContent = ("[$(Get-Content -Path $_.rawContent)]") | ConvertFrom-Json # New format after CICD 3.0.0 - $testableContent = ("[$(Get-Content -Path $_.rawContent)]").split(" ").replace("[","").replace("]","") | ConvertFrom-Json + $testableContent = [IO.File]::ReadAllText($_.rawContent).split("`n") | ConvertFrom-Json $testableContentProperties = ` $testableContent | ` From 026cf849db0912f2036d6e5537233b25cb4a9257 Mon Sep 17 00:00:00 2001 From: Florian Eiden Date: Tue, 15 Sep 2020 15:24:44 -0700 Subject: [PATCH 17/18] Restore support for asaNugetVersion --- asa.unittest.tests/Get-AutRunResult.Tests.ps1 | 707 ++++++++++-------- asa.unittest/Public/Start-AutRun.ps1 | 293 ++++---- .../private/Get-AutFieldFromFileInfo.ps1 | 92 +-- asa.unittest/private/Get-AutRunResult.ps1 | 16 +- asa.unittest/private/Invoke-ReadAllText.ps1 | 33 + 5 files changed, 621 insertions(+), 520 deletions(-) create mode 100644 asa.unittest/private/Invoke-ReadAllText.ps1 diff --git a/asa.unittest.tests/Get-AutRunResult.Tests.ps1 b/asa.unittest.tests/Get-AutRunResult.Tests.ps1 index b54e8d5..25fdea1 100644 --- a/asa.unittest.tests/Get-AutRunResult.Tests.ps1 +++ b/asa.unittest.tests/Get-AutRunResult.Tests.ps1 @@ -1,324 +1,383 @@ -### If tests are in ModuleRoot\Whatever, and scripts reachable via a module at ModuleRoot\Module\Module.psm1 - -$projectRoot = Resolve-Path "$PSScriptRoot\.." #ModuleRoot\Whatever becomes \ModuleRoot with .. -$moduleRoot = Split-Path (Resolve-Path "$projectRoot\*\*.psd1") #Look for the manifest to get to ModuleRoot\Module -$moduleName = Split-Path $moduleRoot -Leaf #Extract the module name from above -Import-Module (Join-Path $moduleRoot "$moduleName.psm1") -force - -############################################################################################################# -# Invoke-Pester .\Get-AutRunResult.Tests.ps1 -CodeCoverage .\..\asa.unittest\private\Get-AutRunResult.ps1 - - -Describe "Get-AutRunResult Nominal" { - InModuleScope $moduleName { - - $t_solutionPath = "TestDrive:\foo" - $t_asaProjectName = "bar" - $t_unittestFolder = "bar.Tests" - $t_testID = "yyyymmddhhmmss" - $t_testCase = "123" - - Mock Test-Path {return $true} - Mock Get-ChildItem {return 1} - Mock Get-AutFieldFromFileInfo {} - Mock Get-Content {return (@{FilePath="foobar"} | ConvertTo-Json)} - Mock Add-Content {} - Mock Compare-Object {} - Mock Out-File {} - - It "tries to get a list of files" { - Get-AutRunResult ` - -solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - -testID $t_testID ` - -testCase $t_testCase | Out-Null - - Assert-MockCalled Get-ChildItem -Times 1 -Exactly -Scope It - } - - Mock Get-AutFieldFromFileInfo {} - It "tries nothing if it gets nothing" { - Get-AutRunResult ` - -solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - -testID $t_testID ` - -testCase $t_testCase | Out-Null - - Assert-MockCalled Out-File -Times 0 -Exactly -Scope It - } - - Mock Get-ChildItem {return 1} - It "calls Get-AutFieldFromFileInfo if it find files" { - Get-AutRunResult ` - -solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - -testID $t_testID ` - -testCase $t_testCase | Out-Null - - Assert-MockCalled Get-AutFieldFromFileInfo -Times 1 -Exactly -Scope It - } - - Mock Get-AutFieldFromFileInfo {return @(` - @{Basename0="003";FilePath="foobar";Basename1="Output";Basename2="fb3"},` - @{Basename0="001";FilePath="foobar1";Basename1="Output";Basename2="fb11"},` - @{Basename0="001";FilePath="foobar2";Basename1="Output";Basename2="fb12"},` - @{Basename0="002";FilePath="foobar";Basename1="Output";Basename2="fb2"}` - )} - It "Generates N testable files for N output files" { - Get-AutRunResult ` - -solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - -testID $t_testID ` - -testCase $t_testCase | Out-Null - - Assert-MockCalled Get-Content -Times 16 -Exactly -Scope It #4 for ref, 4 for output times 2 - Assert-MockCalled Add-Content -Times 8 -Exactly -Scope It #4 for ref, 4 for output times 2 - } - - Mock Get-AutFieldFromFileInfo {return @(` - @{Basename0="003";FilePath="foobar";Basename1="Output";Basename2="fb3"},` - @{Basename0="001";FilePath="foobar1";Basename1="Output";Basename2="fb11"},` - @{Basename0="001";FilePath="foobar2";Basename1="Output";Basename2="fb12"},` - @{Basename0="002";FilePath="foobar";Basename1="Output";Basename2="fb2"}` - )} - Mock Compare-Object {return $null} - It "Tests and generates 0 result files for N correct tests" { - Get-AutRunResult ` - -solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - -testID $t_testID ` - -testCase $t_testCase | Out-Null - - Assert-MockCalled Compare-Object -Times 4 -Exactly -Scope It - Assert-MockCalled Out-File -Times 0 -Exactly -Scope It - } - - Mock Get-AutFieldFromFileInfo {return @(` - @{Basename0="003";FilePath="foobar";Basename1="Output";Basename2="fb3"},` - @{Basename0="001";FilePath="foobar1";Basename1="Output";Basename2="fb11"},` - @{Basename0="001";FilePath="foobar2";Basename1="Output";Basename2="fb12"},` - @{Basename0="002";FilePath="foobar";Basename1="Output";Basename2="fb2"}` - )} - Mock Compare-Object {return "ERROR"} - It "Tests and generates 4 result files for N correct tests" { - Get-AutRunResult ` - -solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - -testID $t_testID ` - -testCase $t_testCase | Out-Null - - Assert-MockCalled Compare-Object -Times 4 -Exactly -Scope It - Assert-MockCalled Out-File -Times 4 -Exactly -Scope It - } - - Mock Get-AutFieldFromFileInfo {return @(` - @{Basename0="003";FilePath="foobar";Basename1="Output";Basename2="fb3"},` - @{Basename0="001";FilePath="foobar1";Basename1="Output";Basename2="fb11"},` - @{Basename0="001";FilePath="foobar2";Basename1="Output";Basename2="fb12"},` - @{Basename0="001";FilePath="foobar3";Basename1="Output";Basename2="fb13"},` - @{Basename0="002";FilePath="foobar";Basename1="Output";Basename2="fb2"}` - )} - Mock Compare-Object {return "a"} - It "returns N for N errors" { - Get-AutRunResult ` - -solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - -testID $t_testID ` - -testCase $t_testCase | - Should -be 5 - } - } -} - -Describe "Get-AutRunResult empty folders" { - InModuleScope $moduleName { - - $t_solutionPath = "TestDrive:\foo" - $t_asaProjectName = "bar" - $t_unittestFolder = "bar.Tests" - $t_testID = "yyyymmddhhmmss" - $t_testCase = "123" - - Mock Test-Path {return $true} - Mock Get-ChildItem {} - Mock Get-AutFieldFromFileInfo {} - Mock Get-Content {} - Mock Add-Content {} - Mock Compare-Object {} - Mock Out-File {} - - It "provides 0 error in output pipeline on an empty folder" { - Get-AutRunResult ` - -solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - -testID $t_testID ` - -testCase $t_testCase | - Should -be 0 - } - - It "generates no file on an empty folder" { - Get-AutRunResult ` - -solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - -testID $t_testID ` - -testCase $t_testCase | Out-Null - - Assert-MockCalled Out-File -Times 0 -Exactly -Scope It - } - } -} - - -Describe "Get-AutRunResult parameters" { - InModuleScope $moduleName { - - $t_solutionPath = "TestDrive:\foo" - $t_asaProjectName = "bar" - $t_unittestFolder = "bar.Tests" - $t_testID = "yyyymmddhhmmss" - $t_testCase = "123" - - Mock Test-Path {return $true} - Mock Get-ChildItem {return 1} - Mock Get-AutFieldFromFileInfo {} - Mock Get-Content {return (@{FilePath="foobar"} | ConvertTo-Json)} - Mock Add-Content {} - Mock Compare-Object {} - Mock Out-File {} - - It "runs with a valid set of parameters" { - { Get-AutRunResult ` - -solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - -testID $t_testID ` - -testCase $t_testCase } | - Should -not -throw "-* is required" - } - - It "fails without -solutionPath" { - { Get-AutRunResult ` - #-solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - -testID $t_testID ` - -testCase $t_testCase } | - Should -throw "-solutionPath is required" - } - - It "fails without -asaProjectName" { - { Get-AutRunResult ` - -solutionPath $t_solutionPath ` - #-asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - -testID $t_testID ` - -testCase $t_testCase } | - Should -throw "-asaProjectName is required" - } - - It "fails without -unittestFolder" { - { Get-AutRunResult ` - -solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - #-unittestFolder $t_unittestFolder ` - -testID $t_testID ` - -testCase $t_testCase } | - Should -throw "-unittestFolder is required" - } - - It "fails without -testID" { - { Get-AutRunResult ` - -solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - #-testID $t_testID ` - -testCase $t_testCase } | - Should -throw "-testID is required" - } - - It "fails without -testCase" { - { Get-AutRunResult ` - -solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - -testID $t_testID ` - #-testCase $t_testCase - } | - Should -throw "-testCase is required" - } - } -} - -Describe "Get-AutRunResult paths" { - InModuleScope $moduleName { - - $t_solutionPath = "TestDrive:\foo" - $t_asaProjectName = "bar" - $t_unittestFolder = "bar.Tests" - $t_testID = "yyyymmddhhmmss" - $t_testCase = "123" - - Mock Test-Path {return $true} - Mock Get-ChildItem {return 1} - Mock Get-AutFieldFromFileInfo {} - Mock Get-Content {return (@{FilePath="foobar"} | ConvertTo-Json)} - Mock Add-Content {} - Mock Compare-Object {} - Mock Out-File {} - - Mock Test-Path {return $true} - It "runs with a valid set of paths" { - { Get-AutRunResult ` - -solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - -testID $t_testID ` - -testCase $t_testCase } | - Should -not -throw - } - - Mock Test-Path {return $false} - It "fails when solutionPath is not a valid path" { - { Get-AutRunResult ` - -solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - -testID $t_testID ` - -testCase $t_testCase } | - Should -throw "$t_solutionPath is not a valid path" - } - - $t_testPath = "$t_solutionPath\$t_unittestFolder\3_assert\$t_testID\$t_testCase" - Mock Test-Path {return $true} -ParameterFilter {$path -eq $t_solutionPath} - It "fails when testPath is not a valid path" { - { Get-AutRunResult ` - -solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - -testID $t_testID ` - -testCase $t_testCase } | - Should -throw "$t_testPath is not a valid path" - } - - $t_outputSourcePath = "$t_testPath\$t_asaProjectName\Inputs" - Mock Test-Path {return $true} -ParameterFilter {$path -eq $t_testPath} - It "fails when outputSourcePath is not a valid path" { - { Get-AutRunResult ` - -solutionPath $t_solutionPath ` - -asaProjectName $t_asaProjectName ` - -unittestFolder $t_unittestFolder ` - -testID $t_testID ` - -testCase $t_testCase } | - Should -throw "$t_outputSourcePath is not a valid path" - } - } -} +### If tests are in ModuleRoot\Whatever, and scripts reachable via a module at ModuleRoot\Module\Module.psm1 + +$projectRoot = Resolve-Path "$PSScriptRoot\.." #ModuleRoot\Whatever becomes \ModuleRoot with .. +$moduleRoot = Split-Path (Resolve-Path "$projectRoot\*\*.psd1") #Look for the manifest to get to ModuleRoot\Module +$moduleName = Split-Path $moduleRoot -Leaf #Extract the module name from above +Import-Module (Join-Path $moduleRoot "$moduleName.psm1") -force + +############################################################################################################# +# Invoke-Pester .\Get-AutRunResult.Tests.ps1 -CodeCoverage .\..\asa.unittest\private\Get-AutRunResult.ps1 + + +Describe "Get-AutRunResult Nominal" { + InModuleScope $moduleName { + + $t_solutionPath = "TestDrive:\foo" + $t_asaProjectName = "bar" + $t_unittestFolder = "bar.Tests" + $t_testID = "yyyymmddhhmmss" + $t_testCase = "123" + $t_asaNugetVersion = "3.0.0" + + Mock Test-Path {return $true} + Mock Get-ChildItem {return 1} + Mock Get-AutFieldFromFileInfo {} + Mock Get-Content {return (@{FilePath="foobar"} | ConvertTo-Json)} + Mock Add-Content {} + Mock Compare-Object {} + Mock Out-File {} + Mock Invoke-ReadAllText {return (@{FilePath="foobar"} | ConvertTo-Json)} + + It "tries to get a list of files" { + Get-AutRunResult ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID ` + -testCase $t_testCase ` + -asaNugetVersion $t_asaNugetVersion | Out-Null + + Assert-MockCalled Get-ChildItem -Times 1 -Exactly -Scope It + } + + Mock Get-AutFieldFromFileInfo {} + It "tries nothing if it gets nothing" { + Get-AutRunResult ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID ` + -testCase $t_testCase ` + -asaNugetVersion $t_asaNugetVersion | Out-Null + + Assert-MockCalled Out-File -Times 0 -Exactly -Scope It + } + + Mock Get-ChildItem {return 1} + It "calls Get-AutFieldFromFileInfo if it find files" { + Get-AutRunResult ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID ` + -testCase $t_testCase ` + -asaNugetVersion $t_asaNugetVersion | Out-Null + + Assert-MockCalled Get-AutFieldFromFileInfo -Times 1 -Exactly -Scope It + } + + Mock Get-AutFieldFromFileInfo {return @(` + @{Basename0="003";FilePath="foobar";Basename1="Output";Basename2="fb3"},` + @{Basename0="001";FilePath="foobar1";Basename1="Output";Basename2="fb11"},` + @{Basename0="001";FilePath="foobar2";Basename1="Output";Basename2="fb12"},` + @{Basename0="002";FilePath="foobar";Basename1="Output";Basename2="fb2"}` + )} + $t_asaNugetVersion = "2.x.y" + It "Generates N testable files for N output files for asANugetVersion 2.x" { + Get-AutRunResult ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID ` + -testCase $t_testCase ` + -asaNugetVersion $t_asaNugetVersion | Out-Null + + Assert-MockCalled Get-Content -Times 16 -Exactly -Scope It #4 for ref, 4 for output times 2 + Assert-MockCalled Add-Content -Times 8 -Exactly -Scope It #4 for ref, 4 for output times 2 + } + $t_asaNugetVersion = "3.0.0" + + Mock Get-AutFieldFromFileInfo {return @(` + @{Basename0="003";FilePath="foobar";Basename1="Output";Basename2="fb3"},` + @{Basename0="001";FilePath="foobar1";Basename1="Output";Basename2="fb11"},` + @{Basename0="001";FilePath="foobar2";Basename1="Output";Basename2="fb12"},` + @{Basename0="002";FilePath="foobar";Basename1="Output";Basename2="fb2"}` + )} + $t_asaNugetVersion = "3.0.0" + It "Generates N testable files for N output files for asANugetVersion 3 or above" { + Get-AutRunResult ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID ` + -testCase $t_testCase ` + -asaNugetVersion $t_asaNugetVersion | Out-Null + + Assert-MockCalled Get-Content -Times 12 -Exactly -Scope It #4 for output times 3 + Assert-MockCalled Invoke-ReadAllText -Times 4 -Exactly -Scope It #4 for ref + Assert-MockCalled Add-Content -Times 8 -Exactly -Scope It #4 for ref, 4 for output times 2 + } + $t_asaNugetVersion = "3.0.0" + + Mock Get-AutFieldFromFileInfo {return @(` + @{Basename0="003";FilePath="foobar";Basename1="Output";Basename2="fb3"},` + @{Basename0="001";FilePath="foobar1";Basename1="Output";Basename2="fb11"},` + @{Basename0="001";FilePath="foobar2";Basename1="Output";Basename2="fb12"},` + @{Basename0="002";FilePath="foobar";Basename1="Output";Basename2="fb2"}` + )} + Mock Compare-Object {return $null} + It "Tests and generates 0 result files for N correct tests" { + Get-AutRunResult ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID ` + -testCase $t_testCase ` + -asaNugetVersion $t_asaNugetVersion | Out-Null + + Assert-MockCalled Compare-Object -Times 4 -Exactly -Scope It + Assert-MockCalled Out-File -Times 0 -Exactly -Scope It + } + + Mock Get-AutFieldFromFileInfo {return @(` + @{Basename0="003";FilePath="foobar";Basename1="Output";Basename2="fb3"},` + @{Basename0="001";FilePath="foobar1";Basename1="Output";Basename2="fb11"},` + @{Basename0="001";FilePath="foobar2";Basename1="Output";Basename2="fb12"},` + @{Basename0="002";FilePath="foobar";Basename1="Output";Basename2="fb2"}` + )} + Mock Compare-Object {return "ERROR"} + It "Tests and generates 4 result files for N correct tests" { + Get-AutRunResult ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID ` + -testCase $t_testCase ` + -asaNugetVersion $t_asaNugetVersion | Out-Null + + Assert-MockCalled Compare-Object -Times 4 -Exactly -Scope It + Assert-MockCalled Out-File -Times 4 -Exactly -Scope It + } + + Mock Get-AutFieldFromFileInfo {return @(` + @{Basename0="003";FilePath="foobar";Basename1="Output";Basename2="fb3"},` + @{Basename0="001";FilePath="foobar1";Basename1="Output";Basename2="fb11"},` + @{Basename0="001";FilePath="foobar2";Basename1="Output";Basename2="fb12"},` + @{Basename0="001";FilePath="foobar3";Basename1="Output";Basename2="fb13"},` + @{Basename0="002";FilePath="foobar";Basename1="Output";Basename2="fb2"}` + )} + Mock Compare-Object {return "a"} + It "returns N for N errors" { + Get-AutRunResult ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID ` + -testCase $t_testCase ` + -asaNugetVersion $t_asaNugetVersion | + Should -be 5 + } + } +} + +Describe "Get-AutRunResult empty folders" { + InModuleScope $moduleName { + + $t_solutionPath = "TestDrive:\foo" + $t_asaProjectName = "bar" + $t_unittestFolder = "bar.Tests" + $t_testID = "yyyymmddhhmmss" + $t_testCase = "123" + + Mock Test-Path {return $true} + Mock Get-ChildItem {} + Mock Get-AutFieldFromFileInfo {} + Mock Get-Content {} + Mock Add-Content {} + Mock Compare-Object {} + Mock Out-File {} + Mock Invoke-ReadAllText {} + + It "provides 0 error in output pipeline on an empty folder" { + Get-AutRunResult ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID ` + -testCase $t_testCase ` + -asaNugetVersion $t_asaNugetVersion | + Should -be 0 + } + + It "generates no file on an empty folder" { + Get-AutRunResult ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID ` + -testCase $t_testCase ` + -asaNugetVersion $t_asaNugetVersion | Out-Null + + Assert-MockCalled Out-File -Times 0 -Exactly -Scope It + } + } +} + + +Describe "Get-AutRunResult parameters" { + InModuleScope $moduleName { + + $t_solutionPath = "TestDrive:\foo" + $t_asaProjectName = "bar" + $t_unittestFolder = "bar.Tests" + $t_testID = "yyyymmddhhmmss" + $t_testCase = "123" + + Mock Test-Path {return $true} + Mock Get-ChildItem {return 1} + Mock Get-AutFieldFromFileInfo {} + Mock Get-Content {return (@{FilePath="foobar"} | ConvertTo-Json)} + Mock Add-Content {} + Mock Compare-Object {} + Mock Out-File {} + Mock Invoke-ReadAllText {} + + It "runs with a valid set of parameters" { + { Get-AutRunResult ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID ` + -testCase $t_testCase ` + -asaNugetVersion $t_asaNugetVersion } | + Should -not -throw "-* is required" + } + + It "fails without -solutionPath" { + { Get-AutRunResult ` + #-solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID ` + -testCase $t_testCase ` + -asaNugetVersion $t_asaNugetVersion } | + Should -throw "-solutionPath is required" + } + + It "fails without -asaProjectName" { + { Get-AutRunResult ` + -solutionPath $t_solutionPath ` + #-asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID ` + -testCase $t_testCase ` + -asaNugetVersion $t_asaNugetVersion } | + Should -throw "-asaProjectName is required" + } + + It "fails without -unittestFolder" { + { Get-AutRunResult ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + #-unittestFolder $t_unittestFolder ` + -testID $t_testID ` + -testCase $t_testCase ` + -asaNugetVersion $t_asaNugetVersion } | + Should -throw "-unittestFolder is required" + } + + It "fails without -testID" { + { Get-AutRunResult ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + #-testID $t_testID ` + -testCase $t_testCase ` + -asaNugetVersion $t_asaNugetVersion } | + Should -throw "-testID is required" + } + + It "fails without -testCase" { + { Get-AutRunResult ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID ` + #-testCase $t_testCase + -asaNugetVersion $t_asaNugetVersion } | + Should -throw "-testCase is required" + } + + It "fails without -asaNugetVersion" { + { Get-AutRunResult ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID ` + -testCase $t_testCase ` + #-asaNugetVersion $t_asaNugetVersion ` + } | + Should -throw "-asaNugetVersion is required" + } + } +} + +Describe "Get-AutRunResult paths" { + InModuleScope $moduleName { + + $t_solutionPath = "TestDrive:\foo" + $t_asaProjectName = "bar" + $t_unittestFolder = "bar.Tests" + $t_testID = "yyyymmddhhmmss" + $t_testCase = "123" + + Mock Test-Path {return $true} + Mock Get-ChildItem {return 1} + Mock Get-AutFieldFromFileInfo {} + Mock Get-Content {return (@{FilePath="foobar"} | ConvertTo-Json)} + Mock Add-Content {} + Mock Compare-Object {} + Mock Out-File {} + Mock Invoke-ReadAllText {} + + Mock Test-Path {return $true} + It "runs with a valid set of paths" { + { Get-AutRunResult ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID ` + -testCase $t_testCase ` + -asaNugetVersion $t_asaNugetVersion } | + Should -not -throw + } + + Mock Test-Path {return $false} + It "fails when solutionPath is not a valid path" { + { Get-AutRunResult ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID ` + -testCase $t_testCase ` + -asaNugetVersion $t_asaNugetVersion } | + Should -throw "$t_solutionPath is not a valid path" + } + + $t_testPath = "$t_solutionPath\$t_unittestFolder\3_assert\$t_testID\$t_testCase" + Mock Test-Path {return $true} -ParameterFilter {$path -eq $t_solutionPath} + It "fails when testPath is not a valid path" { + { Get-AutRunResult ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID ` + -testCase $t_testCase ` + -asaNugetVersion $t_asaNugetVersion } | + Should -throw "$t_testPath is not a valid path" + } + + $t_outputSourcePath = "$t_testPath\$t_asaProjectName\Inputs" + Mock Test-Path {return $true} -ParameterFilter {$path -eq $t_testPath} + It "fails when outputSourcePath is not a valid path" { + { Get-AutRunResult ` + -solutionPath $t_solutionPath ` + -asaProjectName $t_asaProjectName ` + -unittestFolder $t_unittestFolder ` + -testID $t_testID ` + -testCase $t_testCase ` + -asaNugetVersion $t_asaNugetVersion } | + Should -throw "$t_outputSourcePath is not a valid path" + } + } +} diff --git a/asa.unittest/Public/Start-AutRun.ps1 b/asa.unittest/Public/Start-AutRun.ps1 index f4bbdc3..735b3b7 100644 --- a/asa.unittest/Public/Start-AutRun.ps1 +++ b/asa.unittest/Public/Start-AutRun.ps1 @@ -1,147 +1,148 @@ -<# -.SYNOPSIS -Orchestrator script used to run unit tests on an Azure Stream Analytics project - -In case of issues with PowerShell Execution Policies, see https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scripts?view=powershell-7 -PS: VSCode has a weird behavior on that topic, use Windows Terminal instead : https://github.com/PowerShell/vscode-powershell/issues/1217 - -.DESCRIPTION -See documentation for more information : https://github.com/Fleid/asa.unittest - -This script leverages a text fixture (folder structure + filename convention) to run unit tests for a given ASA project. -It requires dependencies installed by the companion script Install_AutToolset - -.PARAMETER asaNugetVersion -Version of the Azure Stream Analytics CI/CD nuget package (Microsoft.Azure.StreamAnalytics.CICD) to be downloaded and used - -.PARAMETER solutionPath -Path to the solution (folder) containing both the Azure Stream Analytics folder and the Tests folder - -.PARAMETER asaProjectName -Name of the Azure Stream Analytics project = name of the project folder = name of the query in that folder (.asaql) = name of the project description file (.asaproj) - -.PARAMETER unittestFolder -Name of the folder containing the test fixture (folders 1_arrange, 2_act, 3_assert), usually "asaProjectName.Tests" - -.EXAMPLE -Start-AutRun.ps1 -solutionPath "C:\Users\fleide\Repos\asa.unittest" -asaProjectName "ASAHelloWorld" -verbose -#> - -Function Start-AutRun{ - - [CmdletBinding( - SupportsShouldProcess=$true, - ConfirmImpact="Low" - )] - param ( - #[ValidateSet("2.3.0","2.4.0","2.4.1")] - [string]$asaNugetVersion, - - [string]$solutionPath = $ENV:BUILD_SOURCESDIRECTORY, # Azure DevOps Pipelines default variable - - [string]$asaProjectName = $(Throw "-asaProjectName is required"), - - [string]$unittestFolder = "$asaProjectName.Tests" - ) - - BEGIN { - ################################################################################################################################ - write-verbose "101 - Set and check variables" - - if (-not (Test-Path $solutionPath)) {Throw "Invalid -solutionPath"} - - if (-not (($asaProjectName.Length -ge 1) - # 1.0.9 - This is actually not necessary, the validation requirement are only applied on the Azure job, not the local project - #-and ($asaProjectName -match '^[a-zA-Z0-9_-]+$') ` - #-and ($asaProjectName.Length -le 63) ` - )) {Throw "Invalid -asaProjectName (empty string)"} - - if (-not (Test-Path "$solutionPath\$unittestFolder\1_arrange")) {Throw "Can't find 1_arrange folder at $solutionPath\$unittestFolder\1_arrange"} - - if (-not $asaNugetVersion) { - $asaNugetVersion = (` - Get-ChildItem -path "$solutionPath\$unittestFolder\2_act\" | ` - Where-Object { ($_.Name -like "Microsoft.Azure.StreamAnalytics.CICD.*") ` - -and ($_.Name -match '([0-9]+\.[0-9]+\.[0-9]+)$') } | ` - Sort-Object -Descending -Property LastWriteTime | ` - Select-Object -First 1 -ExpandProperty Name ` - ).Substring(37) #Microsoft.Azure.StreamAnalytics.CICD. - } - - $exePath = "$solutionPath\$unittestFolder\2_act\Microsoft.Azure.StreamAnalytics.CICD.$asaNugetVersion\tools\sa.exe" - if (-not (Test-Path $exePath -PathType Leaf)) {Throw "Can't find sa.exe at $solutionPath\$unittestFolder\2_act\Microsoft.Azure.StreamAnalytics.CICD.$asaNugetVersion\tools\sa.exe"} - - $testID = (Get-Date -Format "yyyyMMddHHmmss") - } - - PROCESS { - if ($pscmdlet.ShouldProcess("Starting an asa.unittest run for $asaProjectName at $unittestFolder")) - { - ################################################################################################################################ - # 2xx - Creating run fixture - - $testCases = New-AutRunFixture ` - -solutionPath $solutionPath ` - -asaProjectName $asaProjectName ` - -unittestFolder $unittestFolder ` - -testID $testID - - ################################################################################################################################ - # 4xx - Running the jobs - write-verbose "401 - Run SA in parallel jobs" - - ForEach ($testCase in $testCases) { - New-AutRunJob ` - -solutionPath $solutionPath ` - -asaProjectName $asaProjectName ` - -unittestFolder $unittestFolder ` - -testID $testID ` - -testCase $testCase ` - -exePath $exePath - } - - ## Wait for all jobs to complete and results ready to be received - write-verbose "402 - Waiting for all jobs to end..." - - Wait-Job * | Out-Null - - write-verbose "403 - Jobs done" - - <# - ## Debug ~ Process the results - foreach($job in Get-Job) - { - $result = Receive-Job $job - Write-Host $result - } - #> - - ################################################################################################################################ - - write-verbose "501 - Calculating diffs" - - $errorCounter = 0 - - ## For each Output test file, generate a testable file (adding brackets to it) then run the diff with the corresponding arranged output file - - ForEach ($testCase in $testCases) { - $errorCounter += Get-AutRunResult ` - -solutionPath $solutionPath ` - -asaProjectName $asaProjectName ` - -unittestFolder $unittestFolder ` - -testID $testID ` - -testCase $testCase - } - - ################################################################################################################################ - - # Final result - if ($errorCounter -gt 0) { - Write-Verbose "Ending Test Run with $errorCounter errors" - throw("Ending Test Run with $errorCounter errors") - } - - } #ShouldProcess - } #PROCESS - END {} +<# +.SYNOPSIS +Orchestrator script used to run unit tests on an Azure Stream Analytics project + +In case of issues with PowerShell Execution Policies, see https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scripts?view=powershell-7 +PS: VSCode has a weird behavior on that topic, use Windows Terminal instead : https://github.com/PowerShell/vscode-powershell/issues/1217 + +.DESCRIPTION +See documentation for more information : https://github.com/Fleid/asa.unittest + +This script leverages a text fixture (folder structure + filename convention) to run unit tests for a given ASA project. +It requires dependencies installed by the companion script Install_AutToolset + +.PARAMETER asaNugetVersion +Version of the Azure Stream Analytics CI/CD nuget package (Microsoft.Azure.StreamAnalytics.CICD) to be downloaded and used + +.PARAMETER solutionPath +Path to the solution (folder) containing both the Azure Stream Analytics folder and the Tests folder + +.PARAMETER asaProjectName +Name of the Azure Stream Analytics project = name of the project folder = name of the query in that folder (.asaql) = name of the project description file (.asaproj) + +.PARAMETER unittestFolder +Name of the folder containing the test fixture (folders 1_arrange, 2_act, 3_assert), usually "asaProjectName.Tests" + +.EXAMPLE +Start-AutRun.ps1 -solutionPath "C:\Users\fleide\Repos\asa.unittest" -asaProjectName "ASAHelloWorld" -verbose +#> + +Function Start-AutRun{ + + [CmdletBinding( + SupportsShouldProcess=$true, + ConfirmImpact="Low" + )] + param ( + #[ValidateSet("2.3.0","2.4.0","2.4.1")] + [string]$asaNugetVersion, + + [string]$solutionPath = $ENV:BUILD_SOURCESDIRECTORY, # Azure DevOps Pipelines default variable + + [string]$asaProjectName = $(Throw "-asaProjectName is required"), + + [string]$unittestFolder = "$asaProjectName.Tests" + ) + + BEGIN { + ################################################################################################################################ + write-verbose "101 - Set and check variables" + + if (-not (Test-Path $solutionPath)) {Throw "Invalid -solutionPath"} + + if (-not (($asaProjectName.Length -ge 1) + # 1.0.9 - This is actually not necessary, the validation requirement are only applied on the Azure job, not the local project + #-and ($asaProjectName -match '^[a-zA-Z0-9_-]+$') ` + #-and ($asaProjectName.Length -le 63) ` + )) {Throw "Invalid -asaProjectName (empty string)"} + + if (-not (Test-Path "$solutionPath\$unittestFolder\1_arrange")) {Throw "Can't find 1_arrange folder at $solutionPath\$unittestFolder\1_arrange"} + + if (-not $asaNugetVersion) { + $asaNugetVersion = (` + Get-ChildItem -path "$solutionPath\$unittestFolder\2_act\" | ` + Where-Object { ($_.Name -like "Microsoft.Azure.StreamAnalytics.CICD.*") ` + -and ($_.Name -match '([0-9]+\.[0-9]+\.[0-9]+)$') } | ` + Sort-Object -Descending -Property LastWriteTime | ` + Select-Object -First 1 -ExpandProperty Name ` + ).Substring(37) #Microsoft.Azure.StreamAnalytics.CICD. + } + + $exePath = "$solutionPath\$unittestFolder\2_act\Microsoft.Azure.StreamAnalytics.CICD.$asaNugetVersion\tools\sa.exe" + if (-not (Test-Path $exePath -PathType Leaf)) {Throw "Can't find sa.exe at $solutionPath\$unittestFolder\2_act\Microsoft.Azure.StreamAnalytics.CICD.$asaNugetVersion\tools\sa.exe"} + + $testID = (Get-Date -Format "yyyyMMddHHmmss") + } + + PROCESS { + if ($pscmdlet.ShouldProcess("Starting an asa.unittest run for $asaProjectName at $unittestFolder")) + { + ################################################################################################################################ + # 2xx - Creating run fixture + + $testCases = New-AutRunFixture ` + -solutionPath $solutionPath ` + -asaProjectName $asaProjectName ` + -unittestFolder $unittestFolder ` + -testID $testID + + ################################################################################################################################ + # 4xx - Running the jobs + write-verbose "401 - Run SA in parallel jobs" + + ForEach ($testCase in $testCases) { + New-AutRunJob ` + -solutionPath $solutionPath ` + -asaProjectName $asaProjectName ` + -unittestFolder $unittestFolder ` + -testID $testID ` + -testCase $testCase ` + -exePath $exePath + } + + ## Wait for all jobs to complete and results ready to be received + write-verbose "402 - Waiting for all jobs to end..." + + Wait-Job * | Out-Null + + write-verbose "403 - Jobs done" + + <# + ## Debug ~ Process the results + foreach($job in Get-Job) + { + $result = Receive-Job $job + Write-Host $result + } + #> + + ################################################################################################################################ + + write-verbose "501 - Calculating diffs" + + $errorCounter = 0 + + ## For each Output test file, generate a testable file (adding brackets to it) then run the diff with the corresponding arranged output file + + ForEach ($testCase in $testCases) { + $errorCounter += Get-AutRunResult ` + -solutionPath $solutionPath ` + -asaProjectName $asaProjectName ` + -unittestFolder $unittestFolder ` + -testID $testID ` + -testCase $testCase ` + -asaNugetVersion $asaNugetVersion + } + + ################################################################################################################################ + + # Final result + if ($errorCounter -gt 0) { + Write-Verbose "Ending Test Run with $errorCounter errors" + throw("Ending Test Run with $errorCounter errors") + } + + } #ShouldProcess + } #PROCESS + END {} } \ No newline at end of file diff --git a/asa.unittest/private/Get-AutFieldFromFileInfo.ps1 b/asa.unittest/private/Get-AutFieldFromFileInfo.ps1 index 1a16a4d..a06678d 100644 --- a/asa.unittest/private/Get-AutFieldFromFileInfo.ps1 +++ b/asa.unittest/private/Get-AutFieldFromFileInfo.ps1 @@ -1,47 +1,47 @@ -<# -.SYNOPSIS -Tool script used to parse a FileInfo to extract fields from naming convention - -.DESCRIPTION -See documentation for more information : https://github.com/Fleid/asa.unittest - -.PARAMETER thisFileInfo -FileInfo to be processed - -.PARAMETER fieldSeparator -Separator used in the naming convention - -.PARAMETER numberOfFields -Number of fields to be extracted - -.EXAMPLE -(Get-ChildItem -Path $arrangePath -File) | Get-AutFieldFromFileInfo -#> - -Function Get-AutFieldFromFileInfo{ - [CmdletBinding()] - param ( - [Parameter(ValueFromPipeline=$true)] - [System.IO.FileInfo]$thisFileInfo, - [string]$separatorOfFields, - [int]$numberOfFields - ) - - BEGIN {} - - PROCESS { - $Fields = New-Object PSObject -Property @{ - FullName = $thisFileInfo.Name - FilePath = $thisFileInfo.Fullname - Basename = $thisFileInfo.Basename - } - - $basenameParts = $thisFileInfo.Basename.Split($separatorOfFields) - - for (($i=0);($i -lt $numberOfFields);$i++){ - $Fields | Add-Member Noteproperty "basename$fieldSeparator$i" $basenameParts[$i] - } - - $Fields - } +<# +.SYNOPSIS +Tool script used to parse a FileInfo to extract fields from naming convention + +.DESCRIPTION +See documentation for more information : https://github.com/Fleid/asa.unittest + +.PARAMETER thisFileInfo +FileInfo to be processed + +.PARAMETER fieldSeparator +Separator used in the naming convention + +.PARAMETER numberOfFields +Number of fields to be extracted + +.EXAMPLE +(Get-ChildItem -Path $arrangePath -File) | Get-AutFieldFromFileInfo +#> + +Function Get-AutFieldFromFileInfo{ + [CmdletBinding()] + param ( + [Parameter(ValueFromPipeline=$true)] + [System.IO.FileInfo]$thisFileInfo, + [string]$separatorOfFields, + [int]$numberOfFields + ) + + BEGIN {} + + PROCESS { + $Fields = New-Object PSObject -Property @{ + FullName = $thisFileInfo.Name + FilePath = $thisFileInfo.Fullname + Basename = $thisFileInfo.Basename + } + + $basenameParts = $thisFileInfo.Basename.Split($separatorOfFields) + + for (($i=0);($i -lt $numberOfFields);$i++){ + $Fields | Add-Member Noteproperty "basename$fieldSeparator$i" $basenameParts[$i] + } + + $Fields + } } \ No newline at end of file diff --git a/asa.unittest/private/Get-AutRunResult.ps1 b/asa.unittest/private/Get-AutRunResult.ps1 index 5e2fbca..77133ca 100644 --- a/asa.unittest/private/Get-AutRunResult.ps1 +++ b/asa.unittest/private/Get-AutRunResult.ps1 @@ -20,8 +20,11 @@ Timestamp of the test run (yyyyMMddHHmmss), will be used in the folder structure .PARAMETER testCase Current test to be run (001, 002, 003...) +.PARAMETER asaNugetVersion +Version of the Azure Stream Analytics CI/CD nuget package (Microsoft.Azure.StreamAnalytics.CICD) to be downloaded and used + .EXAMPLE -Get-AutRunResult -solutionPath $solutionPath -asaProjectName $asaProjectName -unittestFolder $unittestFolder -testID $testID -testCase $testCase +Get-AutRunResult -solutionPath $solutionPath -asaProjectName $asaProjectName -unittestFolder $unittestFolder -testID $testID -testCase $testCase -asaNugetVersion "3.0.0" #> Function Get-AutRunResult{ @@ -33,7 +36,8 @@ Function Get-AutRunResult{ [string]$asaProjectName = $(Throw "-asaProjectName is required"), [string]$unittestFolder = $(Throw "-unittestFolder is required"), [string]$testID = $(Throw "-testID is required"), - [string]$testCase = $(Throw "-testCase is required") + [string]$testCase = $(Throw "-testCase is required"), + [string]$asaNugetVersion = $(Throw "-asaNugetVersion is required") ) BEGIN { @@ -85,9 +89,13 @@ Function Get-AutRunResult{ Add-Content -Path $_.sortedTestCaseOutputFilePath -Value $referenceSortedContent # Prepare output content (format, sorting) - # $testableContent = ("[$(Get-Content -Path $_.rawContent)]") | ConvertFrom-Json + + if ($asaNugetVersion.split(".")[0].Equals("2")) { + $testableContent = ("[$(Get-Content -Path $_.rawContent)]") | ConvertFrom-Json + } else { # New format after CICD 3.0.0 - $testableContent = [IO.File]::ReadAllText($_.rawContent).split("`n") | ConvertFrom-Json + $testableContent = (Invoke-ReadAllText -p $_.rawContent).split("`n") | ConvertFrom-Json + } $testableContentProperties = ` $testableContent | ` diff --git a/asa.unittest/private/Invoke-ReadAllText.ps1 b/asa.unittest/private/Invoke-ReadAllText.ps1 new file mode 100644 index 0000000..90e6d06 --- /dev/null +++ b/asa.unittest/private/Invoke-ReadAllText.ps1 @@ -0,0 +1,33 @@ +<# +.SYNOPSIS +Helper function for invoking a .NET class. +Allows for moking in Pester + +.DESCRIPTION +See source for more information : https://github.com/pester/Pester/issues/592 + +.PARAMETER param1 +Literal path to the executable ("...\nuget.exe", "npm") + +.EXAMPLE +Invoke-ReadAllText -param1 $rawContent + +#> + +Function Invoke-ReadAllText +{ + [CmdletBinding()] + [OutputType('System.String')] + param( + [Parameter(Mandatory=$true)] + [string] $param1 + ) + +BEGIN {} + +PROCESS { + return [IO.File]::ReadAllText($param1) +} #PROCESS + +END {} +} From 1a5f65c89a64827eb0eac03a2236f49f418e1987 Mon Sep 17 00:00:00 2001 From: Florian Eiden Date: Tue, 15 Sep 2020 15:30:50 -0700 Subject: [PATCH 18/18] Update to include asanugetversion --- README_DEV.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README_DEV.md b/README_DEV.md index 410c1e4..5f657ce 100644 --- a/README_DEV.md +++ b/README_DEV.md @@ -39,10 +39,12 @@ New-AutProject ` $asaProjectName = "ASAHelloWorld" $solutionPath = "C:\users\fleide\Repos\asa.unittest\examples" $unittestFolder = "ASAHelloworld.Tests" +$asanugetversion = "3.0.0" Start-AutRun ` -asaProjectName $asaProjectName ` -solutionPath $solutionPath ` -unittestFolder $unittestFolder ` + -asanugetversion $asanugetversion ` -verbose ``` @@ -63,7 +65,7 @@ Scripts should be isolated in atomic .ps1 file, written as advanced functions. T Common parameters: ```PowerShell -#$ASAnugetVersion = "2.4.0" +$ASAnugetVersion = "2.4.0" $solutionPath = "C:\Users\fleide\Repos\asa.unittest\examples" $asaProjectName = "ASAHelloWorld" $unittestFolder = "ASAHelloWorld.Tests"