2017-03-09html
1 背景及目標
2 環境配置
2.1 SVN的安裝及使用
2.2 新建Jenkins任務
3 過程分析git
返回服務器
上一篇文章Selenium Web 自動化 - 項目持續集成中用到Jenkins+Git實現持續集成。能夠實現自動化部署、運行、發送運行結果。但這裏還有幾個問題:ide
因爲某些測試人員沒有開發經驗,生成unittest代碼文件,可能會出錯。因此,咱們的這篇文章的實現這樣的目標:svn
當有新的用例(兩個excel)建立且checkin的時候,jenkins能調用命令生成unittest代碼文件並checkin到git(這裏是commit到svn),且jenkins開始構建。post
返回測試
SVN客戶端:TortoiseSVN使用詳細步驟url
SVN服務器端:用VisualSVN作項目版本控制 spa
配置下SVN服務器端,以下圖所示,詳情見用VisualSVN作項目版本控制
圖1 配置SVN服務器端
注意:上圖中用戶Developer1在2.2節Step2命令svn commit中會用到,在step3jenkin任務配置中也會用到。
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」會作以下操做:
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任務
1 用戶新增或修改用例(參數)並commit後
2 Jenkins會執行PreStep,即調用命令GenerateCodeAndCommit.bat。這裏有三種狀況:
3 Jenkins開始構建