diff --git a/Functions/TestResults.Tests.ps1 b/Functions/TestResults.Tests.ps1 index 120b79f8c..5bbdfc5a1 100644 --- a/Functions/TestResults.Tests.ps1 +++ b/Functions/TestResults.Tests.ps1 @@ -1,3 +1,6 @@ +$here = Split-Path -Parent $MyInvocation.MyCommand.Path +. $here\Validate-Xml.ps1 + Describe "Write nunit test results" { Setup -Dir "Results" @@ -148,41 +151,36 @@ Describe "Write nunit test results" { $xmlEnvironment.'machine-name'.Should.Be($env:ComputerName) } - $pscx = Import-Module Pscx -AsCustomObject -ErrorAction SilentlyContinue - if($pscx) { - it "Should validate test results against the nunit 2.5 schema" { - $testResults = @{} - $testResults.Describes = @( - @{ - name = 'Describe #1' - Tests = @(@{ - name = "Successful testcase" - time = "1.0" - success = $true - }, - @{ - name = "Failed testcase" - time = "1.0" - success = $true - }); + it "Should validate test results against the nunit 2.5 schema" { + $testResults = @{} + $testResults.Describes = @( + @{ + name = 'Describe #1' + Tests = @(@{ + name = "Successful testcase" + time = "1.0" + success = $true }, @{ - name = 'Describe #2' - Tests = @{ - name = "Failed testcase" - time = "2.0" - success = $false - } + name = "Failed testcase" + time = "1.0" + success = $true + }); + }, + @{ + name = 'Describe #2' + Tests = @{ + name = "Failed testcase" + time = "2.0" + success = $false } - ); - $testFile = "$TestDrive\Results\Tests.xml" - Write-NunitTestReport $testResults $testFile - $valid = Test-Xml $testFile -SchemaPath '.\nunit_schema_2.5.xsd' -Verbose - $valid.Should.Be($true) - } - } - else { - Write-Host "PowerShell Community Extensions not found, unable to validate nunit xml against schema. To run this test download http://pscx.codeplex.com" + } + ); + $testFile = "$TestDrive\Results\Tests.xml" + Write-NunitTestReport $testResults $testFile + [xml]$xml = gc $testFile + $valid = Validate-Xml $xml '.\nunit_schema_2.5.xsd' + $valid.Should.Be($true) } } diff --git a/Functions/Validate-Xml.ps1 b/Functions/Validate-Xml.ps1 new file mode 100644 index 000000000..4eed7d1f7 --- /dev/null +++ b/Functions/Validate-Xml.ps1 @@ -0,0 +1,107 @@ +############################################################################################## +# Taken from http://gallery.technet.microsoft.com/scriptcenter/2f6f0541-d152-4474-a8c1-b441d7424454 +# Written by Justin Yancey +############################################################################################## + +# +#A function used to validate an XML object against a given schema +# +# +# +# +#Array +# + +Function Validate-Xml{ + param( + [Parameter( + Mandatory = $true, + Position = 0, + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [xml]$xml, + [Parameter( + Mandatory = $true, + Position = 1, + ValueFromPipeline = $false)] + [string]$schema + ) + + #Declare the array to hold our error objects + $validationerrors = @() + + #Check to see if we have defined our namespace cache variable, + #and create it if it doesnt exist. We do this in case we want to make + #lots and lots of calls to this function, to save on excessive file IO. + if (-not $schemas){ ${GLOBAL:schemas} = @{} } + + #Check to see if the namespace is already in the cache,if not then add it + # + # + if (-not $schemas[$schema]) { + #Read in the schema file + [xml]$xmlschema = Get-Content $schema + #Extract the targetNamespace from the schema + $namespace = $xmlschema.get_DocumentElement().targetNamespace + #Add the schema/namespace entry to the global hashtable + $schemas.Add($schema,$namespace) + # + } else { + # + #Pull the namespace from the schema cache + $namespace = $schemas[$schema] + } + # + + #Define the script block that will act as the validation event handler +$code = @' + param($sender,$a) + $ex = $a.Exception + #Trim out the useless,irrelevant parts of the message + $msg = $ex.Message -replace " in namespace 'http.*?'","" + #Create the custom error object using a hashtable + $properties = @{LineNumber=$ex.LineNumber; LinePosition=$ex.LinePosition; Message=$msg} + $o = New-Object PSObject -Property $properties + #Add the object to the $validationerrors array + $validationerrors += $o +'@ + #Convert the code block to as ScriptBlock + $validationEventHandler = [scriptblock]::Create($code) + + #Create a new XmlReaderSettings object + $rs = new-object System.Xml.XmlreaderSettings + #Load the schema into the XmlReaderSettings object + [Void]$rs.schemas.add($namespace,(new-object System.Xml.xmltextreader($schema))) + #Instruct the XmlReaderSettings object to use Schema validation + $rs.validationtype = "Schema" + $rs.ConformanceLevel = "Auto" + #Add the scriptblock as the ValidationEventHandler + $rs.add_ValidationEventHandler($validationEventHandler) + + #Create a temporary file and save the Xml into it + $xmlfile = [System.IO.Path]::GetTempFileName() + $xml.Save($xmlfile) + + #Create the XmlReader object using the settings defined previously + $reader = [System.Xml.XmlReader]::Create($xmlfile,$rs) + + #Temporarily set the ErrorActionPreference to SilentlyContinue, + #as we want to use our validation event handler to handle errors + $previousErrorActionPreference = $ErrorActionPreference + $ErrorActionPreference = "SilentlyContinue" + + #Read the Xml using the XmlReader + while ($reader.read()) {$null} + #Close the reader + $reader.close() + + #Delete the temporary file + Remove-Item $xmlfile + + #Reset the ErrorActionPreference back to the previous value + $ErrorActionPreference = $previousErrorActionPreference + + #Return the array of validation errors + return $validationerrors +} +#