这段时间除了项目测试外,主要在做web自动化的事情,大致总结一下吧,总体的设计模式pageobject+pagefactory+testng的数据驱动,项目用maven来构建,使用jenkins集成,用grid分布式部署,支持并发。下面分别来简单说下注意事项吧。

一、jenkins

代码放在git上,除了常规的设置git插件外,需要注意

1.触发构建

  选择,Build periodically。0 * * * * 表示的就是每个小时的第 0 分钟执行一次构建。参数含义:

  • 第一个参数代表的是分钟 minute,取值 0~59;
  • 第二个参数代表的是小时 hour,取值 0~23;
  • 第三个参数代表的是天 day,取值 1~31;
  • 第四个参数代表的是月 month,取值 1~12;
  • 最后一个参数代表的是星期 week,取值 0~7,0 和 7 都是表示星期天。

2.构建步骤

  运行pom文件,命令是

clean install compile test-compile test

  一定要把maven中的main和test一起编译。

3.测试报告

  目前公司的Jenkins安装的插件是publish testng results,路径默认即可 。**/testng-results.xml,效果图如下:

4.发送邮件

  邮件触发选择always,content我暂时设计了一个模板,以后再优化,效果如下

代码如下:

hi all,<br/><hr/>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>qiaoyeye</title>
<style type="text/css">
<!--
.STYLE1 {
font-size: 18px;
font-weight: bold;
color: #FF0000;
}
.STYLE2 {
font-size: 14px;
font-weight: bold;
}
.STYLE3 {
color: #00FF00;
font-weight: bold;
font-size: 14px;
}
.STYLE4 {
color: #FF0000;
font-weight: bold;
font-size: 14px;
}
.STYLE5 {
color: #FFFF00;
font-weight: bold;
font-size: 14px;
}
.STYLE6 {font-size: 12px}
-->
</style>
</head> <body>
<span class="STYLE1">构建结果 - ${BUILD_STATUS}</span>
<br />
<br />
<br />
<br />
<br />
<span class="STYLE2">构建信息</span>
<hr />
<br />
<ul>
<li>项目名称:${PROJECT_NAME}</li>
<li>构建编号:${BUILD_NUMBER}</li>
<li>构建时间:${BUILD_ID}</li>
<li>触发原因:${CAUSE}</li>
<li>构建日志:<a href="${BUILD_URL}console">${BUILD_URL}console</a></li>
<li>构建URL:<a href="${BUILD_URL}">${BUILD_URL}</a></li>
<li>项目URL:<a href="${PROJECT_URL}">${PROJECT_URL}</li>
<li>工作目录:<a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li>
</ul>
<br />
<br />
<span class="STYLE2">测试概览</span>
<hr />
<br />
<table width="700" height="64" border="1">
<tr>
<td bgcolor="#CCCCCC"><div align="center" class="STYLE2">total</div></td>
<td bgcolor="#CCCCCC"><div align="center" class="STYLE3">passed</div></td>
<td bgcolor="#CCCCCC"><div align="center" class="STYLE4">failed</div></td>
<td bgcolor="#CCCCCC"><div align="center" class="STYLE5">skipped</div></td>
</tr>
<tr>
<td><div align="center"><span class="STYLE6"> ${TEST_COUNTS, var="total"}</span></div></td>
<td><div align="center"><span class="STYLE6"> ${TEST_COUNTS, var="pass"}</span></div></td>
<td><div align="center"><span class="STYLE6"> ${TEST_COUNTS, var="fail"}</span></div></td>
<td><div align="center"><span class="STYLE6"> ${TEST_COUNTS, var="skip"}</span></div></td>
</tr>
</table>
<br />
<br />
<span class="STYLE2">failure log:</span>
<hr />
$FAILED_TESTS
<br />
$PASSED_TESTS
<br />
$SKIPPED_TESTS
<br />
</body>
</html>
<br/><hr/>
(本邮件是程序自动下发的,请勿回复!)<br/><hr/>

