UDN-企业互联网技术人气社区

板块导航

浏览  : 548
回复  : 1

[教程技巧] 基于 Docker 的 UI 自动化测试实践

[复制链接]
舞操的头像 楼主
发表于 2016-6-18 20:34:48 | 显示全部楼层 |阅读模式
  最近这段时间对内部的一个配置平台实现了UI自动化,过程中经常上testerhome寻找一些灵感和帮助,最后用到的一些技术比如 Docker、behave、phantomjs等等目前论坛上的资料相对较少,所以特意记录下思路,希望可以给其他同学一点启发。

  UI自动化框架的选择

  在之前做过的一个Android自动化项目中选用了calabash,很喜欢BDD的风格,函数库够多的时候写起自动化来就像是把用例的中文翻译成英语,so easy~

  但是也是之前使用calabash的经历发现ruby的库实在是不够丰富,虽然就语言本身更喜欢ruby一些,没办法,为了没那么多幺蛾子这次还是换成python吧。。。

  python的BDD框架并不多,比较出名的是behave和lettuce,对比过后选择了behave。

  好吧,其实没有真正对比试用过,就是被behave主页上对其他工具的恶毒攻击洗脑了~~

  http://pythonhosted.org/behave/comparison.html

4.png


  与Phantomjs的集成

  简单来讲phantomjs是一个没有UI的浏览器,可以与selenium webdriver完美集成。

  为什么要选用它:

  快,没有GUI的浏览器比起chrome,firefox这些webdriver来执行速度要快很多

  要测试的是内部的配置平台,没有那么多花哨的js,css,更加注重功能,phantomjs足够使用

  就是想在linux下干活,但是我的server并没有UI。。。

  behave中使用phantomjis

  1. from behave import *
  2. from selenium import webdriver
  3. from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

  4. def before_scenario(context,scenario):
  5.     context.dr = webdriver.PhantomJS('phantomjs',service_args=['--ignore-ssl-errors=yes'])
  6.     context.dr.set_window_size(1360, 900)
  7.     ...
复制代码

  1. from behave import *
  2. from selenium import webdriver
  3. from selenium.webdriver.common.by import By
  4. from selenium.webdriver.support.ui import WebDriverWait
  5. from selenium.webdriver.support import expected_conditions as EC
  6. from selenium.webdriver.common.keys import Keys
  7. from selenium.webdriver.common.action_chains import ActionChains
  8. from selenium.webdriver.common.alert import Alert

  9. @given('I open test portal')
  10. def step_impl(context):
  11.     context.dr.get(context.index)
  12.     assert_that(context.dr.current_url,matches_regexp('7030/cas/login'),"not auth page")
  13.     ...
复制代码


  behave用例示例

  1.   @1887204

  2.   Scenario: 1887204-3

  3.   Given I open test portal

  4.   when I input username and login

  5.   then I move to release rule page

  6.   when I reset cfp cp-center log

  7.   when I reset cfp carrier-center log

  8.   then I create new release rule "autotest" "正常订购" "1" "diy" within "180"s

  9.   | id | equal | value |

  10.   | 运营商: | = | 中国联通 |

  11.   | 套餐: | = | lt_50m_qg_suc |

  12.   | 客户账号: | = | autotest |

  13.   then I check cfp cp-center log within "30"s for "release order success.*target release count:1"

  14.   ...
复制代码


  测试数据隔离怎么做

  正常来说,到上面为止框架已经有了,后面就可以填用例了~

  但是我想让自动化更加健壮一些,希望每个用例运行时都是干净的独立的环境。

  这就需要我们对每次测试后的环境进行清理,而behave对于单个case并没有对应teardown这样一个专门清理的函数,这就使得错误发生后没有办法很好的还原环境。

  最开始我们考虑在behave的after_scenario()方法中根据失败用例的tag进行特定的清理。

  这样可以work,但是额外的清理会浪费较多时间,而且UI测试哪里有100%的事情,清理过程中的一点问题可能就造成了之后用例的大片失败,这让我们如履薄冰。

  就在这个时候Docker进入了我们视野。

  如果我们每个case都重启下Docker数据源容器,每个用例的环境就能保证一致,那测试人员就只需要专注编写核心功能的自动化。

  而Docker启动一个容器很快,装有PG,redis的容器只需要几秒钟就能正常运行。

  好 那就试试吧~

  安装配置Docker

  公司的测试机是centos系统,如果想玩Docker过程中不出幺蛾子,建议保证系统到centos7,内核3.10以上。。。

  一开始的时候,我是并不信邪的,在centos6的系统风风火火的搞了起来,结果脸就被打肿了,各种血泪不说了。

  Docker安装很简单,官网文档看看就行

  安装好Docker后,首先从官方库中下载centos6.6的镜像。

