当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 使用 Pester 编写 PowerShell 测试:入门

作者:精品下载站 日期:2024-12-14 20:48:30 浏览:13 分类:玩电脑

使用 Pester 编写 PowerShell 测试:入门


这是我的书《The Pester Book》中的两章示例。如果想学习如何测试 PowerShell 代码,单元测试框架 Pester 是事实上的方法。这是介绍章节。 Pester 书有 200 多页真实的深入示例,涵盖了 Pester 和测试方法的各个方面。

那么您准备好通过编写测试来进行 PowerShell 开发的下一步了吗?那太棒了!为了让您了解本书的内容,我们来看看如何使用 PowerShell 模块 Pester 编写 Powershell 测试。

无论您是专业软件开发人员还是周末 PowerShell 脚本编写者,Pester 都是测试 PowerShell 代码所需的工具。

安装 Pester

Pester 预安装在 Windows 10 及更高版本以及 Windows Server 2016 或更高版本上。 Pester 目前可以恢复到 PowerShell v2。如果安装了 PowerShell 包管理器,则可以使用 Install-Module 命令安装 Pester。如果没有,请前往该项目的 GitHub 页面将其下载为 ZIP 文件。当您解压 ZIP 文件时,Pester 需要位于您的 C:\Program Files\WindowsPowerShell\Modules 文件夹或“PSModulePath”环境变量中的任何其他文件夹中。您可以通过运行 $env:PSModulePath 来查看此环境变量。

此外,当您下载 Pester 时,您的浏览器可能会将下载的 ZIP 文件标记为潜在不安全。如果是这样,请在解压 ZIP 文件之前使用 Unblock-File 命令解锁 ZIP 文件。您还可以右键单击该文件,然后从 Windows 资源管理器中选择“属性”以查找“取消阻止”按钮。

创建 PowerShell Pester 测试

在安装了 Pester 的 PowerShell 控制台中,您可以快速创建一个简单的项目。 Pester 提供了一个名为 New-Fixture 的命令,该命令构建了单个 PowerShell 脚本和测试文件以供使用。然而,这个命令现在被认为是遗留的,并将从未来的 Pester 版本中删除。不过,不用担心,创建一个简单的测试很简单。

要构建 Pester 测试,您至少需要两个文件:一个包含要测试的代码的 PS1 脚本和一个测试脚本文件。在某处创建一个名为 Pester101 的文件夹,一个名为 Pester101.ps1 的 PS1 脚本以及一个名为 Pester101.Tests.ps1 的关联测试脚本文件。下面是一些可以为您完成此操作的代码。

PS> New-Item -Path 'C:\Pester101' -ItemType Directory
PS> New-Item -Path 'C:\Pester101\Install-Pester.ps1' -ItemType File
PS> New-Item -Path 'C:\Pester101\Install-Pester.Tests.ps1' -ItemType File

Install-Pester.ps1 内部,创建一个名为 Install-Pester 的函数(您将了解 Pester loves 函数)并保留它空白的。函数名称可以是任何名称。

function Install-Pester {
    param()

}

创建 Install-Pester.ps1 脚本后,现在将以下代码添加到顶部的 Install-Pester.Tests.ps1 文件中。前三行代码本身与 Pester 无关;这只是一种对 Install-Pester.ps1 内部的函数进行点采购的方法,以便在此测试脚本中可用。下面的描述块就是神奇发生的地方。

$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Tests.", ".")
. "$here$sut"

describe 'Install-Pester' {
    it 'does something useful' {
        $true | Should -Be $false
    }
}

恭喜!您已经正式创建了您的第一个 Pester 测试!

使用 PowerShell 运行测试

现在您已经构建了基本的测试支架,让我们按原样运行测试,看看会发生什么。此时,您尚未将任何代码放入 Install-Pester.ps1 文件中的 Install-Pester 函数中。该函数什么也不做。

如果您还没有这样做,请更改为 C:\Pester101 文件夹,然后运行 Invoke-Pester

PS> cd C:\Pester101
PS> Invoke-Pester

Invoke-Pester 运行时,它将自动在您所在的同一文件夹或任何子文件夹中查找以 Tests.ps1 结尾的任何文件。如果找到,就会运行它。

