Selenium Web 自动化 - 项目持续集成(进阶)

2017-03-09

目录

1 背景及目标
2 环境配置
  2.1 SVN的安装及使用
  2.2 新建Jenkins任务
3 过程分析

1 背景及目标


返回

上一篇文章Selenium Web 自动化 - 项目持续集成中用到Jenkins+Git实现持续集成。可以实现自动化部署、运行、发送运行结果。但这里还有几个问题:

  1. 当有新的用例,我们除了要添加两个Excel(一个用于定位元素,一个用于记录操作步骤和操作数据),还要生成unittest的代码文件。
  2. 让后把两个excel和生成的unittest代码文件checkin到git。

由于某些测试人员没有开发经验,生成unittest代码文件,可能会出错。所以,我们的这篇文章的实现这样的目标

  当有新的用例(两个excel)创建且checkin的时候,jenkins能调用命令生成unittest代码文件并checkin到git(这里是commit到svn),且jenkins开始构建。

2 环境配置


返回

2.1 SVN的安装及使用

SVN客户端:TortoiseSVN使用详细步骤

SVN服务器端:用VisualSVN做项目版本控制

配置下SVN服务器端,如下图所示,详情见用VisualSVN做项目版本控制

图1 配置SVN服务器端

注意:上图中用户Developer1在2.2节Step2命令svn commit中会用到,在step3jenkin任务配置中也会用到。

2.2 新建Jenkins任务

Step1:选择SVN,设置Repository URL和Credentials;

注意:要显示Credentials,需安装插件“Subversion Plug-in”

Step2:配置PreSteps,输入命令GernerateCodeAndCommit.bat;

::设置svn客户端代码为当前目录
cd D:\Study\QkHttpTest
::运行可执行jar包
java -jar TCGenerateUnitCode.jar DR
::将目录下所有新增java文件标记为add
svn add src\com\qf\test\unittest\*.java
::将标记为add或修改的java文件commit,注意:这里要添加用户名、密码,否则jekins没有权限add,会抛错:svn: E215004: No more credentials or we tried too many times。查看jenkens问题,见https://issues.jenkins-ci.org/browse/JENKINS-14781
svn --username Developer1 --password Developer1 commit -m "add unittest files" src\com\qf\test\unittest\*.java

这里的“TCGenerateUnitCode.jar”会做如下操作:

  1. 输入文件名作为参数,比如:DR
  2. 把DR和test\TestCase拼接成新的目录test\TestCase\DR,在这个目录下读取所有testcase,并生成unittest入口的java文件
  3. 把这个文件放到src/com/qf/test/unittest下

TCGenerateUnitCode代码如下:

