如何在PowerShell中进行TDD和单元测试?

70

随着微软将powershell推向所有新的服务器产品,我开始(不情愿地)认为我需要认真对待它。其中之一是TDD。您是否找到了对PowerShell脚本进行单元测试的好方法?

我从Mr Geek Noise找到了模拟的示例,但我真的想要像RhinoMocks那样的东西。Brian Hartsock有一个使用MS Test运行Powershell字符串测试的示例。有点hacky,但似乎可以工作。

我想要的是一个干净的Powershell TDD体验,就像在“真正”的语言中一样。


更新以澄清:

前两个答案试图让我远离测试 Powershell。这些意见很有趣。我不想知道在 Powershell 中进行测试是否是一个好主意。那是一个主观的问题,应该在不同的论坛中提问。我想要一个解决方案来单元测试 Powershell。如果您认为这是一个坏主意(可能是),请将其视为一个有趣的学术问题。

  • 是的,脚本语言将不同的系统粘合在一起。然而,正如已经指出的那样,在动态语言中也很容易模拟和破坏接口。
  • 我不是在问“调试”。调试是一个非常有用的话题。我会让其他人来问它。
  • 也许 PS 脚本应该简单。语言支持模块化,即使是一个坏主意,复杂的过程也是不可避免的。
  • 这个问题的答案不是“你不能”。我可以看到(从链接的博客 - 这些博客有点旧)一些人已经在这个问题上取得了进展。

重新声明:如何实现类似 xUnit 的自动化测试 Powershell 逻辑? 集成测试很有趣,打破依赖关系的单元测试最有趣。


1
请查看 https://dev59.com/vHNA5IYBdhLWcg3wVcP6,其中有一个类似的问题,并提供了一些链接(PSUnit和Lee Holmes帖子)。 - stej
1
永远不要小瞧PowerShell。它能以最少的代码实现极其强大的功能。 - D3vtr0n
6个回答

46

2
比 PsUnit 更好的设计。它不需要与配置文件或安装程序打交道。我已经获取了它并将在本周开始使用。 - Precipitous
3
这里有一篇由Scott撰写的博客文章,讨论了Pester的使用,它是一个供系统管理员使用的BDD框架。 - Ameer Deen
1
我写了一个三部曲的关于使用Pester进行PowerShell TDD的系列文章 -- 请参阅实用的PowerShell单元测试 - Michael Sorens

11

PsUnit 已经更新了一个框架。我几个月前也遇到过和你一样的问题,觉得 PsUnit 对于我需要编写的脚本来说太过庞大和复杂,所以我为 PowerShell 编写了自己的单元测试框架。

PowerShell 和其他脚本语言(例如 Python)具有相同的特征,即您可以在任何时候覆盖函数,甚至可以在测试方法中使用作用域进行伪造(即模拟)。也就是说,如果您要测试依赖其他函数的函数或对象,您可以在测试方法中声明它们,以创建一个本地的虚假实现。

因此,无论您选择使用哪种测试框架,我都认为 PowerShell 非常容易进行测试驱动开发。这至少是我的经验。


1
PsUnit非常棒且轻量级。 - Ian Patrick Hughes

3

我认为你在询问的是“测试策略”,而不是具体的TDD,所以我会回答这两个问题。

在PowerShell中,你的大部分工作将涉及通过cmdlets和对象管道集成许多不同的系统。如果你想要确信你的PowerShell脚本能够正常运行,请尽可能地投入精力构建一个完美的分段环境,以便尽可能准确地测试所有这些系统。

在完美的分段环境中运行你的脚本将比通过TDD “充实你的设计”或使用事后单元测试“测试你的代码意图”更有价值。

以下是一些可能有用的小提示:

  • 内置cmdlet上存在-whatif开关。我刚发现你也可以这样做:-whatif:$someBool - 你需要时就知道它的用处。
  • V2中即将推出的ISE带有调试器。非常好。
  • 你总是可以在C#中编写自定义cmdlet并在其中执行任何操作。

嗯...你也怀疑这是可能的。请注意,Geek Noise博客展示了模拟(不同系统)的解决方案。 - Precipitous
我认为这是可能的,但谁在乎呢?知道你在测试和脚本中都输入了“\server\fileshare”有什么价值呢?你要么过度指定与外部 cmdlet 的交互,要么只测试自己系统内的交互(这最终将成为你脚本的非常小的一部分)。我想这也有价值,但是,如果可能的话,在一个分阶段环境中进行真正的测试(并在生产环境中进行测试)将带来更大的收益。 - Peter Seale
2
系统测试和单元测试都是必需的,没有哪一个能带来“更大的好处”。如果我正在测试“与外部 cmdlet 的交互”,那么这不是一个单元测试。以下是一个常见逻辑的微不足道的示例,它受益于单元测试/模拟:我们有一个发布后脚本,在 Windows 事件日志中识别有趣的错误 - 排除垃圾邮件。Posh 在这里表现出色 - 不需要 cmdlet。筛选条件是复杂而微妙的。将 where-object 条件提取到函数中并测试各种输入。很容易想出其他例子。 - Precipitous

1
我是一名有用的助手,可以为您翻译文本。
我正在编写一些基本的PowerShell脚本,并采用以下模型进行TDD:
首先,在SUT_spec.ps1中编写规范:
Import-Module -Name .\my_SUT.ps1