3.png


  然后以此为基础分别配置3个镜像,分别是安装了behave的镜像,pg/redis的镜像和安装了application以及其他组件的镜像。

2.png


  启动app,pg容器,其中pg容器以container的形式附在app的容器内,这样做的目的是为了让两个容器的ip一致,这样app的配置文件中关于pg,redis的配置可以用127.0.0.1指定。并且这两个容器又相对独立,用例执行结束后可以stop掉pg容器,并新建一个容器附在app容器中。

  这么做的效果跟所有组件布在同一个容器中是一样的,好处在于重启pg,redis比重启app要快,快很多~

  1.   Docker run -d -v /opt/data/remote:/opt/share 172.16.154.92:5000/centos:6-cfp-apps-2.6.1

  2.   Docker run -d --net=container:{上一步产生容器的ID} 172.16.154.92:5000/centos:6-cfp-env-2.6.1
复制代码


  集成celery

  到上一步为止,我们大体的结构已经有了,但是我们想让它更快,更好用一点。于是我们加上了celery。

  celery是一个比较常用的python异步框架,分别在Docker机器以及behave容器中安装上。

  我们希望自动化控制脚本通过Docker机器中的celery去新建n个behave以及app,env的容器,并在case完成后重新新建env容器。

  然后我们希望behave容器中的celery接受用例id和app容器的ip,从而去指定的app页面中执行用例

  behave容器中使用supervisor启动celery并监听behave消息队列

  1.   [supervisord]

  2.   nodaemon=true

  3.   [program:celery]

  4.   command=bash -c "cd /root/ && celery worker -A tasks -Q behave -l info -c 1 -f /opt/share/celery%(ENV_celery)s.log"

  5.   startretries=0
复制代码

  1. celery worker -A tasks -Q main -c 10 -l info
复制代码


  celery的task脚本tasks.py中指定队列

  Docker机器中celery监听main队列。

  1. from celery import Celery,platforms
  2. import subprocess
  3. import os,sys
  4. import time

  5. platforms.C_FORCE_ROOT = True
  6. app = Celery()

  7. app.conf.update(
  8.     CELERY_IMPORTS = ("tasks", ),
  9.     BROKER_URL = 'redis://172.16.154.92:9852/0',
  10.     CELERY_RESULT_BACKEND = 'redis://172.16.154.92:9852/1',
  11.     CELERY_ROUTES = {
  12.         'tasks.cfp_start': {'queue': 'main'},
  13.         'tasks.behave_init': {'queue': 'main'},
  14.         'tasks.get_ip': {'queue': 'main'},
  15.         'tasks.behave': {'queue': 'behave'},
  16.         'tasks.rm_Docker': {'queue': 'main'},
  17.         'tasks.stop_Docker': {'queue': 'main'},
  18.     },
  19.     ...
  20. )
复制代码


  这样我们通过控制脚本得到需要测试的caseid,然后启动配置个数的app,pg,behave容器,在检查到app容器ready后发送caseid和容器ip到celery队列。

  然后监控case执行过程,在某个case完成后,重启该case对应容器的pg容器,完成后发送下个caseid和ip到celery。这样分布式的测试保证了单个用例的执行环境。

  运行速度也有一定的保障。

  毕竟我的测试机可是24核 24g的机器。。。 运行过程中整机的cpu有时突破90%,也算是资源没有浪费了~~

  结果处理

  因为每次behave都只是执行一个case,因此生成的junit报告也只有一个case的信息。因此需要做报告合并。

  不想重复造轮子搜索了下, 通过两个现有的模块 xunitparser,junit_xml愉快搞定。生成一个大的junit报告

  然后就是放在jenkins,用插件展示了。

1.png


  用例调试

  之所以用例调试要专门拿来说下,是因为使用Docker容器创建的容器都是私有ip,不能直接访问。

  Docker倒是可以将容器中的端口映射一个实体机的端口,但这个并不十分好用,因为我们app的配置文件里面需要配置一些跳转的url,而这些跳转的urlip又是私有的或者干脆是127.0.0.1的。。。 于是我们新建了一个squid的容器跟app容器在一个网段,然后暴露代理端口给我们,这样浏览器设下代理就ok了。

  然后就是用例运行中的截图,phantom本来就是没有界面的嘛,而且又是多个用例异步的执行,这要怎么调试呢。

  也很简单,behave中通过after_step() 方法在每个用例每个步骤执行后都可以screenshot,保存在用例的目录。该目录mount在Docker机器中。

  然后启动一个nginx容器,设置好截图目录,就可以直接查看啦~~

原文作者: strayhrt · 来源:开发者头条
发表于 2016-6-19 22:40:32 | 显示全部楼层
赞一个
使用道具 举报

回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部