阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

使用 Vagrant 和 Fabric 用于集成测试

419次阅读
没有评论

共计 5276 个字符,预计需要花费 14 分钟才能阅读完成。

在 cloudshare 中,我们的服务是由许多部件组成的。当我们更改一个给定组件的代码后我们总需要测试它。我们小心地尝试着平衡单元测试和集成测试(或系统测试)的总量,以便能够实现合理的代码覆盖率和测试运行时间,最重要的是提升对我们代码的信心。

不久前,我们彻底改写了一个叫网关的组件。这个网关运行在 Linux 机器上,其处理了我们内部的许多路由,防火墙,NAT,负载平衡以及流量日志等很多内容。它基本上是一个路由器 / 防火墙,通过获取动态配置并根据它了解的配置实施不同的网络规则。这次改写是通过重新设计其(虚拟)硬件和内核模块完成的。它是一个 Python 应用包使用原始的 debian 打包部署的。

如何使用 vagrant 在虚拟机安装 Hadoop 集群 http://www.linuxidc.com/Linux/2013-04/82750.htm

Vagrant 中高效的 Puppet 模块管理 http://www.linuxidc.com/Linux/2014-05/101873.htm

在重写之前,这个网关是“冰封”的。“冰封”在这里的意思是没有人敢修改它的代码。它没有测试代码,因此每个更改都需要一份完整的手册,单是痛苦的回归测试也需要花一个星期。

我们坐下来定义了我们的目标。我们希望所有的开发人员都能够在本地的机器跑所有的集成测试,并且能够很容易。很容易还意味着在变更代码后不需要部署其他任何东西。需要做的这是在 IDE 中编辑代码然后重新运行测试。不需要提交代码,不需要重新打包,不需要部署(我们在 Windows 上开发)/
当进行测试时就不是那么容易了,你知道会发生什么。

改善集成测试:

我们已经知道需要改善我们的单元测试。但是集成测试呢?那是另一回事。你如何测试你的硬件和内核配置以确保这些配置能完成你所想让它实现的网络魔术。

让我们考虑如何手动来做这个事情。简单的方法是用 Linux 提供的一系列网络工具:ping,traceroute,tcpdump,netcat 等。事实上,这也正是我们 QA 工程师做的事情:

部署新代码.

创建一个 几台 连接到同一个 网关的机器组成的测试平台

对于任何可能的配置,网关都会测试整个网络的功能应该是流畅 / 阻塞 / 跑通 NAT/ 路由 等。

这简直是一场噩梦。

我甚至敢说:不要 QA 工程师,就算他们可能才华横溢,不留死角地涵盖所有情况,或浪费时间(合理数量)。更何况我们希望的是,他们比只是会弄回归测试多一点创意。这实际上是机器的工作,而不是人的工作。

我们终于面临了严酷考验,并开始思考为何这是可能的。Vagrant,那时完全是个新的后备方案,来的如此自然。它允许我们能够创建一个由不同的虚拟局域网连接的虚拟机的环境。Vagrant 还可以让你直接挂载你在主机文件夹到你管理的虚拟机,并且也满足我们的“容易测试”的要求。如果代码已经被挂载在 VM Vagrant,没必要进行部署。

下面是 vagrant 文件, 来定义虚拟环境:

Vagrant::Config.run do |config|
    config.vm.define :gateway do |gateway_config|
        gateway_config.vm.box = "gateway"
        gateway_config.vm.host_name = "gateway"
        gateway_config.vm.box_url = "http://FQDN…./gateway.box"

        gateway_config.vm.network :hostonly, "192.168.58.2", {:adapter => 2, :netmask => '255.255.255.0'}
        gateway_config.vm.network :hostonly, "192.168.56.90", {:adapter => 3, :auto_config => false}
        gateway_config.vm.share_folder "code", "/code", "../../..", :mount_options => ["dmode=755", "fmode=755"]
    end

    config.vm.define :tester1 do |config|
        config.vm.box = "tester"
        config.vm.host_name = "tester1"
        config.vm.box_url = "http://FQDN…../tester.box"

        config.vm.network :hostonly, "192.168.58.91", {:adapter => 2, :netmask => '255.255.255.0'}
        config.vm.network :hostonly, "192.168.56.91", {:adapter => 3, :auto_config => false}

        config.vm.share_folder "code", "/code", "../tests"
    end

    config.vm.define :tester2 do |config|
        config.vm.box = "tester"
        config.vm.host_name = "tester2"
        config.vm.box_url = "http://FQDN…./tester.box"

        config.vm.network :hostonly, "192.168.58.92", {:adapter => 2, :netmask => '255.255.255.0'}
        config.vm.network :hostonly, "192.168.56.91", {:adapter => 3, :auto_config => false}

        config.vm.share_folder "code", "/code", "../tests"
    end