package com.qf.test.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
import java.util.Scanner; import org.testng.Assert;
import org.testng.DependencyMap; import com.qf.test.dal.RWTxtFileWithJackson;
import com.qf.test.dal.RWTxtFileWithBuffer;
import com.qf.test.entity.Dependence;
import com.qf.test.entity.TestCase; /*
* 输入文件名作为参数,比如:DR
* 把DR和test\TestCase拼接成新的目录test\TestCase\DR,在这个目录下读取所有testcase,并生成unittest入口的java文件
* 把这个文件放到src/com/qf/test/unittest下
*/
public class TestCaseFactoryForModule {
static String caseFolder = "test\\TestCases"; public static void main(String[] args) throws Exception { final String casePageFolder = "src/com/qf/test/unittest";
String moduleName = null;
File sourceFile = null; // @SuppressWarnings("resource")
// // 从控制台可以输入
// Scanner s = new Scanner(System.in);
// System.out.println("请输入模块名称(不要按回车键,输入完成之后请再按回车键):");
// moduleName = s.nextLine();// 输入模块名字 moduleName = args[0];
moduleName = moduleName.replaceFirst(moduleName.substring(0, 1),
moduleName.substring(0, 1).toLowerCase());
// 如果包名不存在,就新建
// File functionPackage = new File(caseFolder + "/" + moduleName);
File functionPackage = new File(casePageFolder);
if (functionPackage.exists()) {
System.out.println(functionPackage + "包已经存在,自动跳过!");
System.out.println("正在生成用例到" + moduleName + "包下,请稍等...");
} else {
functionPackage.mkdir();
System.out.println(functionPackage + "包已创建!");
System.out.println("正在生成用例到" + moduleName + "包下,请稍等...");
} String functionName = null;
sourceFile = new File(casePageFolder + File.separator
+ moduleName.toUpperCase() + "_Test.java");// 创建测试用例源码,指定存放路径
try {
FileWriter writer = new FileWriter(sourceFile);
// 生成测试用例代码的头文件
writer.write("package com.qf.test.unittest; \n"
+ "import org.testng.annotations.Test; \n"
+ "import com.qf.test.unittest.base.BaseParpare; \n "
+ "import com.qf.test.bll.TestProcess; \n" + "public class " + moduleName.toUpperCase()
+ "_Test extends BaseParpare{ \n"); for (int i = 0; i < getFunctionNum(moduleName); i++) { // 第一层循环
// 取得模块的个数 functionName = getFunctionName(moduleName, i);// 获得每轮循环的
// 模块名 TestCase tc = RWTxtFileWithJackson.Read(caseFolder + "\\"
+ moduleName + "\\" + functionName + ".csv"); Dependence[] dep = tc.getDependencies(); functionName = functionName.replaceFirst(
functionName.substring(0, 1),
functionName.substring(0, 1).toLowerCase()); // @Test(dependsOnMethods = {"PostwithImages"}) String testcase = null;
String testcases = "";
if (dep != null) {
for (int k = 0; k < dep.length; k++) {
testcase = dep[k].getTestcase();
testcase = testcase.replaceFirst(
testcase.substring(0, 1),
testcase.substring(0, 1).toLowerCase())
+ "_Test";
if (testcases != "")
testcases = testcases + "\",\"" + testcase;
else
testcases = testcase;
}
testcases = "(dependsOnMethods = {\"" + testcases + "\"})"; } // @Test的主体部分,也就是测试用例的方法 writer.write("@Test"
+ testcases
+ "\npublic void"
+ " "
+ functionName
+ "_Test() {\n"
+ "\tTestProcess.Run(testcasefolderPath,"
+ "\""
+ moduleName.toUpperCase()
+ "\",\""
+ functionName.replaceFirst(functionName
.substring(0, 1), functionName.substring(0, 1)
.toUpperCase()) + "\");\n" + " }\n");
} // 代码结尾大括号
writer.write("}");
writer.close();
} catch (IOException ex) {
System.out.println("Error: " + functionName + "\n"
+ ex.getMessage());
return;
} System.out.println("模块[" + moduleName + "] 的用例已经生成完毕,共计:"
+ getFunctionNum(moduleName) + "条,请到" + casePageFolder + "/"
+ "路径下查阅!"); } /**
* 获得当前路径下模块个数
*
* @return 得到模块的个数
*/
public static int getFunctionNum(String moduleName) {
int countNotfile = 0;
String path = caseFolder + "\\" + moduleName;
File file = new File(path);
File[] array = file.listFiles(); for (int i = 0; i < array.length; i++) {
if (!array[i].isFile())
countNotfile = countNotfile + 1;
}
return array.length - countNotfile; } /**
* 获得模块名字 也就是excel 表名
*
* @param 循环模块名称的角标
* @return 得到对应index的模块名字
*/
public static String getFunctionName(String moduleName, int index) {
int countNotfile = 0;
String path = caseFolder + "\\" + moduleName;
// path="D:\\Program Files (x86)\\Jenkins\\jobs\\SvnQkHttpTest\\workspace\\test\\TestCases\\DR";
String functionName = "";
// get file list where the path has
File file = new File(path); // get the folder list
File[] array = file.listFiles(); for (int i = 0; i <= index; i++) {
if (!array[i].isFile())
countNotfile = countNotfile + 1;
}
index += countNotfile; if (array[index].isFile()) {
functionName = array[index].getName().substring(0,
array[index].getName().lastIndexOf("."));
}
return functionName;
}
}

Step3:设置触发条件,选择Poll SCM,日程表* * * * *,表示每当每隔1分钟扫描svn,若有commit操作,开始构建。

图2 新建Jenkins任务

3 过程分析


返回

1 用户新增或修改用例(参数)并commit后

2 Jenkins会执行PreStep,即调用命令GenerateCodeAndCommit.bat。这里有三种情况:

  • 若新建testcase目录并加入testcase,会生成新的unittest入口java文件,svn把这个文件标记为add并commit;
  • 若在已有的testcase目录加入testcase,会修改已有unittest入口Java文件,svn直接commit这个文件;
  • 若只修改已有testcase,已有unittest入口java文件不变,不做svn操作。

3 Jenkins开始构建

