前段时间写过两篇帖子,主要介绍了如何在 mac 系统上面安装 appium 并以测试集的方式运行自动化测试脚本。今天这篇文章就主要来说说在完成上面的工作之后,如何实现自动化测试的持续集成。下面介绍的内容是我自己的实践经验,请大家千万不要把这当成是什么持续集成教学帖(当然我也没这水平),持续集成实现的方式不止一种,我所做的就是把我自己实践过的东西分享出来,希望能给大家一点帮助,能在大家进行持续集成实践的时候给大家提供一点参考,仅此而已。啊啊,我发现我废话真是多,好了,说正经的吧。。。。

我想大家应该都听过这样一句话:没有做持续集成的自动化测试都只能叫半自动化测试。因为虽然你写好了脚本,虽然你可能只需要双击运行某个脚本或者只需要在命令行里边敲一个运行脚本的命令就能够运行一次完整的测试,但问题就是你还是要来双击一下或者敲个命令才能运行测试,还是有一个人工的干预。毫无疑问自动化测试的目标应该是无需人工的干预的,完全自动执行的。

那么什么叫持续集成,其实我也不清楚,按我实际实践经验来说,我说不上来持续集成是什么,但我可能隐隐感觉到了持续集成应该干些什么,那么持续集成应该干什么呢?我从流程角度来说说该干什么(我只说移动 app 测试,并且是我自己接触到的)

1.开发提交代码后自动编包到指定目录下(svn 上或者某台服务器的指定目录)
2.测试机器定时到指定目录下取最新包到本地指定目录
3.测试机器定时运行某个启动脚本开始运行自动化测试,测试运行完成后生成测试报告文件到指定目录下
4.测试机器自动发送测试报告到指定邮件收件人(以附件形式或链接形式,我个人喜欢后者)

以上就是我认为的持续集成应该干到事情,web 上做持续集成可能还会涉及到包到自动部署内容(我以前看过一篇殷坤大神的介绍他们公司做持续集成的帖子,挺受益,大家可以自己找来看看)

下面我就就上面提到的后 3 点来说一下我的实践经验,因为第 1 点是在我着手做自动化测试之前就已经做好,不是我做的所以我也没有什么好说的,具体实现起来应该不难,这个大家通过谷歌百度应该是能解决问题的。
做持续集成有两种选择。一种是选择一款好用的持续集成工具,这个可能大家一下就想到 jenkins;还有一种选择是不用持续集成工具(这话听起来好像一句废话),我们可以通过系统本身的一些功能和其它一些方式来实现持续集成需要实现的功能。我选择的是第二种。

环境:
操作系统版本是 MAC OS X 10.9.1;
APPIUM 版本是 1.1.0;
python 版本是 2.7

整体实现思路:
整个自动化测试的启动脚本是 set_up.py,通过 crontab 新增定时任务确定一个时间来定时执行 setu_up.py 以运行自动化测试。
实际是研发每天 12 点之前会将当天的包编好放到中转服务器上指定的目录,所以运行自动测试的定时任务时间设定在凌晨 2 点。

set_up.py 实现以下功能:

1.运行去服务器上取包的脚本 fetch_app.sh,如果脚本执行没有成功,则发送失败邮件到指定邮件接收人,邮件内容应包含脚本执行失败信息
2.如果取包没有发生错误,则执行 svn 命令从 svn 上 checkout 出最新的测试脚本目录到本地
3.如果上一步命令执行没有出错,则运行命令开始执行测试主控脚本 main.py,否则提示 svn check out failed 并发送失败邮件到相关邮件接收人

对于上面的第 2 点,补充说明以下。测试脚本存放在 svn 上,是为了方便多人进行脚本维护,这要求一点就是所有参与脚本维护的测试人员必须确保新编写的脚本在本地测试通过后才能更新到 svn 上以保证 svn 上的脚本都是能够正确运行的脚本。

好像漏了点什么?测试报告呢?测试报告在执行 main.py 脚本的时候生成,测试执行过程中会将测试结果写入该报告,报告格式为 html 格式。测试报告这块我使用的是第三方的模块 HTMLTestRunner.py。这个模块貌似没有包含测试通过率等一些内容,我通过修改这个模块的源码,对测试通过率做了一下统计,另外由于我的测试同事说报告字体太小,出错日志部分背景不好看等等原因(==!),我对字体大小和背景这些东西也做了修改,这些都可以通过修改该模块的代码实现,并且修改起来并不算难,所以如果大家使用这个模块并且有一些自己的需求的话,可以尝试做相应的修改。貌似扯远了。。。。

上面的 set_up.py 实现的 3 个功能中,提到了几个脚本,一个是 fetch_app.sh,这是一个 shell 脚本;另外一个是 main.py 脚本。通过定时任务来运行测试启动脚本可以通过 crontab 来实现。至于怎么使用 crontab 添加定时任务,这个比较简单,大家想详细了解可以自行百度。
上面都是纯文字,看的人想睡觉,好,下面进入最期待的贴代码环节 =。=:
首先是定时任务,在终端中敲 crontab -e 命令,按 a 键进入编辑模式,添加一个定时任务,如图:

上面这个定时任务的意思就是每天凌晨 2 点钟运行指定目录下的 set_up.py 脚本。
再来看看最核心的 set_up.py 脚本的大致内容,我就不贴详细代码了,原因有这么几个。一是我这部分代码写的烂且有重复之嫌,不想献丑(当然代码本身也很简单);另外一个发送邮件部分的主要代码是我百度来的,我只是做了一些修改;还有一个原因是我给出一个具体的思路即可,具体的实现方法可以有很多,比如发邮件功能就可以有很多种方法。这样其实也能让大家自己动手去找,去学,对大家自身也是一个经验,一个提升。

#-*-coding:utf-8-*-
import time,os,sys
import operator
import commands

from test_email_list import read_receiver_list

cmd0 = '/Users/hobbs/auto-test/fetch_app.sh'
fetch_err_info = commands.getoutput(cmd0)
#print err_info
if err_info == '' : 
    cmd = 'svn co svn://192.168.888.888/dev/ios-auto-test/ /Users/hobbs/Desktop/ios-auto-test'
    svn_co_info = commands.getoutput(cmd)
    print svn_co_info
    if "Checked out revision" in svn_co_info :
        cmd2 = 'python /Users/hobbs/Desktop/ios-auto-test/scripts/main.py'
        execute_test_info = commands.getoutput(cmd2)
        print "test finished!"
    else:
        print "SVN check out failed"
        #发送svn检出测试脚本目录失败邮件到指定接收人,邮件内容中包含svn检出脚本失败信息,svn_co_info
else:
    #发送取测试包失败邮件到指定接收人,邮件内容中包含取包脚本执行失败信息fetch_err_info,方便查找问题
    print "send fetch fail email success!!!!"


对于这段代码补充一点内容,就是我是如何实现发送邮件到指定接收人的,大家看代码中有这么一句

from test_email_list import read_receiver_list

其中的 test_email_list 中有个 read_receiver_list 方法,我将收件人存放在一个指定目录下的 txt 文件中(也在 svn 到某个测试目录下,方便大家维护收件人列表),然后用这个方法来读取 txt 文件并将其存在一个 list 中,这样我就可以在代码中使用这个 list 来发送邮件到这个 list 中的所有收件人。
大家也许也注意到了,代码中发了两封邮件都是失败邮件,那测试成功的邮件呢?测试成功的邮件放到 main.py 中去了。(自问自答,我是不是显得很脑残?)那么我们再来看看传说中到 main.py 长什么样,请看伪代码!

# -*- coding:utf-8 -*-
from selenium import selenium
import unittest, time, re
import HTMLTestRunner


from test01 import Module1_cls
from test02 import Module2_cls
from test03 import Module3_cls

from test_email_list import read_receiver_list

global reportname
time_now = time.strftime("%Y%m%d%H%M%S")
print time_now

reportname ="/Library/WebServer/Documents/auto-reports/hobbs_Reports/" + time_now + "_report_of_hobbs.html"
def suit_run():

    global reportname
    fp = file(reportname,"wb")
    suit = unittest.TestSuite()

    suit.addTests(unittest.defaultTestLoader.loadTestsFromTestCase(Module1_cls))
    suit.addTests(unittest.defaultTestLoader.loadTestsFromTestCase(Module2_cls))
    suit.addTests(unittest.defaultTestLoader.loadTestsFromTestCase(Module3_cls))

    runner = HTMLTestRunner.HTMLTestRunner(stream=fp,title="report_of_xxx",description="hobbs report")
    runner.run(suit)

    time.sleep(3)

def sendMail():
    global reportname

    #这里省去发送邮件相关代码,邮件中应给出报告的链接地址。在这里地址为reportname

    print "success!!!!"

suit_run()
sendMail()


对于上面代码做一点补充说明。上文中也说过了,测试报告可以以邮件附件的方式发送给邮件接收人,也可以直接在邮件内容中给出报告的链接地址。我采用的是后者,通过使用 MAC 自带的 webserver 来实现。具体为将生成的测试报告放在 WebServer 的相关目录下(代码中为/Library/WebServer/Documents/auto-reports/hobbs_Reports/,具体的子目录根据自身情况设置),然后邮件中内容中给出 http 链接即可。提到邮件内容,邮件内容最好能有本次测试的一个概况,如测试了多少 case,通过了多少 case,通过率多少等等。因为角色不同关注点也会不同,你的 boss 很可能都不想点链接去查看具体的测试报告,他可能只关心大体结果;但是测试工程师或者开发人员可能就会点进去查看报告的详细情况。

好了,也扯了半天了,就扯到这里。我说过我属于半桶水,半桶水乱晃,所以竟敢大胆在众大神面前扯淡。但是就像我开头说的,我只是想把自己的一点实践经验分享给大家,给大家作个参考。另外一个就是想抛砖引玉,现在砖已经抛了,期待能引来玉。最后我负责抛砖,你负责拍砖,欢迎大家批评指正,今天的淡就扯到这里。。。。


↙↙↙阅读原文可查看相关链接,并与作者交流