zoukankan      html  css  js  c++  java
  • Selenium Web 自动化

    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:StudyQkHttpTest
    ::运行可执行jar包
    java -jar TCGenerateUnitCode.jar DR
    ::将目录下所有新增java文件标记为add
    svn add srccomqf	estunittest*.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" srccomqf	estunittest*.java

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

    1. 输入文件名作为参数,比如:DR
    2. 把DR和testTestCase拼接成新的目录testTestCaseDR,在这个目录下读取所有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和testTestCase拼接成新的目录testTestCaseDR,在这个目录下读取所有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; 
    "
                        + "import org.testng.annotations.Test; 
    "
                        + "import com.qf.test.unittest.base.BaseParpare; 
     "
                        + "import com.qf.test.bll.TestProcess; 
    "
    
                        + "public class " + moduleName.toUpperCase()
                        + "_Test extends BaseParpare{ 
    ");
    
                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
                            + "
    public void"
                            + " "
                            + functionName
                            + "_Test() {
    "
                            + "	TestProcess.Run(testcasefolderPath,"
                            + """
                            + moduleName.toUpperCase()
                            + "",""
                            + functionName.replaceFirst(functionName
                                    .substring(0, 1), functionName.substring(0, 1)
                                    .toUpperCase()) + "");
    " + " }
    ");
                }
    
                // 代码结尾大括号
                writer.write("}");
                writer.close();
            } catch (IOException ex) {
                System.out.println("Error: " + functionName + "
    "
                        + 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;
        }
    }
    View Code

    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开始构建

  • 相关阅读:
    AX2009 VS平台报表开发学习笔记(二)数据源
    字符集的问题
    php侧拉菜单,漂亮,可以向右或者向左展开,支持FF,IE
    ASP正则函数替换分页后的参数
    asp 图片正则 替换,替换前检查图片是不是本地地址的方法
    asp正则过滤重复字符串的代码
    PHP 正则 email语句详解
    签东软了
    东软医疗面试归来
    linux的svn co
  • 原文地址:https://www.cnblogs.com/Ming8006/p/6522382.html
Copyright © 2011-2022 走看看