5.可以把失败的截图作为附件添加

projectjobname/imgfilename/*.png

**/ExceptionScreenshotImg/**/*.png

二、maven

主要是pom文件,需要在pom中添加对testng的支持

<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<suiteXmlFiles>
<!-- <suiteXmlFile> -->
<file>src/test/java/OmsWebAuto.xml</file>
<!-- </suiteXmlFile> -->
</suiteXmlFiles>
</configuration>
</plugin>

pom对reportNG的支持

<!-- reportng -->

    <dependency>
<groupId>org.uncommons</groupId>
<artifactId>reportng</artifactId>
<version>1.1.2</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.4</version>
<scope>test</scope>
</dependency>
<!-- 加入reportNG和testng的插件 --> <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
<configuration>
<properties>
<property>
<name>usedefaultlisteners</name>
<value>false</value>
</property>
<property>
<name>listener</name>
<value>org.uncommons.reportng.HTMLReporter, org.uncommons.reportng.JUnitXMLReporter</value>
</property>
</properties>
<suiteXmlFiles>
<!-- <suiteXmlFile> -->
<file>src/test/java/International.xml</file>
<!-- </suiteXmlFile> -->
</suiteXmlFiles> </configuration> </plugin>

三、框架

1.合理利用selenium的监听事件

可以把一些log或者经常调用的方法等放在监听事件类里,只需要自己新建一个类实现WebDriverEventListener即可,好处是在后面的代码中不需要在写一堆方法或频繁调用了,效果真的不错。注册监听的方法:

private static EventFiringWebDriver registerEvent(WebDriver driver) {
EventFiringWebDriver event = new EventFiringWebDriver(driver);
BaseEventListener eventlis = new BaseEventListener();
event.register(eventlis);
return event;

2. 利用testng的监听事件

如失败自动截图,参考我的文章:

selenium遇到异常自动截图

失败自动重跑,抽时间再整理成文章:

等……

3.所有用例只启动浏览器、登录、关闭浏览器一次

要想做到这点,首先要明白testng的生命周期,可以参考我的这边文章http://www.cnblogs.com/qiaoyeye/p/5317566.html

然后核心思想是保证所有的测试类在整个生命周期内用的是同一个webdriver对象,一定要理解,要想做到这一点,就必须单独建立一个类,包含初始化webdriver的方法和webdriver的全局变量,放在合适的testng注解内,其他所有的测试类,都调用该类的webdriver。举例如下:

  • webdriver初始化类:
/**
* 在整个测试中,只启动浏览器、登录至主页、关闭浏览器一次。所有测试类的driver=TestSuite.driver,以保证共用的是一个driver。
* @author QiaoJiafei
* @version 创建时间:2016年5月13日 下午6:48:41
* 类说明
*/
public class TestSuite{
public static WebDriver driver; @BeforeSuite
public void befSuite() {
driver = DriverFactory.setUpDriver();
visitorURL();
Login.login(driver);
//直接进入订单系统页面
HomePage homepage = new HomePage(driver);
homepage.jumpProduct();
}
private void visitorURL() {
String url = OptionFile.readProperties("./src/test/resources/logininfo.properties", "URL");
driver.get(url);
} @AfterSuite
public void aftSuite() {
DriverFactory.tearDownDriver(driver);
}
}
  • 测试类,注意这里把testsuite的driver赋值给了driver,保证了整个生命周期用的都是同一个driver
public class TestOrderSearch extends BaseTestClass{
@Test
public void testOrderSerach() {
driver = TestSuite.driver;
OrderHomePage odp = new OrderHomePage(driver);
OrderSearchPage osp = odp.jumpOrderSearch();
osp.searchOrder();
osp.clickOrderDetail(); }
}
  • Driverfactory就是一个初始化和销毁driver的工厂类。

4.pafactory遇到iframe怎么办

我的解决办法是三种,在同一个类内解决,不同类解决,内部类解决。

  • 同一个类

  在同一个类中的话,在使用iframe中的元素时一定要先切换ifame,使用完元素后,要记得切回主体。这种办法适合iframe中要使用的元素比较少时使用。

  • 内部类

  在内部类的话,等于把处理iframe的元素抽象到了一个类中,切换iframe和切回主体都在内部类中,这样其他类只需要调用内部类即可,不需要在关心iframe的处理,适合iframe中有适量的元素处理

  

    public class Inner  extends BasePage{

        public Inner(WebDriver driver) {
super(driver);
this.toFrame("ueditor_0");
}
//
@FindBy(xpath="/html/body")
WebElement rich_body; public void setContent() {
this.setRichTextBox(rich_body, "web ui auto test");
this.toDefaultContent();
}
}
  • 不同的类

  和内部类类似,使用要在iframe处理的元素比较多,就可以单独拉出啦作为一个类处理。

5.活用反射

java的反射真的太好了,目前主要用在:

  • 在数据驱动动态获取必要参数,因为testng的数据驱动不支持主动调用传参的。
  • 自动截图中,自动以运行的类名来命名文件夹,然后以方法名+时间戳来命名图片。
  • pagefactory初始化之前,从property文件中获取当前正在运行的类的标题,key是类名,value是标题,这样只需要配置好property文件就行,省了不少麻烦。

四、grid

这个没什么好说的,一台电脑启动hub,然后在不同的机器上启动node,注册到该hub上,grid会根据框架对浏览器的配置来分配相应的node启动浏览器测试,selenium官网上有很多这方面的介绍,这里只介绍下我常用的命令

  • hub:

  

java -jar selenium-server-standalone-2.53.0.jar -role hub
  • node1:

  

java -Dwebdriver.chrome.driver=C:\selenium\node_chrome32_windows\driver\chromedriver.exe -jar selenium-server-standalone-2.53.0.jar -role node -hub http://192.168.15.54:4444/grid/register -maxSession 20 -browser "browserName=chrome,platform=WINDOWS,maxInstances=20" -port 5556
  • node2
  • …………

上面的命令更换浏览器名称、端口、路径即可


目前只是初步成型,后面还有很多工作要做。

关于selenium的CI、框架……的更多相关文章

  1. ci框架登陆之后每隔几分钟就需要重新登录的问题

    一个简单的登陆写好之后,发现每次进入需要登陆之后才能进入的页面都会跳转到登录页面,猜测应该是session被清了,打印出来,果然为空,但是我没有设置session的生存周期,按照默认的应该是24小时, ...

  2. 第一天ci框架开发商城2

    ci框架开发商城2 1/28/2016 9:45:52 PM mvc完整案例 mvc完成新闻的增删改查 news控制器news.php class News extends CI_controller ...

  3. 第一天ci框架开发商城1

    ci框架开发商城1 1/28/2016 9:43:52 PM userguide删除 system application controllers 控制器 models 模型 views 视图 模板 ...

  4. CI框架之HOOKS使用流程及原理

        Ci框架中Hooks可以理解:在框架的执行流程过程中,允许开发者在固定的某些时间点上(如:调用控制器前,调用控制器后等时间点上),调用其他函数来扩充CI框架执行流程的一种方法.技术上来就是通过 ...

  5. CI框架使用PHPmail插件发送QQ邮件:

    有助请顶,不好请评.0:33 2016/3/12CI框架使用PHPmail插件发送QQ邮件:发送成功,不过修改了主机参数,还包含了一个phpmail中的一个另外的文件,详见下方:参见:http://c ...

  6. 初学后台框架总结篇二——快速了解CI框架

    一.下载CI框架并安装,这里放置一张自己的项目目录结构图 目录框架搭建好之后开始将自己的项目与框架融合 二.更改相关配置 1.用任何文本编辑器打开 application/config/config. ...

  7. CI框架,源代码一次性判断获取post(get)数据是否有某个字段值为空方法

    一.以下是CI框架 1.把所有的要接收的字段放在数组中 例: 我要接收:id,name,age,mobile 等字段 $req = array('id','name','age','mobile'); ...

  8. CI框架搭建

    CI 框架等移植到不同等环境十分方便,只要改很少等配置: 1.修改config.php 文件(修改这一个文件就可以跑通了): $config['base_url'] = 'http://127.0.0 ...

  9. ngnix 配置CI框架 与 CI的简单使用

    ngnix 支持 CI框架1.修改config.php 参考网址:https://www.chenyudong.com/archives/codeigniter-in-nginx-and-url-re ...

  10. CI框架如何在主目录application目录之外使用uploadify上传插件和bootstrap前端框架:

    19:29 2016/3/10CI框架如何在主目录application目录之外使用uploadify上传插件和bootstrap前端框架:项目主路径:F:\wamp\www\graduationPr ...

随机推荐

  1. PetaPoco4.0 实体某个字段不赋值会更新成null解决方案

    最新用PetaPoco4.0做项目发现有个需求,就是比如说:在mvc表单中,只显示部分字段,一个表单还有其他状态等字段,没有显示到mvc页面上 但是当MVC收集表单提交更新的时候,会发现会把数据库中的 ...

  2. 【C#进阶系列】26 计算限制的异步操作

    什么是计算限制的异步操作,当线程在要使用CPU进行计算的时候,那么就叫计算限制. 而对应的IO限制就是线程交给IO设备(键鼠,网络,文件等). 第25章线程基础讲了用专用的线程进行计算限制的操作,但是 ...

  3. 把生成的excel文件直接提供为下载页效果

    把php中的excel显示下载页下载到本地硬盘需要设置头信息: 代码: $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Ex ...

  4. EC笔记,第一部分:4.确定对象初始化

    04.确定对象初始化 将对象初始化,C++反复无常,所以在使用前应该手动初始化 1.分清赋值与初始化 以下例子: class test{ public: int a; test(){ a=0;//赋值 ...

  5. Java异常处理机制 try-catch-finally 剖析

    Java拥有着强大的异常处理机制,最近初步学习了下,感觉内容还是挺多的,特此来将自己的理解写出来与大家分享. 一. 在Java代码code中,由于使用Myeclipse IDE,可以自动提醒用户哪里有 ...

  6. css限制单行文本输入,超出部分使用...替换

    在实际应用中,经常需要只显示一行文字,不允许文字换行破坏整体样式的情况.例如'商品的名称','简介'等等.但是由于显示器的宽度不一样,会出现后台所给文字内容,一行文本容纳不下的情况.溢出的文本如果使用 ...

  7. Blink, 通向哈里·波特的魔法世界

    <哈里·波特>的故事里面,魔法界的新闻报纸都是动画的,配图带有动画效果.能够回放新闻的主要场景. 初次看到这个,感觉还挺新鲜的.不过现在,Blink 这样的 App 可以让这个魔法世界的幻 ...

  8. Android—基于Socket与上传图片到客户端

    最近项目中需要客户端和Socket互相传递数据时候需要相互传递图片所以做下总结以免以后忘记,也希望给大家带来帮助. 先上客户端的代码: 根据图片名称上传照相机中单个照片(此方法为自己封装) 参数所代表 ...

  9. Android Fragment使用(二) 嵌套Fragments (Nested Fragments) 的使用及常见错误

    嵌套Fragment的使用及常见错误 嵌套Fragments (Nested Fragments), 是在Fragment内部又添加Fragment. 使用时, 主要要依靠宿主Fragment的 ge ...

  10. Android Do not keep activities选项分析

    Android Do not keep activities选项分析 Developer Options里面有一项: Do not keep activities -> 不保留Activitie ...