使用Docker和Golang进行便捷的MongoDB测试

本文讲的是使用Docker和Golang进行便捷的MongoDB测试,【编者的话】Docker的使用场景之一就是测试,在测试中,我们有时候会由于超时或者仅仅因为两个开发版本使用相同的数据库在同时运行而导致测试出错。本文以Golang和MongoDB为例,介绍了如何使用Docker来简化和改进单元测试。

背景
我们正在不断寻找新技术来解决开发中遇到的问题。我们一直在使用Java+Spring,然而Java 8和Spring Boot为我们带来了新的生机,并改变了单一的Java应用为微服务模式(译者注:monolithic Java applications)。而当你有API的时候,你只需一个合适的前端框架就可以替代jsp和jQuery:在我们的案例中我们选择AngularJS。两年前我们第一次使用了Angular,现在所有的项目都引入了AngularJS。

超过10年的Java 在你的灵魂深处留下了深刻的印记
这两三年来,我一直在寻找更好的东西。在这个行业中,最好的事情是你会有各种选择。我们曾经使用NodeJS构建了几个项目,并学习了Ruby的服务配置管理框架Chef。当然我们也有一些Scala项目,并了解过Clojure、Haskell和Rust语言,后来我们发现了Go。虽然我们只使用Go语言编写了几个小服务,但是却对与Go相关的语言、标准库、工具和社区而震惊。有大量的博客文章解释了为什么不同的公司选择了Go,本文不再赘述。同时如果你想学习如何编写Go,可以查阅A tour of Go,如果你喜欢阅读请查看Effective Go或观看A tour of Go视频。

负载测试
可能我需要相当长的篇幅来介绍负载测试,所有的编程语言都需要编写单元测试代码,另外还有一些需要使用TDD方法和达到100%测试覆盖率的目标的方法。动态语言需要安排更多类型的测试,可能当你经过了上百次的测试,你的应用才能达到一个稳定的状态。痛苦的是,由于有不同的开发语言,所以你的测试需要很多的准备工作:曾经几秒钟就可以完成的事情,那现在可能会需要几分钟,甚至是几十分钟才能完成。因此,你要开始仓库(数据库)的调用,并建立集成测试的数据库开发的预载和清除方法。有时候集成测试可能会失败,而这可能是由于超时或者仅仅因为两个开发版本使用相同的数据库在同时运行。

使用Golang和Docker进行的测试
Golang不会有类似的问题,有了Golang的快速构建、测试周期和一些Docker魔法的支持,你能够在几秒内启动MongoDB Docker容器并运行所有的测试。这个真的是从开始到结束只需要几秒的时间,但是第一次运行除外,因为第一次运行的时候需要下载和提供MongoDB Docker容器。

我从这里得到真正的灵感,即使一直在寻找借口来确认这是否是正确的:

让我们做一些可以进行Docker实验的nice的事情
我已经研究Golang+AngularJS一段时间了,而且现在是最佳时间来证明Docker是否如宣传的一样神奇。对于OS X用户来说,涉及到Docker时会有个小烦恼:它只在Linux上面运行。是的,你可以运用Boot2Docker来安装到OS X上,而Boot2Docker将在虚拟化的Linux上运行Docker。我已经通过Ubuntu来使用Vagrant作为开发环境,因此我刚刚在这上面安装了Docker。

首先,我要熟悉Camlistore的实施环境并且复制它。特别感谢Brad Fitzpartick,你通过Camlistore和Golang标准程序库来完成了出色的工作。Thanks!

可以通过story_test.go来找到实际测试。对于那些看不懂Golang的用户,我已经在最重要的代码部分添加了额外的注释。

Setup test environment
func TestStoryCreateAndGet(t *testing.T) {

// Start MongoDB Docker container
//
// One of the most powerful features in Golang
// is the ability to return multiple values from functions.
// In this we get:
// - containerID (type=ContainerID struct)
// - ip (type=string)
containerID, ip := dockertest.SetupMongoContainer(t)

// defer schedules KillRemove(t) function call to run immediatelly
// when TestStoryCreateAndGet(t) function is done,
// so you can place resource clenup code close to resource allocation
defer containerID.KillRemove(t)

app := AppContext{}

// Connect to Dockerized MongoDB
mongoSession, err := mgo.Dial(ip)

// Golang favors visible first hand error handling.
// Main idea is that Errors are not exceptional so you should handle them
if err != nil {
Error.Printf("MongoDB connection failed, with address '%s'.", Configuration.MongoUrl)
}

// close MongoDB connections when we're finished
defer mongoSession.Close()

app.mongoSession = mongoSession

// create test http server with applications route configuration
ts := httptest.NewServer(app.createRoutes())
defer ts.Close()

storyId := testCreate(ts, t) // run create test
testGet(ts, storyId, t) // run get test for created story
}