… more testers machines defined here ...

 

如你所见,本地源码呗挂载 / 编写在 vagrant 虚拟机中。在这也有网络定义。一个作为集成测试的物理网络用来配置 VLANs(注意:auto_confi => false option)和其他用来测试代码通信。

当开发者运行一段测试时发生了什么?

实际上是在网关虚拟机上运行了测试。使用了本地挂载代码来创建应用对象,调用对象,然后使用 fabric 在测试机器上远程运行网络工具来 ping/sniff/trace/accept 所有通过和返回给网关的流量的种类。

下面来看个简单的例子,简化了很多的:

class TestVlansBase(unittest.TestCase):
    def setUp(self):
        self._initialize_tester_machines()

    def tearDown(self):
        for tester_name, vlan in self.dct_interfaces_to_remove.iteritems():
            self._remove_interface_from_host(tester_name, vlan)

class TestVlans(TestVlansBase):
    def _test_connection(
            self, server_name, server_vlan, server_ip, server_port, protocol, client_name,
            client_dst_ip=None, client_dst_port=None):
        self.assertTrue(protocol in ('tcp', 'udp'), 'protocol should be tcp or udp')
        client_dst_ip = client_dst_ip or server_ip
        client_dst_port = client_dst_port or server_port
        if protocol == 'tcp':
            server = self._create_server(server_name, server_ip, server_port)
        elif protocol == 'udp':
            filter_exp = '{0} port {1}'.format(protocol, server_port)
            server = self._create_sniffer_on_host(server_name, server_vlan, filter_exp, 1)
        client = self._connect_to_host(client_name, client_dst_ip, client_dst_port, protocol)
        client.runner.join()
        if server.runner.exitcode is None:
            # this means that the process did not exit hence no packets were seen
            server.runner.terminate()
        server.runner.join()
        self.assertEqual(client.runner.exitcode, 0)
        self.assertEqual(server.runner.exitcode, 0)

    def test_reroute_http_traffic(self):
        self._configure_testers()
        self.gateway.configure()
        self._test_connection('tester3', 93, '10.180.0.3', 88, 'tcp', 'tester2', client_dst_ip='10.10.10.10', client_dst_port=80)
        self._test_connection('tester3', 93, '10.180.0.3', 88, 'tcp', 'tester2', client_dst_ip='10.10.10.10', client_dst_port=44444)
        self._test_connection('tester3', 93, '10.180.0.3', 88, 'tcp', 'tester2', client_dst_ip='10.10.10.10', client_dst_port=88)

所有的从网关(测试运行的地方)到测试者机器的远程调用使用的是 fabric。

一个可以在测试上运行的简单命令:

class FabricProcessProxy(object):
    __metaclass__ = ABCMeta

    def __init__(self, *args, **kwargs):
        self.kwargs = kwargs
        self.args = args
        self.out_q = multiprocessing.Queue()
        # self.runner = multiprocessing.Process(target=lambda: execute(self.run, *self.args, **self.kwargs))
        self.runner = multiprocessing.Process(target=lambda: self.out_q.put(execute(self.run, *self.args, **self.kwargs)))

    def execute(self, hosts):
        self.kwargs['hosts'] = hosts
        self.runner.start()
        return self.runner

    @abstractmethod
    def run(self):
        raise NotImplementedError()

class Ping(FabricProcessProxy):
    def run(self, target, iface, count):
        str_iface = '-I {0}'.format(iface) if iface else ' '
        return run('ping -c {count}{iface}-W 1 {target}'.format(count=count, iface=str_iface, target=target))

