1

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

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

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

在实践中,我发现powershell返回的信息似乎是错误的。第二个堆栈帧按预期引用正确的文件,但始终给出我在 assert 方法中调用 Get-PSCallStack 的行号。有时,这个数字甚至可能高于给定文件中的行数(即,位置给出为“ScriptFile.ps1 第 88 行”,但文件只有 20 行)。

powershell 中的堆栈跟踪是否有问题,或者我在这里不理解什么?

编辑

根据要求,我发布了一个应该产生相同结果的示例

测试者.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;

测试用例.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:第 11 行”

4

1 回答 1

2

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

根据这个报告的问题: https ://connect.microsoft.com/PowerShell/feedback/details/531086/depending-on-how-you-invoke-a-script-block-the-invocation-details-may-not-从脚本块内部可用#

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
于 2010-08-24T15:48:42.470 回答