Selenium Web 自动化 - 项目持续集成(进阶)的更多相关文章

  1. Selenium Web 自动化 - 项目持续集成

    Selenium Web 自动化 - 项目持续集成 2017-02-13 目录 1环境准备  1.1 安装git  1.2 安装jenkins  1.3 安装jenkins插件  1.4 jekins ...

  2. Selenium Web 自动化 - 项目实战环境准备

    Selenium Web 自动化 - 项目实战环境准备 2016-08-29 目录 1 部署TestNG  1.1 安装TestNG  1.2 添加TestNG类库2 部署Maven  2.1 mav ...

  3. Selenium Web 自动化 - 项目实战(三)

    Selenium Web 自动化 - 项目实战(三) 2016-08-10 目录 1 关键字驱动概述2 框架更改总览3 框架更改详解  3.1 解析新增页面目录  3.2 解析新增测试用例目录  3. ...

  4. Selenium Web 自动化 - 项目实战(二)

    Selenium Web 自动化 - 项目实战(二) 2016-08-08 什么是数据驱动?简答的理解就是测试数据决定了测试结果,这就是所谓数据驱动.数据驱动包含了数据,他就是测试数据,在自动化领域里 ...

  5. Selenium Web 自动化 - 项目实战(一)

    Selenium Web 自动化 - 测试框架(一) 2016-08-05 目录 1 框架结构雏形2 把Java项目转变成Maven项目3 加入TestNG配置文件4 Eclipse编码修改5 编写代 ...

  6. Selenium Web 自动化

    1 Selenium Web 自动化 - Selenium(Java)环境搭建 2 Selenium Web 自动化 - 如何找到元素 3 Selenium Web 自动化 - Selenium常用A ...

  7. Selenium Web 自动化 - Selenium(Java)环境搭建

    Selenium Web 自动化 - Selenium(Java)环境搭建 2016-07-29 1 下载JDK JDK下载地址:http://www.oracle.com/technetwork/j ...

  8. Jenkins +Maven+Tomcat+SVN +Apache项目持续集成构建

    详解Jenkins +Maven+Tomcat+SVN +Apache项目持续集成 一:前言 1. Jenkins jenkins版本大全http://mirrors.jenkins-ci.org/ ...

  9. RobotFramework自动化测试框架-Selenium Web自动化(二)关于在RobotFramework中如何使用Selenium很全的总结(上)

    好久没有继续分享关于自动化测试相关的东西了,自动化在现今的测试领域已经越来越重要了,大部分公司在测试岗位招聘中都需要会相关的自动化测试知识.而 RobotFramework自动化测试框架 是自动化测试 ...

随机推荐

  1. Spring新下载地址

    Spring官网改版后找了好久都没有找到直接下载Jar包的链接,下面汇总些网上提供的方法,亲测可用. 1.直接输入地址,改相应版本即可:http://repo.springsource.org/lib ...

  2. Java经典案例之-判断兔子的数量(斐波那契数列)

    /** * 描述:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子, * 假如兔子都不死,问每个兔子总数为多少? * 分析:根据题目条件可以推断 * 兔子的规律 ...

  3. C语言的位运算的优势

    位运算加速技巧1. 如果乘上一个2的倍数数值,可以改用左移运算(Left Shift) 加速 300% x = x * 2;x = x * 64;//改为:x = x << 1; // 2 ...

  4. 在ubuntu下增加root用户并登录

    1.打开终端. 2.输入sudo gedit /usr/share/lightdm/lightdm.conf.d/50-ubuntu.conf 3.在弹出的编辑框里输入:greeter-show-ma ...

  5. #图# #最大生成树# #kruskal# ----- OpenJudge 799:Heavy Transportation

    OpenJudge 799:Heavy Transportation 总时间限制: 3000ms 内存限制: 65536kB 描述BackgroundHugo Heavy is happy. Afte ...

  6. 算法一之N皇后问题

    (写这篇文章主要是明天就要考试了,算法考试,今天不想再复习了,xiang着今天也开通了博客,于是在这个平台上进行复习,应该会更高效.最后祝愿我明天考个好成绩.嘻嘻...) n皇后问题,主要是应用到回溯 ...

  7. 在Flex中使用文件系统

    一.File和FileStream对象File和FileStream是AIR文件系统中,重要的组成部分,File对象有许多属性,用于唯一区别它与文件系统上的其他文件对象,属性包括:url/native ...

  8. vue初探

    vue初探 很多同学一定都听过MVVM.组件.数据绑定之类的专业术语,而vue框架正是这样的一种框架.vue的作用是:通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件. 第一部分:vue介 ...

  9. web前端性能调优(二)

    项目经过第一波优化之后APP端已基本已经符合我们的要求了,但是TV端还是反应比较慢,页面加载和渲染都比较慢了一点,我觉的还是有必要在进行一些优化,经过前面的优化,我们的优化空间已经小了一部分,不过还是 ...

  10. 定时任务管理中心(dubbo+spring)-我们到底能走多远系列47

    我们到底能走多远系列47 扯淡: 又是一年新年时,不知道上一年你付出了多少,收获了多少呢?也许你正想着老板会发多少奖金,也许你正想着明年去哪家公司投靠. 这个时间点好好整理一下,思考总结一下,的确是个 ...