$case1_input=@{}
$case1_output=@{}
f1 $case1_input $case1_output

$case1_result = $case1_output["Output"] -eq "expected"
"f1 case1: $case1_result"

# repeat for all test cases

Remove-Module -Name my_SUT

其次,我的单元(SUT)是在my_SUT.ps1文件中作为一个函数存在:

function f1($the_input, $the_output)
{
    #take input from $the_input hashtable, process it and put output into $the_output hashtable.

    $the_output["Output"]="results"
}

第三,发布的主入口点作为一个单独的文件,类似于SUT_spec.ps1,但是其输入来自实际的外部来源。

0

虽然这个讨论已经死了,但相关问题仍然非常活跃。

在讨论PS单元测试的实用性时,我看到一个缺失的东西是企业系统中模块的使用。想象一下,在一个企业设置中,有一个中央存储库,用于实现PS中的常见网络/文件级任务。在这种情况下,你有少量的开发人员和网络专家,他们都有略微重叠的职责。一个开发人员创建了一个封装业务逻辑的模块,并且它的实用性立即得到了认可,以至于其他人很快就加入并将该模块纳入自己的工作中。该模块包含在从一次性交互式脚本到中型客户端应用程序的任何内容中;虽然有些人可能不同意使用shell脚本语言的用例,但在这个领域,进化是不断的。

在这种情况下,我认为有价值的是为这些常见模块定义一组“合同”来遵循。如果知识共享对组织至关重要,那么可能会有多个人修改这些模块。通过单元测试验证模块的完整性将有助于维护秩序、最小化混乱,从而维持(甚至增加)模块本身的价值。

关于首选方法,我还没有采用任何一种。PS让人想起流体/动态/敏捷的物质。将其限制在像TDD这样的刚性结构中感觉不自然。然而,考虑到上述情况,这个目标不能被忽视。不管怎样,我很纠结,很抱歉浪费了您的时间。谢谢阅读。

这听起来有些类似于我几年前在“PowerShell&.Net-构建工具包系统”下博客中写的内容 - http://chrisoldwood.blogspot.co.uk/2011/11/i-first-came-across-com-back-in-mid-90s.html。我已经在PS中编写了很多粘合剂,如果我能够对其进行单元测试,尤其是错误处理,那将更加舒适,因为在测试环境中往往很难模拟。 - Chris Oldwood

-3
从你的问题中,我认为你可能会失望。Powershell只是一个小型命令行语言。当然,它可以做任何C#能做的事情,甚至更多,但汇编语言也可以。当然,它也是面向对象的,并且与.NET库连接在一起,但C#是一种更加清晰的语言。
如果一个解决方案比一行代码还长,或者你认为需要进行TDD测试,那么你不应该使用Powershell。它是一种充满惊喜的神秘语言,对于任何复杂的事情都要避免使用。
如果你想做一些临时搜索和替换或格式化文本,或者在文件系统中查找,那么Powershell就是你的好朋友。你真正想做的是每天都用一点,经常重复自己,以便熟悉语法。出于这个原因,也要避免使用开源的Powershell库,忘记编写自己的CmdLets,除非你有一个非常专业的用例来进行临时命令行使用。管道绑定规则是神秘而丑陋的。
当然,这只是我的观点,但我是一位长期使用Powershell的用户,现在我看待它的方式让我感到更加愉快。

2
我认为 PowerShell 脚本会被编写,因为微软正在大力推动它。它很快就会变得有用。由于将编写 PS 脚本并且它们将成为程序(不管多么卑微),我希望它们是健壮的。所以,我想要对它们进行测试。你可能不同意,但那么,让我们把这称为一次学术演习:你如何对 PowerShell 脚本进行单元测试?实际结论可能是它太难了(我认为不是不可能),如果我坚持追求质量,我应该使用 IronPython 来代替脚本。 :) - Precipitous
没有人怀疑在Powershell中进行TDD是可能的。毕竟,Powershell可以做到C#所能做的一切,甚至更多。理论上,Powershell的函数性质可以使它成为比C#更好的测试语言。问题只是Powershell的语法和总体设计...嗯,丑陋而令人惊讶。等你用了一年后再来谈谈吧... - Mike
1
我至少已经使用PS三年来进行日常工作(主要是因为其强大的文件功能)-我们现在可以交流了 :) 我同意它很丑。然而,它可以连接到很多功能。这些惊喜就是我想要测试它的原因。 - Precipitous
1
顺便说一句,每当我问一个 Powershell 相关的问题时,我经常会得到告诉我不要使用 Powershell 的答案,很少能得到实际的回答,所以我意识到这很烦人。非常抱歉!但是在某些情况下,Powershell 可能是您唯一的选择,比如在客户现场。 - Mike
我喜欢PowerShell,我使用和学习它的时候越来越喜欢!我认为有很多像我一样热爱它的人。而且不要忘记PowerShell现在已经成为Visual Studio的重要组成部分,以NuGet包管理器控制台的形式存在。 - knut
多年过去了,我仍然感觉一样。我在这里只是因为我注意到我经常从这个答案中失分。那就这样吧。话虽如此,我仍然是一个PowerShell用户,有时候它很方便,只是每次回到它身上,我都得重新学习。它就是不粘。顺便说一句,有时候更好的选择是JavaScript。 - Mike

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接