请注意 [-] 和红色文本。该指标表明测试失败。在该指标下方,它会告诉您原因。在本例中,它失败了,因为布尔值 $false 应该是 $true,正如您可能知道的那样,它是无效的。 Pester 中的单元测试返回 true 或 false。

编写通过的 Pester 测试

所以你失败了,但别担心,我会帮助你通过这次测试。在您喜欢的编辑器中打开 C:\Pester101\Install-Pester.ps1 文件,然后插入一行 Write-Output "Working!" ,如下所示。

function Install-Pester {
    param()
    Write-Output "Working!"
}

保存文件,然后打开 C:\Pester101\Install-Pester.Tests.ps1 文件。将整个 describe 部分替换为以下代码。

describe 'Install-Pester' {
    it 'outputs a string' {
        Install-Pester | Should -Be 'Working!'
    }
}

现在,在 C:\Pester101 文件夹中再次运行 Invoke-Pester 并查看会发生什么。

现在请注意,您的测试已通过 [+] 和绿色文本指示。

PowerShell 测试的工作原理

您现在已经成功完成了在 Pester 中创建和运行测试的所有操作,但是它是如何工作的呢?

  1. 您创建了两个文件; Install-Pester.ps1Install-Pester.Tests.ps1 位于 C:\Pester101 目录中。
  2. Install-Pester.ps1 脚本表示要测试的代码。 Install-Pester.Tests.ps1 脚本包含针对 Install-Pester.ps1 中的代码运行的测试。
  3. 当在 C:\Pester101 目录中运行 Invoke-Pester 时,它会查找以 .Tests.ps1 结尾的所有脚本。
  4. 一旦 Invoke-Pester 找到所有脚本,它就会运行每个脚本(在本例中为单个脚本)。
  5. 当运行 Install-Pester.Tests.ps1 测试脚本时,它会获取 Install-Pester.ps1 脚本,以便 Pester 可以运行 Install-Pester 里面的函数。
  6. 然后,Pester 在测试内部执行该函数(第一次什么都不做),然后将布尔值 $true 与布尔值 $false 进行比较。由于测试预期 $true$false,因此失败。
  7. 在第二轮中,Pester dot 再次获取了 Install-Pester 函数,运行它,这次捕获了 Working! 的输出。然后将该输出与 Working! 的预期输出进行比较。由于它们都是相同的,所以测试通过了。

了解 Pester 块

Pester 的领域特定语言 (DSL) 严重依赖 PowerShell 脚本块。脚本块允许 Pester 分段代码、控制代码的运行方式等等。脚本块将使 Pester 能够完成大部分的单元测试魔法!要了解 Pester,首先必须了解 Pester 用于执行代码的各种脚本块(块)。

在 Pester 的 DSL 中,您将看到六种类型的块:

  • 描述
  • 上下文
  • BeforeEach/BeforeAll
  • AfterEach/AfterAll
  • 模拟

这些块中的每一个都使 Pester 能够控制测试运行时代码执行的顺序、控制范围以确保一个块的活动不会与另一个块发生冲突或允许子范围继承其父级的范围。

描述块

测试文件中的最高级别是描述块。 describe 块是测试的逻辑分组。每个测试文件可以有一个或多个描述块。几乎所有事情都发生在describe块内。如果测试文件包含一个或多个描述块,则描述块是几乎所有其他内容的容器。

与本章介绍的所有其他块一样,describe 块是一个 PowerShell 脚本块,其中包含执行 Pester 测试所需的所有代码。

最简单的describe块由一个名称和一个由左大括号和右大括号指示的脚本块组成。

describe 'Stop-MailDaemon' {
    ## Stuff goes in here
}

描述块还分隔了范围,在执行单元测试时理解这一点至关重要。

上下文块

describe 块的下一层是context 块。 context 块位于 describe 块内部,并提供 it 块的逻辑分组,您接下来将介绍这些块。 context 块(如 describe 块)具有名称和脚本块定义,其中包含 context 块内的代码。它们是可选的,因此与 describe 块不同,它们不必用于构建测试。

describe -Tag 'Linux' 'Stop-MailDaemon' {
    ## Describe-specific code in here
    context 'When the server is down' {
        ## Context-specific code in here
    }
}

Context 块不仅可以让您更好地组织测试,还可以让您定义单独的范围,您将在“模拟简介”一章中了解更多相关内容。