def _ping_from_host(self, host, dst_ip, through_iface=None, num_pings=1, b_verify_success=True):
        ping = Ping(dst_ip, through_iface, num_pings)
        ping.execute(['vagrant@{0}'.format(host)]).join()
        if b_verify_success:
            self.assertEqual(ping.runner.exitcode, 0)
        return ping.runner.exitcode

_ping_from_host('tester2', '10.180.0.3')

既然这个基础结构已经建好了,我们就不在回头看它了。我们今天所拥有的网关是一等公民,而且只要通过了测试,我们就不怕重构它,添加新的功能和做出其他改变。

Vagrant 的详细介绍:请点这里
Vagrant 的下载地址:请点这里

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-20发表,共计5276字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

星哥玩云

星哥玩云
星哥玩云
分享互联网知识
用户数
4
文章数
19351
评论数
4
阅读量
7976441
文章搜索
热门文章
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见 zabbix!轻量级自建服务器监控神器在 Linux 的完整部署指南 在日常运维中,服务器监控是绕不开的...
飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛 NAS 中安装 Navidrome 音乐文件中文标签乱码问题解决、安装 FntermX 终端 问题背景 ...
阿里云CDN
阿里云CDN-提高用户访问的响应速度和成功率
随机文章
星哥带你玩飞牛 NAS-9:全能网盘搜索工具 13 种云盘一键搞定!

星哥带你玩飞牛 NAS-9:全能网盘搜索工具 13 种云盘一键搞定!

星哥带你玩飞牛 NAS-9:全能网盘搜索工具 13 种云盘一键搞定! 前言 作为 NAS 玩家,你是否总被这些...
终于收到了以女儿为原型打印的3D玩偶了

终于收到了以女儿为原型打印的3D玩偶了

终于收到了以女儿为原型打印的 3D 玩偶了 前些日子参加某网站活动,获得一次实物 3D 打印的机会,于是从众多...
300元就能买到的”小钢炮”?惠普7L四盘位小主机解析

300元就能买到的”小钢炮”?惠普7L四盘位小主机解析

  300 元就能买到的 ” 小钢炮 ”?惠普 7L 四盘位小主机解析 最近...
告别Notion焦虑!这款全平台开源加密笔记神器,让你的隐私真正“上锁”

告别Notion焦虑!这款全平台开源加密笔记神器,让你的隐私真正“上锁”

  告别 Notion 焦虑!这款全平台开源加密笔记神器,让你的隐私真正“上锁” 引言 在数字笔记工...
让微信公众号成为 AI 智能体:从内容沉淀到智能问答的一次升级

让微信公众号成为 AI 智能体:从内容沉淀到智能问答的一次升级

让微信公众号成为 AI 智能体:从内容沉淀到智能问答的一次升级 大家好,我是星哥,之前写了一篇文章 自己手撸一...

免费图片视频管理工具让灵感库告别混乱

一言一句话
-「
手气不错
开发者福利:免费 .frii.site 子域名,一分钟申请即用

开发者福利:免费 .frii.site 子域名,一分钟申请即用

  开发者福利:免费 .frii.site 子域名,一分钟申请即用 前言 在学习 Web 开发、部署...
安装Black群晖DSM7.2系统安装教程(在Vmware虚拟机中、实体机均可)!

安装Black群晖DSM7.2系统安装教程(在Vmware虚拟机中、实体机均可)!

安装 Black 群晖 DSM7.2 系统安装教程(在 Vmware 虚拟机中、实体机均可)! 前言 大家好,...
安装并使用谷歌AI编程工具Antigravity(亲测有效)

安装并使用谷歌AI编程工具Antigravity(亲测有效)

  安装并使用谷歌 AI 编程工具 Antigravity(亲测有效) 引言 Antigravity...
自己手撸一个AI智能体—跟创业大佬对话

自己手撸一个AI智能体—跟创业大佬对话

自己手撸一个 AI 智能体 — 跟创业大佬对话 前言 智能体(Agent)已经成为创业者和技术人绕...
12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换,告别多工具切换

12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换,告别多工具切换

12.2K Star 爆火!开源免费的 FileConverter:右键一键搞定音视频 / 图片 / 文档转换...