All tests fail with “This test should run but it did not. Most likely a setup in some parent block failed.”
This happens even with minimal code and when combining the implementation and tests into a single file as instructed.
The issue seems to be with loading/parsing the script (especially class definitions) before Pester runs the tests.
My code link: Exercism
Can you include your code in your post, preferably in a code block (three `s before and after the code)? Your link just goes to the exercise page so we can’t see what you did.
I can confirm that there is nothing wrong with the exercise, the examplar that I did still pass everything when I copy paste them.
IIrc there was a help topic on discord with similar error message, it seems like if an exercise is involved with class and the provided answer is lacking the required implementation it will fail like that.
using namespace System.Collections.Generic
using namespace System.Text
Class SgfTree {
[hashtable] $Properties = @{}
[SgfTree] $Children = @()
SgfTree() {}
SgfTree($properties, $children) {
$this.Properties = $properties
$this.Children = $children
}
# Helper to compare arrays (order matters)
static [bool] AreArraysEqual($arr1, $arr2) {
if (($null -eq $arr1 -and $null -ne $arr2) -or ($null -ne $arr1 -and $null -eq $arr2)) { return $false }
if ($null -eq $arr1 -and $null -eq $arr2) { return $true }
if ($arr1.Count -ne $arr2.Count) { return $false }
for ($i = 0; $i -lt $arr1.Count; $i++) {
if ($arr1[$i] -ne $arr2[$i]) { return $false }
}
return $true
}
# Helper to compare hashtables (properties)
static [bool] ArePropertiesEqual($props1, $props2) {
if (($null -eq $props1 -and $null -ne $props2) -or ($null -ne $props1 -and $null -eq $props2)) { return $false }
if ($null -eq $props1 -and $null -eq $props2) { return $true }
if ($props1.Count -ne $props2.Count) { return $false }
foreach ($key in $props1.Keys) {
if (-not $props2.ContainsKey($key)) { return $false }
if (-not [SgfTree]::AreArraysEqual($props1[$key], $props2[$key])) { return $false }
}
# Also check $props2 doesn't have extra keys
foreach ($key in $props2.Keys) {
if (-not $props1.ContainsKey($key)) { return $false }
}
return $true
}
[bool] Equals($other) {
if ($null -eq $other -or $other -isnot [SgfTree]) { return $false }
if (-not [SgfTree]::ArePropertiesEqual($this.Properties, $other.Properties)) { return $false }
if ($this.Children.Count -ne $other.Children.Count) { return $false }
for ($i = 0; $i -lt $this.Children.Count; $i++) {
if (-not $this.Children[$i].Equals($other.Children[$i])) { return $false }
}
return $true
}
}
— Parser State Class —
Class SgfParserState {
[string]$Data
[int]$Index = 0
SgfParserState([string]$SgfData) { $this.Data = $SgfData }
[char] Peek() { if ($this.Index -ge $this.Data.Length) { return [char]0 }; return $this.Data[$this.Index] }
[void] Consume([int]$count = 1) { $this.Index += $count }
[void] Expect([char]$char) {
$peeked = $this.Peek()
if ($peeked -ne $char) { throw “Expected ‘$char’ but found 'peeked' at index ($this.Index)” }
$this.Consume()
}
}
— Parsing Helper Functions —
function Parse-SgfValue($state) {
$valueBuilder = [StringBuilder]::new()
$escaped = $false
while ($state.Index -lt $state.Data.Length) {
$char = $state.Peek()
if ($escaped) {
$state.Consume()
if ($char -eq “n") { } # Ignore escaped newline elseif ($char -match '\s') { [void]$valueBuilder.Append(" ") } # Other escaped whitespace -> space else { [void]$valueBuilder.Append($char) } # Keep escaped literal $escaped = $false } elseif ($char -eq '\') { $state.Consume() $escaped = $true } elseif ($char -eq ']') { return $valueBuilder.ToString() # End found, return value } else { $state.Consume() if ($char -eq "
n”) { [void]$valueBuilder.Append($char) } # Keep newline
elseif ($char -match ‘\s’) { [void]$valueBuilder.Append(" ") } # Other whitespace → space
else { [void]$valueBuilder.Append($char) } # Regular char
}
}
throw “Unclosed property value”
}
function Parse-SgfProperties($state) {
$properties = @{}
while ($state.Peek() -match ‘[A-Z]’) {
$propIdentBuilder = [StringBuilder]::new()
while ($state.Peek() -match ‘[A-Z]’) { [void]$propIdentBuilder.Append($state.Consume()) }
$propIdent = $propIdentBuilder.ToString()
# Property ID must be uppercase (checked implicitly by loop, explicitly checked later if needed)
$propValues = [List[string]]::new()
if ($state.Peek() -ne '[') { throw "Properties without delimiter" }
while ($state.Peek() -eq '[') {
$state.Consume() # Consume '['
$propValues.Add(Parse-SgfValue $state)
$state.Expect(']')
}
if ($properties.ContainsKey($propIdent)) { throw "Duplicate property '$propIdent'" }
$properties[$propIdent] = $propValues.ToArray()
}
# Check if we started parsing an ID but failed (e.g., lowercase or missing '[')
if ($properties.Count -eq 0 -and $state.Peek() -match '[a-zA-Z]') {
$identCheck = ''
$checkIndex = $state.Index
while($checkIndex -lt $state.Data.Length -and $state.Data[$checkIndex] -match '[a-zA-Z]'){
$identCheck += $state.Data[$checkIndex]
$checkIndex++
}
if ($identCheck -match '[a-z]') { throw "Property must be in uppercase"}
# If no lowercase but still failed, might be missing '[' caught later by Expect
}
return $properties
}
function Parse-SgfNode($state) {
$state.Expect(‘;’)
$properties = Parse-SgfProperties $state
return [SgfTree]::new($properties, @())
}
Parses content within one level of parentheses ‘()’ → returns root node of that (sub)tree
function Parse-SgfSubTree($state) {
$nodesInSequence = [List[SgfTree]]::new()
$lastNodeInSequence = $null
while ($state.Peek() -ne ')') {
if ($state.Index -ge $state.Data.Length) { throw "Unexpected end of input; expecting ')'" }
$char = $state.Peek()
if ($char -eq ';') {
$newNode = Parse-SgfNode $state
$nodesInSequence.Add($newNode)
$lastNodeInSequence = $newNode
} elseif ($char -eq '(') {
if ($lastNodeInSequence -eq $null) { throw "Variation '(' cannot appear before first node ';'" }
$state.Consume() # Consume '('
$childTree = Parse-SgfSubTree $state
$state.Expect(')') # Consume ')'
$lastNodeInSequence.Children = [array]$lastNodeInSequence.Children + $childTree
} else {
# Throw specific errors checked by tests if applicable
if ($char -match '[a-z]') { throw "Property must be in uppercase" }
# If Peek is '[' could be properties without delimiter error if prev node missing
if ($char -eq '[' -and $lastNodeInSequence -eq $null) {throw "Properties without delimiter"} # Arguably caught by variation check
throw "Unexpected character '$char' at index $($state.Index)"
}
}
if ($nodesInSequence.Count -eq 0) { throw "Tree or variation needs at least one node ';...'" }
# Link sequential nodes: B becomes child of A in sequence A;B
for ($i = 1; $i -lt $nodesInSequence.Count; $i++) {
$nodesInSequence[$i - 1].Children = @($nodesInSequence[$i]) # Simple sequential link
}
return $nodesInSequence[0] # Return the root of the sequence parsed at this level
}
— Main Parser Function —
function Invoke-Parser {
param (
[Parameter(Mandatory=$true)]
[AllowEmptyString()] # Allow empty string for binding
[string]$Data
)
# --- Initial Simple Validation ---
if ([string]::IsNullOrEmpty($Data)) { throw "Tree missing" }
if ($Data -eq "()") { throw "Tree with no nodes" }
if ($Data -eq ';') { throw "Tree missing" }
if (-not $Data.StartsWith("(") ) { throw "Tree missing parentheses" }
# Let parser handle more specific errors like missing props/delimiters/uppercase
# --- Parsing ---
$state = [SgfParserState]::new($Data)
# No outer try/catch - let specific errors propagate for Pester -Throw checks
$state.Expect('(')
$sgfTree = Parse-SgfSubTree $state
$state.Expect(')')
if ($state.Index -ne $state.Data.Length) {
throw "Unexpected data after main tree closes at index $($state.Index)"
}
return $sgfTree
}