它阻止

It 块是可选 context 块的下一步。 It 块可以位于describe 块或context 块中。 阻止断言对代码的期望。它们包含检查实际状态与预期状态的代码。 It 块是大多数人在谈论 Pester 测试时所指的内容。

It 块有一个名称和一个脚本块定义。 it 块的名称由您决定,但最佳实践是为其测试的状态指定一个描述性名称。请务必查看“测试设计实践”一章以获得一些指导。

例如,如果您正在测试代码是否引发异常,那么一个好的 it 块名称应该是“引发异常”,或者,如果测试中检查脚本是否被执行,则名称可以是“脚本运行”。让你的名字简单明了。

describe -Tag 'Linux' 'Stop-MailDaemon' {
    it 'the script runs' {
        ## Code to compare the state to test with the real state
    }
    context 'When the server is down' {
        it 'throws an exception' {
            ## Code to compare the state to test with the real state
        }
    }
    }
}

一个it块(测试)可以有五个可能的结果之一:

  • [+] 通过:测试已运行,并且满足预期。
  • [-] 失败:测试已运行,但未达到预期。
  • [?] 不确定:测试已运行,但没有通过也没有失败。
  • [!] 已跳过:测试未运行,因为它处于已跳过状态。
  • [?] 待处理:测试未运行,因为它为空或待处理。

我们在“控制测试结果”一章中深入介绍了跳过、待定和不确定的状态。

块之前和之后

默认情况下,Pester 从上到下运行代码。但是,有时您可能需要在任何 it 块之前、之后或之间运行代码。在这种情况下,您将使用一个或多个 BeforeAllBeforeEachAfterAllAfterEach 块。这些块运行在测试运行期间的特定时间执行的任意代码。

这些块可以包含您需要的任何任意代码。他们可能会设置一些日志记录、创建数据库连接或您需要的任何其他内容。它们可以出现在描述上下文块中。这些块是点源到它们出现的上下文描述中的,这意味着它们还可以执行诸如定义变量之类的操作,然后这些变量对任何人都“可见” 块位于相同的描述上下文中。这些块在描述上下文中出现的位置并不重要,它们出现的顺序也不重要。但是,为了提高可读性,通常将 BeforeAll/BeforeEach 块放在 describecontext 块的顶部,并将 AfterAll/AfterEach 块放在底部。

describe -Tag 'Linux' 'Stop-MailDaemon' {
    BeforeAll {
        ## Code in here
    }
    BeforeEach {
        ## Code in here
    }

    it 'the script runs' {
        ## Code to compare the state to test with the real state
    }

    context 'When the server is down' {
        it 'throws an exception' {
            ## Code to compare the state to test with the real state
        }
    }
    }
    AfterEach {
        ## Code in here
    }
    AfterAll {
        ## Code in here
    }
}

这些名称是不言自明的。

  • BeforeAll任何 it 块运行之前运行。
  • AfterAll 在所有 it 块运行后运行。
  • BeforeEach 在每个 it 块运行之前运行 - 这意味着,如果您有五个 it 块,则 BeforeEach 运行五次。
  • AfterEach 在每个 it 块运行后运行。

如果您在 describe 块以及子 context 块中定义 BeforeEach/AfterEach,则首先运行describe 块,然后运行context 块中的块。例如:

describe -Tag 'Linux' 'Stop-MailDaemon' {
    BeforeEach {
        ## Runs first
    }

    it 'the script runs' {
        ## Code to compare the state to test with the real state
    }

    context 'When the server is down' {
            BeforeEach {
                ## Runs second
            }
        it 'throws an exception' {
            ## Runs third
        }
    }
    }
}

您是否曾经在 PowerShell 中使用过 try/catch/finally 块?这就是 Pester 在幕后使用的方法。 Pester 将 Before* 代码放在所有其他代码之前。然后,一旦 it 块或 describe 块完成执行,Pester 就会插入 AfterEachAfterAll 中包含的代码> 块放入 finally 块中执行。

概括

对于任何想要学习编写 PowerShell 测试的人来说,The Pester Book 的两章示例是一个很好的起点。为您的 PowerShell 脚本构建测试肯定会将您的 PowerShell 游戏提升到一个新的水平!

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