Skip to content

Commit 14ddd0f

Browse files
authored
Add integration testing module with simple tests to verify PSES starts and stops (#944)
* Add integration testing module as a tool * Add Pester execution and depedency to build * Add simple start and stop integration tests as Pester tests
1 parent 51909ee commit 14ddd0f

File tree

8 files changed

+1271
-2
lines changed

8 files changed

+1271
-2
lines changed

.vsts-ci/templates/ci-general.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ steps:
1414
testRunner: VSTest
1515
testResultsFiles: '**/*.trx'
1616
condition: succeededOrFailed()
17+
- task: PublishTestResults@2
18+
inputs:
19+
testRunner: NUnit
20+
testResultsFiles: '**/TestResults.xml'
21+
condition: succeededOrFailed()
1722
- task: PublishBuildArtifacts@1
1823
inputs:
1924
ArtifactName: PowerShellEditorServices

PowerShellEditorServices.build.ps1

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ param(
1818

1919
#Requires -Modules @{ModuleName="InvokeBuild";ModuleVersion="3.2.1"}
2020

21-
$script:IsCIBuild = $env:TF_BUILD -ne $null
2221
$script:IsUnix = $PSVersionTable.PSEdition -and $PSVersionTable.PSEdition -eq "Core" -and !$IsWindows
2322
$script:TargetPlatform = "netstandard2.0"
2423
$script:TargetFrameworksParam = "/p:TargetFrameworks=`"$script:TargetPlatform`""
2524
$script:RequiredSdkVersion = (Get-Content (Join-Path $PSScriptRoot 'global.json') | ConvertFrom-Json).sdk.version
25+
$script:MinimumPesterVersion = '4.7'
2626
$script:NugetApiUriBase = 'https://www.nuget.org/api/v2/package'
2727
$script:ModuleBinPath = "$PSScriptRoot/module/PowerShellEditorServices/bin/"
2828
$script:VSCodeModuleBinPath = "$PSScriptRoot/module/PowerShellEditorServices.VSCode/bin/"
@@ -330,12 +330,17 @@ task Build {
330330
exec { & $script:dotnetExe build -c $Configuration .\src\PowerShellEditorServices.VSCode\PowerShellEditorServices.VSCode.csproj $script:TargetFrameworksParam }
331331
}
332332

333+
task BuildPsesClientModule SetupDotNet,{
334+
Write-Verbose 'Building PsesPsClient testing module'
335+
& $PSScriptRoot/tools/PsesPsClient/build.ps1 -DotnetExe $script:dotnetExe
336+
}
337+
333338
function DotNetTestFilter {
334339
# Reference https://docs.microsoft.com/en-us/dotnet/core/testing/selective-unit-tests
335340
if ($TestFilter) { @("--filter",$TestFilter) } else { "" }
336341
}
337342

338-
task Test TestServer,TestProtocol
343+
task Test TestServer,TestProtocol,TestPester
339344

340345
task TestServer {
341346
Set-Location .\test\PowerShellEditorServices.Test\
@@ -373,6 +378,28 @@ task TestHost {
373378
exec { & $script:dotnetExe test -f $script:TestRuntime.Core (DotNetTestFilter) }
374379
}
375380

381+
task TestPester Build,BuildPsesClientModule,EnsurePesterInstalled,{
382+
$testParams = @{}
383+
if ($env:TF_BUILD)
384+
{
385+
$testParams += @{
386+
OutputFormat = 'NUnitXml'
387+
OutputFile = 'TestResults.xml'
388+
}
389+
}
390+
$result = Invoke-Pester "$PSScriptRoot/test/Pester/" @testParams -PassThru
391+
392+
if ($result.FailedCount -gt 0)
393+
{
394+
throw "$($result.FailedCount) tests failed."
395+
}
396+
}
397+
398+
task EnsurePesterInstalled -If (-not (Get-Module Pester -ListAvailable | Where-Object Version -ge $script:MinimumPesterVersion)) {
399+
Write-Warning "Required Pester version not found, installing Pester to current user scope"
400+
Install-Module -Scope CurrentUser Pester -Force -SkipPublisherCheck
401+
}
402+
376403
task LayoutModule -After Build {
377404
# Copy Third Party Notices.txt to module folder
378405
Copy-Item -Force -Path "$PSScriptRoot\Third Party Notices.txt" -Destination $PSScriptRoot\module\PowerShellEditorServices
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
2+
$script:ExceptionRegex = [regex]::new('\s*Exception: (.*)$', 'Compiled,Multiline,IgnoreCase')
3+
function ReportLogErrors
4+
{
5+
param(
6+
[Parameter()][string]$LogPath,
7+
8+
[Parameter()][ref]<#[int]#>$FromIndex = 0,
9+
10+
[Parameter()][string[]]$IgnoreException = @()
11+
)
12+
13+
$logEntries = Parse-PsesLog $LogPath |
14+
Where-Object Index -ge $FromIndex.Value
15+
16+
# Update the index to the latest in the log
17+
$FromIndex.Value = ($FromIndex.Value,$errorLogs.Index | Measure-Object -Maximum).Maximum
18+
19+
$errorLogs = $logEntries |
20+
Where-Object LogLevel -eq Error |
21+
Where-Object {
22+
$match = $script:ExceptionRegex.Match($_.Message.Data)
23+
24+
(-not $match) -or ($match.Groups[1].Value.Trim() -notin $IgnoreException)
25+
}
26+
27+
if ($errorLogs)
28+
{
29+
$errorLogs | ForEach-Object { Write-Error "ERROR from PSES log: $($_.Message.Data)" }
30+
}
31+
}
32+
33+
Describe "Loading and running PowerShellEditorServices" {
34+
BeforeAll {
35+
Import-Module -Force "$PSScriptRoot/../../module/PowerShellEditorServices"
36+
Import-Module -Force "$PSScriptRoot/../../tools/PsesPsClient/out/PsesPsClient"
37+
Import-Module -Force "$PSScriptRoot/../../tools/PsesLogAnalyzer"
38+
39+
$logIdx = 0
40+
$psesServer = Start-PsesServer
41+
$client = Connect-PsesServer -PipeName $psesServer.SessionDetails.languageServicePipeName
42+
}
43+
44+
# This test MUST be first
45+
It "Starts and responds to an initialization request" {
46+
$request = Send-LspInitializeRequest -Client $client
47+
$response = Get-LspResponse -Client $client -Id $request.Id
48+
$response.Id | Should -BeExactly $request.Id
49+
50+
ReportLogErrors -LogPath $psesServer.LogPath -FromIndex ([ref]$logIdx)
51+
}
52+
53+
# This test MUST be last
54+
It "Shuts down the process properly" {
55+
$request = Send-LspShutdownRequest -Client $client
56+
$response = Get-LspResponse -Client $client -Id $request.Id
57+
$response.Id | Should -BeExactly $request.Id
58+
$response.Result | Should -BeNull
59+
# TODO: The server seems to stay up waiting for the debug connection
60+
# $psesServer.PsesProcess.HasExited | Should -BeTrue
61+
62+
# We close the process here rather than in an AfterAll
63+
# since errors can occur and we want to test for them.
64+
# Naturally this depends on Pester executing tests in order.
65+
66+
# We also have to dispose of everything properly,
67+
# which means we have to use these cascading try/finally statements
68+
try
69+
{
70+
$psesServer.PsesProcess.Kill()
71+
}
72+
finally
73+
{
74+
try
75+
{
76+
$psesServer.PsesProcess.Dispose()
77+
}
78+
finally
79+
{
80+
$client.Dispose()
81+
}
82+
}
83+
84+
ReportLogErrors -LogPath $psesServer.LogPath -FromIndex ([ref]$logIdx)
85+
}
86+
}

0 commit comments

Comments
 (0)