Post json document to http handler
func testCreate(ts *httptest.Server, t *testing.T) string {

postData := strings.NewReader("{\"text\":\"tekstiä\",\"subjectId\":\"k2j34\",\"subjectUrl\":\"www.fi/k2j34\"}")

// create http POST with postData JSON
res, err := http.Post(ts.URL+"/story", applicationJSON, postData)

// read http response body data
data, err := ioutil.ReadAll(res.Body)
res.Body.Close()
if err != nil {
t.Error(err)
}

id := string(data)

// verify that we got correct http status code
if res.StatusCode != http.StatusCreated {
t.Fatalf("Non-expected status code: %v\n\tbody: %v, data:%s\n", http.StatusCreated, res.StatusCode, id)
}

// verify that we got valid lenght response data
if res.ContentLength != 5 {
t.Fatalf("Non-expected content length: %v != %v\n", res.ContentLength, 5)
}
return id
}

Test that previously created story exists
func testGet(ts *httptest.Server, storyId string, t *testing.T) {

// create http GET request with correct path
res, err := http.Get(ts.URL + "/story/" + storyId)
data, err := ioutil.ReadAll(res.Body)
res.Body.Close()
if err != nil {
t.Error(err)
}

body := string(data)

// validate status code
if res.StatusCode != http.StatusOK {
t.Fatalf("Non-expected status code: %v\n\tbody: %v, data:%s\n", http.StatusCreated, res.StatusCode, body)
}

// validate that response has correct storyId
if !strings.Contains(body, "{\"storyId\":\""+storyId+"\",") {
t.Fatalf("Non-expected body content: %v", body)
}

// validate that content leght is what is should be
if res.ContentLength < 163 && res.ContentLength > 165 {
t.Fatalf("Non-expected content length: %v < %v, content:\n%v\n", res.ContentLength, 160, body)
}

}

眼见为实
因此,启动MongoDB Docker容器,将它配置到应用程序,然后用内置的测试直至创建HTTP服务器。然后,我们设置同样的路由给服务器,并对测试服务器运行两个请求,第一个来创建故事评论,另外一个来获取它。所有的数据都被存储了,并且从MongoDB中获取。那么所有这一切需要多久时间呢?

仅两秒以下!

即使你运行一些条件选择器它仍只需要不到3秒 \o/

Docker是针对所有的用户,而不仅仅是Golang用户

对于那些可以使用Golang的用户,Docker也可以帮助你。它当然没有Golang那么快速,但是和使用外部的MongoDB服务器一样的快,而且没有额外的清理麻烦。毫无疑问,Docker是虚拟化业务中的游戏变化者,并且这些炒作也得到了很好的回报。这样就没有借口来针对MongoDB功能编写任何模拟测试。

原文链接:Painless MongoDB testing with Docker and Golang(翻译:吴锦晟 校对:李颖杰)

===============================================
译者介绍
吴锦晟,大连理工大学硕士研究生,就职于上海金桥信息股份有限公司技术中心。目前负责云计算、虚拟化、大数据及其信息可视化等方向的研究和应用。希望通过翻译技术文章于Dockone社区为Docker的步道做出微薄贡献。

原文发布时间为:2015-01-14

本文作者:吴锦晟 

本文来自合作伙伴DockerOne,了解相关信息可以关注DockerOne。

原文标题:使用Docker和Golang进行便捷的MongoDB测试

时间: 2024-08-02 18:58:46

使用Docker和Golang进行便捷的MongoDB测试的相关文章

Docker与Golang的巧妙结合_docker

Docker与Golang的巧妙结合 [编者的话]这是一个展示在使用Go语言时如何让Docker更有用的提示与技巧的简辑.例如,如何使用不同版本的Go工具链来编译Go代码,如何交叉编译到不同的平台(并且测试结果!),或者如何制作真正小的容器镜像. 下面的文章假定你已经安装了Docker.不必是最新版本(这篇文章不会使用Docker任何花哨的功能). 没有go的Go ...意思是:"不用安装go就能使用Go" 如果你写Go代码,或者你对Go语言有一点点兴趣,你肯定要安装了Go编译器和Go

