如何测试fabric任务

12 投票
1 回答
1800 浏览
提问于 2025-04-18 15:59

有没有人成功测试过他们的fabric任务?有没有什么库可以帮助实现这个?

我对补丁和模拟有一定了解,但在fabric中这挺困难的。我也看过fabric自己的测试套件,但可惜没什么用,而且在fabric的文档中似乎也没有相关的主题。

这些是我想测试的任务……如果可以的话,我希望避免启动虚拟机。

任何帮助都非常感谢,提前谢谢大家!

1 个回答

6

免责声明:下面提到的功能测试和系统测试是同一个意思。由于大多数Fabric项目没有正式的规范,所以这两者的区别并不重要。此外,我可能会在功能测试和集成测试之间随意使用这两个术语,因为它们之间的界限在任何配置管理软件中都变得模糊。

在本地进行Fabric的功能测试很难(甚至不可能)

我很确定,如果不启动虚拟机(VM),或者不进行非常非常复杂的模拟,就无法进行功能测试。你提到的这些都是限制条件。

考虑一下下面这个简单的函数:

def agnostic_install_lsb():
    def install_helper(installer_command):
        ret = run('which %s' % installer_command)
        if ret.return_code == 0:
            sudo('%s install -y lsb-release' % installer_command)
            return True
        return False

    install_commands = ['apt-get', 'yum', 'zypper']
    for cmd in install_commands:
        if install_helper(cmd):
            return True

     return False

如果你有一个任务调用了agnostic_install_lsb,那么你怎么能在本地机器上进行功能测试呢?

你可以通过模拟runlocalsudo的调用来进行单元测试,但在更高层次的集成测试方面就没什么办法了。如果你只满足于简单的单元测试,那么除了mocknose之外,几乎不需要其他测试框架,因为你的所有单元测试都在严格控制的条件下运行。

你该如何进行模拟

你可以模拟sudolocalrun函数,将它们的命令记录到一组StringIO或文件中,但除非我漏掉了什么聪明的办法,否则你还需要非常小心地模拟它们的返回值。继续说一些你可能已经知道的事情,你的模拟要么需要了解Fabric的上下文管理器(这很难),要么你需要模拟你使用的所有上下文管理器(这也很难,但没那么糟糕)。

如果你想走这条路,我认为更安全、更简单的方法是构建一个测试类,其设置会实例化所有上下文管理器、runsudo和你使用的Fabric的其他部分的模拟,而不是试图在每个测试中进行较少的模拟。这样一来,你就建立了一个相对通用的Fabric测试框架,或许可以在PyPi上分享,叫它“mabric”怎么样?

我认为这对大多数情况并没有太大用处,因为你的测试最终关心的是如何执行,而不仅仅是执行的结果。将命令从run('echo "cthulhu" | sudo tee /etc/hostname')改为sudo('echo "cthulhu" > /etc/hostname')不应该导致测试失败,而用简单的模拟很难做到这一点。这是因为我们开始模糊功能测试和单元测试之间的界限,而这种基本的模拟尝试将单元测试的方法应用于功能测试。


在虚拟机上测试配置管理软件是一种成熟的做法

我建议你重新考虑一下,是否真的想要避免为功能测试启动虚拟机。这是Chef测试的普遍做法,它面临着许多相同的挑战。

如果你担心自动化的问题,Vagrant在从模板创建虚拟机方面做得非常好。我甚至听说Vagrant和Docker的集成也不错,如果你是Docker的粉丝。唯一的缺点是,如果你是VMWare的粉丝,Vagrant需要VMWare Workstation(需要花钱)。另外,你可以选择使用Vagrant和Virtualbox,这样是免费的。

如果你在像AWS这样的云环境中工作,你甚至可以选择启动与生产服务器相同基础镜像的新虚拟机,专门用于测试。当然,一个显著的缺点是这会花钱。不过,如果你已经在公共云中运行完整的软件堆栈,那么这并不会占用你太多的成本,因为测试服务器一个月只会运行几个小时。

总之,有很多方法可以在虚拟机上进行全面的功能测试,这对于其他配置管理软件来说是一种经过验证的技术。

如果不使用Vagrant(或类似工具),保持一套可在本地执行的单元测试

让你的测试依赖于运行虚拟机的一个明显问题是,这会让开发者的测试变得困难。尤其是在需要对本地代码版本进行多次测试的情况下,某些项目(例如Web UI开发)可能会需要这样做。

如果你使用Vagrant + Virtualbox、Docker(或原生LXC)或类似的解决方案进行测试虚拟化,那么本地测试并不会特别昂贵。这些解决方案可以在不到十分钟的时间内在便宜的笔记本电脑硬件上启动新的虚拟机。对于特别快速的迭代,你可能能够在同一个虚拟机上进行多次测试(然后用一个新的虚拟机进行最终测试)。

然而,如果你在公共云或类似环境中进行虚拟化,而在虚拟机上进行过多测试会很昂贵,那么你应该将测试分为一套可以在本地运行的单元测试和需要虚拟机的集成或系统测试。这套单独的测试允许在没有完整测试套件的情况下进行开发,随着开发的进行,运行单元测试。然后,在合并/发布/签署更改之前,应该在虚拟机上运行功能测试。

最终,任何进入代码库的内容都应该通过功能测试,但你应该尽量实现尽可能全面的单元测试覆盖率。你能做的越多来增强单元测试的信心,就越好,因为这可以减少系统测试的无效(且可能昂贵)的运行次数。

撰写回答