Powershell的堆栈跟踪是否已损坏?

时间:2010-08-24 10:17:23

标签: powershell stack-trace stackframe

我在powershell中编写一个简单的单元测试工具

我设计了线束,使其断言函数将脚本块作为参数,以允许线束从断言函数中运行代码,并将任何异常视为测试失败。

如果测试失败,我想在测试失败的单元测试中返回行。我的计划是通过在每个断言方法的开头采用堆栈跟踪(Get-PSCallStack)并使用第二个堆栈帧的信息来做到这一点,我假设它应该对应于调用断言函数的行。

在实践中,我发现powershell发回的信息似乎是错误的。第二个堆栈帧指的是正确的文件,但总是给出我在断言方法中调用Get-PSCallStack的行号。有时这个数字可能甚至高于给定文件中的行数(即,Location是“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);

在TestCase.ps1的第7行调用断言,并在Tester.ps1的第9行捕获调用堆栈

打印

Failure Encounterd
Command: TestFailure
Location: Tester.ps1: Line 9
Message: Evaluation Failed expected "True" got "False"

命令正确但文件和行都是错误的

堆栈跟踪的下一帧正确描述了调用TestFailure()的位置,其位置为“TestCase.ps1:Line 11”

1 个答案:

答案 0 :(得分:2)

它不是您使用的断言函数,它是用作“成员函数”的断言脚本块。但它仍然是一个脚本块。

根据此报道的问题: https://connect.microsoft.com/PowerShell/feedback/details/531086/depending-on-how-you-invoke-a-script-block-the-invocation-details-may-not-be-available-from-inside-the-script-block#

从脚本块调用Get-PSCallStack有问题。所以,你的问题的答案可能是:是的,这是一个PowerShell问题。

好吧,我建议你使用功能。我重新考虑你的脚本使用函数(脏版本,坏名称等),它们按预期工作:

#File 1 (Tester.ps1)
#Creates the tester object

function AssertTrue {
    param($expression);

    $stackFrame = (Get-PSCallStack)[1]

    try{
        $result = . $expression;
        if($result -eq $true){
            LogPass
        }else{
            LogFailure ("Evaluation Failed expected ""$true"" got ""$false""") $stackFrame
        }
    }catch [Exception]{
        LogFailure "Unexpected exception encountered" $stackFrame
    }
}

function LogPass {
    #Do nothing
}

function LogFailure {
    param($message, $stackFrame);
    "Failure Encounterd";
    "Command: $($stackFrame.Command)"
    "Location: $($stackFrame.Location)";
    "Message: $message";
}

#File 2 (TestCase.ps1)
#Runs the tests using the tester object

. (Resolve-Path "Tester.ps1");

function TestFailure {
    $expression = {$false};
    AssertTrue $expression
}

TestFailure