Я пишу простой модуль модульного теста в PowerShell
. Я разработал модуль так, чтобы его функции assert принимали блок скрипта в качестве параметра, чтобы позволить ему запускать код из функции assert иобрабатывать любые исключения, которые вызываются как провал теста.
Если тесты не пройдены, я хочу вернуть строку в модульный тест, в котором тест не пройден.Мой план состоял в том, чтобы сделать это путем получения трассировки стека (Get-PSCallStack) в начале каждого метода assert и использовать информацию для второго стекового фрейма, который, как я полагаю, должен соответствовать строке, где была вызвана функция assert.
На практике я обнаружил, что информация, которую вернул PowerShell, показалась неверной.Второй стековый фрейм относится к правильному файлу, как и ожидалось, но всегда дает номер строки, с которой я вызвал Get-PSCallStack в методе assert.Иногда это число может быть даже больше, чем количество строк в указанном файле (т. Е. Местоположение задается как «ScriptFile.ps1 строка 88», но файл содержит только 20 строк).
Есть ли проблема страссировка стека в powershell или есть что-то, чего я здесь не понимаю?
Редактировать
По запросу я публикую пример, который должен давать такие же результаты
Tester.ps1
#File 1 (Tester.ps1)
#Creates the tester object
$tester = (New-Object PSObject);
$tester | Add-Member -MemberType ScriptMethod -Name AssertTrue -Value {
param($expression);
$stackFrame = (GEt-PSCallStack)[1];
try{
$result = &$expression;
if($result -eq $true){
$this.LogPass();
}else{
$this.LogFailure("Evaluation Failed expected ""$true"" got ""$false""", $stackFrame);
}
}catch [Exception]{
$this.LogFailure("Unexpected exception encountered", $stackFrame);
}
}
$tester | Add-Member -MemberType ScriptMethod -Name LogPass -Value {
#Do nothing
};
$tester | Add-Member -MemberType ScriptMethod -Name LogFailure -Value {
param($message, $stackFrame);
"Failure Encounterd";
"Command: $($stackFrame.Command)"
"Location: $($stackFrame.Location)";
"Message: $message";
}
return $tester;
TestCase.ps1
#File 2 (TestCase.ps1)
#Runs the tests using the tester object
$tester = &(Resolve-Path "Tester.ps1");
function TestFailure($tester){
$expression = {$false};
$tester.AssertTrue($expression);
}
TestFailure($tester);
Актив вызывается в 7-й строке TestCase.ps1, а стек вызовов захватывается в 9-й строке Tester.ps1.
Это печатает
Failure Encounterd
Command: TestFailure
Location: Tester.ps1: Line 9
Message: Evaluation Failed expected "True" got "False"
Команда верна, но и файл, и строка неверны
Следующий кадр трассировки стека правильно описывает, где TestFailure ()вызывается с его местоположением "TestCase.ps1: строка 11"