跳过主要内容

保存的文章

单元测试shell脚本:
第四部分

Dave Nicolette |领导敏捷
Dave Nicolette
读: 单元测试shell脚本:第四部分

单元测试

到目前为止,在这个关于单元测试shell脚本的系列文章中,我们已经介绍了几种用常见的*nix shell语言编写的单元测试脚本工具,比如bash、korn和zsh。相同的概念和方法适用于任何shell。

到目前为止,所涉及的工具是用于*nix系统上的shell语言的通用测试框架:shunit2、BATS、zunit、bash-spec和korn-spec。还有一些单元测试框架被设计来支持特定的用例,如Pester(用于Powershell)、t-rexx(用于Rexx)、ChefSpec(用于Chef recipes)和rspec-puppet(用于Puppet)。

在第4部分中,我们将看一看纠缠, Powershell的单元测试框架。

什么是powershell?

PowerShell是一种针对系统管理任务量身定制的Windows导向的脚本语言。它采用MicrosoftWindows®100预装,它可以安装在早期版本的Windows以及基于Debian和Debian的Linux Distras上,无论是主机还是客户操作系统,也可以在Windows子系统下的Windows主机上运行Linux。

我希望PowerShell对需要管理Windows实例的系统管理员来证明有用。Linux支持的原因可能是使用Linux系统帮助系统管理员来管理远程Windows实例。(我没有关于该内部的内部信息;它似乎只是一个合理的假设。)您可以对远程计算机执行PowerShell命令和脚本。我不希望PowerShell到Upplant * nix shell语言,以便使用Windows以外的平台。

文档简介

通常情况下,微软的官方文档很难浏览。许多人求助于像StackOverflow亚傅体育app这样的资源来学习如何使用任何给定的工具来执行任何给定的任务。Powershell目前正在积极开发中,情况变化很快。你在微软官方世界之外找到的建议和例子可能已经过时了。你会从“随机”资源中得到各种矛盾的建议和无效的示例脚本。亚傅体育app合理的警告。

什么是纠缠?

Pester是一个PowerShell模块,提供了来自良好的单元测试框架或库的大部分功能。它在Windows 10上预装了,虽然纠纷项目网站建议在开始使用它之前升级到最新版本。我将第二个推荐,因为我遇到从Windows 10上的项目站点运行Sample-Planet.tests.ps1脚本,即使它在Linux上运行良好。升级修复了问题。

我们的测试主题

我们一直在使用Vivek Gite的示例脚本来检查磁盘使用情况,并可选地发送电子邮件通知。这是一个标准的*nix shell脚本,不能在Windows上运行。为了保持一致性,我们应该创建一个执行等价任务的Powershell脚本。

在以前的分期付款中,我们开始使用现有脚本并写入单元测试用例以覆盖它。在这里,我们有机会使用单元测试框架来测试驱动新脚本。

对于没有应用程序开发背景的读者来说,这可能是一种不熟悉的方法。这是系统管理员和基础设施工程师从软件工程世界中获得的开发技能之一,因为devops在业界取得了进展。

我不想给出测试驱动的发展(TDD)对纠缠和Powershell是独一无二的。我们可以使用相同的方法使用任何单位测试框架或库以任何语言开发脚本。这就是这样,我们需要立即编写新的PowerShell脚本。

测试驱动解决方案的第一步是考虑我们需要代码的代码。回想一下,如果利用率为90%或更高,则返回Vivek的脚本检查磁盘使用情况并发出电子邮件通知。我们以前的测试脚本包含两种情况:

  • 确保硬盘利用率为89%时不发送通知
  • 当磁盘利用率为90%时,确保发送通知

为了我们的立即目的,我们可以考虑那些我们的“要求”。

下一步是编写一段代码,作为新脚本的客户端,并断言针对我们设置的特定前提条件所期望的结果。第一种情况的前提条件是磁盘利用率保持在89%。本例中的“代码段”将是一个Pester函数。

佩斯特使用行为样式语法来表达测试用例和断言结果,功能名称如描述语境, 和.对于使用过另一种行为风格框架(如Rspec)的人来说,这些名称应该很熟悉。它们遵循通常的接受两个参数的模式:一个描述函数意图的字符串,一个包含测试代码的闭包或块。Pester还使用了两种常见的行为风格断言模式之一:应该.(另一个是预计;您在上一期间看到了Bash-Spec。)

这是一些纠缠码的样本让我们开始:

$here = (Split-Path -Parent $ myinvoke . mycommand . path)。美元在这里\磁盘使用情况。ps1 description 'disk - usage ' {Context 'disk usage is below threshold' {It 'issue no notification when disk usage is 89%' {Mock Get-WmiObject {[PSCustomObject]@{Size = 100;FreeSpace = 11}} Mock Send-MailMessage NotifyWhenThresholdExceeded -Threshold 90.0 Assert-MockCalled Send-MailMessage -Times 0}}}

这里需要注意的一件事是,行为风格的语法使测试用例非常容易遵循。帮助人们理解代码意图的工具是非常有益的,因为在任何企业IT环境中,软件专业人员的时间是单个最大的成本。这个值与我们必须维护的测试用例和测试脚本的数量成正比增加。

DOT命令意味着源是外部脚本;这与* nix shell相同。有什么不同的是,我们必须从Windows掩盖它的位置挖掘当前的工作目录名,而不是假设“。\'指向它。

当我们使用TDD时,我们的实际脚本文件尚不存在。我们假设它的名称将是磁盘用法.PS1,它将驻留在与测试脚本相同的目录中。我们知道那个文件不存在。没关系;它是TDD过程的一部分。

初始测试脚本显示了描述语境, 和例证的功能,即使我们不严格需要一个语境在此阶段阻塞。RealWorld®测试脚本可以比这个例子复杂得多,并且语境关键字将更加明显。

我们先做一些假设。我们将在继续的过程中完善测试脚本。现在,我们假设磁盘使用情况。ps1脚本将有一个名为notifywhenthresholdexceded的函数,它接受一个类型为-Threshold的参数(参数值中的小数点建议该类型)。

我们也在假设NotifyWhresholdExceeded函数将在需要发出通知时调用PowerShell cmdlet发送mailmessage。我们正在使用PESTS的内置模拟支持来定义一个MACK-MAILMESSAGE。这将阻止生成真正的电子邮件,以及给我们一个机制来检查是否被测的代码是否称为模拟。这在这里很有用,因为NotifyWhresholdExceeded函数不会返回值。

另一个模拟Get-WMIObject将返回大小和氟普拉斯的值,该空间通常会从PowerShell命令返回,该命令返回卷上的总空间和使用空间,如下所示:

get-wmiobject win32_logicaldisk -filter“deviceId ='c:'”

因此,我们假设Disk-Usage.ps1脚本将调用powershell命令来查找磁盘使用信息。当然,该代码尚不存在。

从功能上讲,所有这些都是我们在其他测试脚本中所做的事情。这里我们使用Powershell和Pester的工具来实现。

现在我们准备开始TDD周期:红色,绿色,重构。我们运行测试脚本,希望它失败,因为我们没有定义一个名为NotifyWhenThresholdExceeds的函数。如果它因为任何其他原因而失败,那就意味着我们没有正确地设置测试用例。当我尝试它时,我得到了这些错误消息:

.:术语‘C:用户\[东西]\磁盘使用。Ps1 '不被认为是cmdlet、函数、脚本文件或可操作程序的名称[…]Disk-Usage.Tests。ps1:2, char:3 CommandNotFoundException: The term 'NotifyWhenThresholdExceeded' is not recognized as The name of a cmdlet, function, script file, or operable program[…]Disk-Usage.Tests。ps1:第9行

这正是我们所期待的,所以我们使用“红色是有原因的”。没有磁盘使用情况这样的文件。ps1,并且没有NotifyWhenThresholdExceeded这样的函数。然而。

TDD循环中的下一步是使测试用例“绿色”;换句话说,做到这一点通过.使它通过的最小代码是一个函数声明。让我们创建一个文件Disk-Usage。Ps1,内容如下:

function notifywhenthresholdexceded ([double]Threshold = 90.0) {}

这一次,测试脚本Disk-Usage.Tests。Ps1运行没有错误。我们已经达到了TDD循环中的“绿色”步骤。

对于TDD新手的注意事项:很明显,这种实现是不正确的。它什么都做不了。它不是“决定”不发出通知。对于使用TDD的正在进行的工作来说,这是很正常的。排除其余功能的方法是定义额外的单元测试用例,“强迫”我们编写必要的代码。

在继续下一个“红色”步骤之前,我们需要进行“重构”步骤,即TDD循环中的第三步。我们寻找机会简化和清理代码。目前没有什么可做的,因为我们才刚刚开始。检查代码并明确决定不重构仍然是一个好习惯,而不是假设重构是不必要的。

接下来,我们需要检查磁盘在阈值90%的阈值的情况下。我们将添加另一个函数到我们的测试脚本,导致:

$here = (Split-Path -Parent $ myinvoke . mycommand . path)。美元在这里\磁盘使用情况。ps1 description 'disk - usage ' {Context 'disk usage is below threshold' {It 'issue no notification when disk usage is 89%' {Mock Get-WmiObject {[PSCustomObject]@{Size = 100;FreeSpace = 11}}模拟Send-MailMessage NotifyWhenThresholdExceeded) 90.0 Assert-MockCalled Send-MailMessage两度0}}上下文的磁盘使用量达到或超过阈值{这一封电子邮件通知,当磁盘使用量的问题是90%的{模拟Get-WmiObject {[PSCustomObject] @{大小= 100;free = 10}} Mock Send-MailMessage NotifyWhenThresholdExceeded -Threshold 90.0 Assert-MockCalled Send-MailMessage -Times 1}}}

第二个测试案例与第一箱非常相似。我们设置get-wmiobject模型来表示90%的磁盘使用情况,我们断言发送邮件Message Mock一次一次。当我们运行测试脚本时,我们希望看到第一个案例传递,第二个案例失败了解了正确的原因。

当我在这里运行它时,我得到了以下输出:

上下文磁盘使用量低于阈值[+]问题时没有通知磁盘使用量89% 55 ms上下文磁盘使用量达到或超过阈值[-]发出电子邮件通知,当磁盘使用量为90% 77 ms预期Send-MailMessage被称为至少1次但被称为0次

这是我们预期的结果。现在我们需要向Disk-Usage添加一些逻辑。Ps1脚本使两个测试用例都通过。以下是一个粗略的实现:

function NotifyWhenThresholdExceeded ([double]Threshold = 90.0) {$diskusage = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'" " $size = $diskusage. "大小$used = $ Size - $diskusage。$percentused = ($used / $size) * 100 If ($percentused -ge $Threshold) {Send-MailMessage -From "sender" -To " receiver " -Subject "Oh, no!"-Body“磁盘空间不足!”}}

这次我们得到:

背景信息硬盘利用率低于阈值[+],当硬盘利用率为89% 43ms时,发出无通知。当硬盘利用率高于阈值[+],当硬盘利用率为90% 50ms时,发出邮件通知

就这些。

代码覆盖率

Pester可以计算代码覆盖率指标,很像应用程序编程语言的测试框架。获取Disk-Usage.Tests的覆盖率指标。ps1脚本,我们可以这样执行Pester:

Invoke-Pester \ Disk-Usage.Tests。ps1 -CodeCoverage \ Disk-Usage.ps1

这将导致如上所示的输出,然后是:

在1.04s测试中完成的测试通过:2,失败:0,跳过:0,待定:0,不确定:0代码覆盖报告:在1个文件中介绍了100.00%的7分析命令。

当然,当您有大量的测试用例和文件时,这类信息要有用得多。这是大多数shell语言测试框架中没有包含的有用特性。

一些警告

熟悉基本软件测试技术的读者可以在座位上蠕动。两个测试用例几乎足以提供强大的潜在误差检测。例如,当传递无效或空的参数或呼叫者取决于阈值的默认值时,我们未验证代码的行为。

此外,“低于阈值”的情况可能由于除磁盘使用以外的任何原因而通过。Ps1脚本故意“决定”不发出通知。假阳性的风险很高。

还有一件事:按照我们为Send-MailMessage编写模拟逻辑的方式,如果测试中的代码多次调用Send-MailMessage,则测试用例将通过。我们真的想确认它被调用了确切地一次。所以,有改进的余地。

请记住这篇文章的目的是展示如何使用Pester模块与PowerShell写入可执行单元测试。它并不意味着全面的测试练习。从这个起点,您可以根据专业环境酌情填充测试套件。最简单的方法是继续重复TDD周期,在您对套件的质量和覆盖感到满意之前,添加了您可以想到的任何条件。至少,这就是我们通常在RealWorld®中进行的方式

下一步是什么?

我们已经探讨了* NIX平台上的通用外壳脚本的少数单位测试框架,以及PowerShell的一个这样的框架。接下来,我们将查看服务器供应工具,厨师和木偶的两个专用单元测试框架。

下一个;单元测试shell脚本:
五个部分

自1977年以来,Dave Nicolette一直是IT专业人士。他在各种技术和管理角色方面服役。自1984年以来,他主要担任顾问,在管理营中保持一英尺。

留下你的评论

您的电子邮件地址将不会被公布。必填字段已标记