Docker与Golang的巧妙结合

本文讲的是Docker与Golang的巧妙结合[编者的话]这是一个展示在使用Go语言时如何让Docker更有用的提示与技巧的简辑.例如,如何使用不同版本的Go工具链来编译Go代码,如何交叉编译到不同的平台(并且测试结果!),或者如何制作真正小的容器镜像. 下面的文章假定你已经安装了Docker.不必是最新版本(这篇文章不会使用Docker任何花哨的功能). 没有go的Go ...意思是:"不用安装go就能使用Go" 如果你写Go代码,或者你对Go语言有一点点兴趣,你肯定要安装了Go编译

如何利用docker 构建golang线上部署环境

公司最近开发了一个项目是用golang 写的,现在要部署到线上环境去,又不想在服务器上装单独的golang,决定用docker 封装下,直接打到镜像里面,然后就直接在hub.docker.com上面搜了下golang的镜像,直接就docker pull golang 最新的是1.9的版本 然后参考官方的文档弄了下Dockerfile大概是这样:   FROM golang MAINTAINER jackluo #指定工作目录 WORKDIR /go/src/ActivitApi COPY . .

mongodb测试小结-tina

                         mongodb测试小结  一.基础配置 1)硬件 双核  8G  100G硬盘 2)集群 1 台mongos.config服务器:3台分片:1台独立mongod存放count_temp统计表  二.测试结果 1)中间数据的处理: 3台分片机上 分别跑3个进程,共9个进程,约为430w/h,5000w的数据大概需要11.6h 3台分片机上 分别跑5个进程,共15个进程,约为840w/h,5000w的数据大概需要6h (5个进程会比3个进程分得更平均

深入实践Spring Boot2.3.4 MongoDB测试

2.3.4 MongoDB测试 如果还没有安装MongoDB服务器,可以参照附录B的方法安装并启动一个MongoDB服务器.然后,使用如代码清单2-18所示的配置方法配置连接服务器的一些参数,该配置假定你的MongoDB服务器安装在本地,并使用默认的数据库端口:27017. 代码清单2-18 MongoDB数据库配置 # MongoDB mongo.host=localhost mongo.name=test mongo.port=27017 这样就可以编写一个JUint测试例子来测试UserR

其他杂项收藏

编程开发 其他 Universal Extractor 1.6.1 绿色多语正式版_近乎于万能的文件提取器 - 绿色软件联盟 - <绿盟:软件下载档案库> QC9.0不支持IE7,IE8.IE9的解决方法_花上的碟儿的空间_百度空间 基于HTTP协议的轻量级开源简单队列服务:HTTPSQS[原创] - 张宴的博客 - Web系统架构与底层研发 UCENTER asp.net版ucenter接口程序源码,Asp.net源码 |-51aspx.com UC(Ucenter)整合asp.net 程序

docker(8):使用alpinelinux 构建 golang http 看看能有多小

1,alpine linux 非常小 首先 alpine 非常的小,安装上了bash 之后也才 5mb. golang 不需要其他的依赖,想看看是不是能在 alpine 上面跑呢. 搭建一个golang的环境,而不是把golang的环境放到alpine上面. 2,首先在centos 搭建golang环境 https://golang.org/doc/install 下载然后解压缩: tar -C /usr/local -xzf go1.7.4.linux-amd64.tar.gz 设置环境变量:

docker(9):使用alpinelinux 构建 golang http 启动了,才15mb

本文的原文连接是: http://blog.csdn.net/freewebsys/article/details/53635529 未经博主允许不得转载. 博主地址是:http://blog.csdn.net/freewebsys 1,关于alpine 环境 http://blog.csdn.net/freewebsys/article/details/53615757 昨天研究了下golang的http服务器. 发现在启动的时候报错: No such file or directory 发现

《循序渐进学Docker》——第一部分 Part 1 基础篇 第1章 全面认识Docker 1.1 Docker是什么

第一部分 Part 1 基 础 篇 第1章 全面认识Docker 第2章 初步体验Docker 第3章 Ubuntu下使用Docker 第4章 Docker的基础知识 第1章 全面认识Docker 欢迎来到Docker的世界. Docker,Golang社区杀手级的应用,是Github上最活跃的项目之一,也是开源社区最受欢迎的项目. Docker,号称要成为所有云应用的基石,并把互联网升级到下一代. 开发.测试.运维人员看到Docker,都激动地说:"太好了,这正是我所需要的!" Do