PowerShell模块函数无法访问调用者范围内的变量

时间:2016-09-03 11:04:22

标签: powershell selenium-webdriver scope pester

我将Pester与Selenium WebDriver一起使用。 WebDriver初始化为&BeforeAll'阻止相应的'描述'阻止并将结果实例分配给$ driver变量。然后,在' Describe'和'它'块我调用驻留在PowerShell自动加载的外部PowerShell模块中的自定义函数。我希望这些函数可以访问在&BeforeAll'之前定义的$ driver变量。阻止,但它没有发生,我收到以下错误信息:

RuntimeException:您无法在空值表达式上调用方法。

以下是Search.Tests.ps1 Pester脚本的代码:

Describe "Search for something" -Tag something {    

BeforeAll {
    $driver = New-WebDriver
    $driver.Navigate().GoToUrl('http://example.com')
}

AfterAll {
    $driver.Close()
    $driver.Dispose()
    $driver.Quit()
}

Find-WebElement -Selector ('some_selector')

    It "Something is found in search results" {
        GetTextFrom-WebElement -Selector ('some_selector') | Should Be 'something'
    }
}

Find-WebElement和GetTextFrom-WebElement是辅助函数,它们使用$ driver通过CSS获取元素并提取元素的内部文本。

我调查了这个问题并找到了解决方法,但我认为这不是一个优雅的方法。解决方法是在param块之后立即重新定义外部PowerShell模块中每个帮助器函数中的$ driver:

$driver = $PSCmdlet.GetVariableValue('driver')

这样功能可以看到$ driver,一切正常。

我的问题:是否可以执行某些操作,因此函数始终可以访问$ driver而无需在每个驱动程序中重新定义驱动程序?

1 个答案:

答案 0 :(得分:2)

  

“我希望这些函数[在PowerShell模块中定义]可以访问'BeforeAll'块中定义的$ driver变量...”

他们没有,你可能不应该依赖这种行为,即使他们这样做了。

Pester Scriptblocks中定义的变量无法从模块访问

BeforeAll{}BeforeEach{}Context{}It{}块中定义的变量 1}}文件由x.Tests.ps1reference)调用。如果恰好直接调用Invoke-Pester文件(即通过在ISE中按 F5 ),则可以从被测模块访问x.Tests.ps1中定义的变量。依靠这种行为可以排除测试大批量运行,因此应该避免。

应避免依赖外部变量的隐式可访问性

似乎您的自定义模块期望BeforeAll{}在模块外部的某处定义,并且可以从模块内部隐式访问。这提出了以下问题:自定义模块的作者在哪里定义$driver?作为模块中的脚本变量?作为全球变量?这两个都是模块的相当笨拙的公共接口,因为很难控制$driver的正确值是否确实可用于模块。如果模块确实依赖于此类行为,我建议更改自定义模块以明确接受您的$driver对象 (或至少创建该对象所需的信息)。

如果您无法更改自定义模块,则可以将变量引用从$driver更改为$driver。你应该尽量避免这种情况,因为以这种方式使用全局变量可能会在某些时候导致任何各种问题。