> getFailCases(String logPath) {
36 | return fc.findFailedCases(logPath);
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/test/java/com/weibo/runfail/NewFailCasesMvn.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runfail;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.FileNotFoundException;
6 | import java.io.FileReader;
7 | import java.io.IOException;
8 | import java.io.Reader;
9 | import java.lang.reflect.Method;
10 | import java.util.ArrayList;
11 | import java.util.HashMap;
12 | import java.util.HashSet;
13 | import java.util.LinkedHashMap;
14 | import java.util.List;
15 | import java.util.Map;
16 | import java.util.Set;
17 | import java.util.regex.Matcher;
18 | import java.util.regex.Pattern;
19 |
20 | import org.junit.Ignore;
21 | import org.junit.Test;
22 |
23 |
24 | /*
25 | *
26 | * 正则匹配出失败用例,maven-surefire-customresult自定义输出格式
27 | *
28 | * CustomResult Fail@后面
29 | *
30 | * CustomResult Error@后面
31 | *
32 | * 1) 后面带(),com.weibo.cases.wanglei16.PublicMentionsStatusTest.testFilterType(com.weibo.cases.wanglei16.PublicMentionsStatusTest)
33 | * 2)后面不带(),com.weibo.cases.maincase.XiaoyuGroupStatusLikeBVTTest.com.weibo.cases.maincase.XiaoyuGroupStatusLikeBVTTest
34 | *
35 | *
36 | *
37 | *
38 | *
39 | * @author hugang
40 | */
41 | public class NewFailCasesMvn extends FailCases {
42 |
43 | // 找出所有失败用例 每行字符串信息
44 | public Set failCasesStr(String logPath){
45 | String failRegex = "^CustomResult Fail@(.*)";
46 | Pattern failPattern = Pattern.compile(failRegex);
47 | Matcher matchFail;
48 |
49 | String errorRegex = "^CustomResult Error@(.*)";
50 | Pattern errorPattern = Pattern.compile(errorRegex);
51 | Matcher matchError;
52 |
53 | // 去掉重复的
54 | Set failSet = new HashSet();
55 |
56 | try (BufferedReader bre = new BufferedReader(new FileReader(new File(logPath)));){
57 | while (bre.ready()) {
58 | String str = bre.readLine();
59 | matchFail = failPattern.matcher(str);
60 | matchError = errorPattern.matcher(str);
61 | if(matchFail.matches() || matchError.matches()){
62 | failSet.add(str);
63 | }
64 | }
65 | } catch (IOException e) {
66 | // TODO Auto-generated catch block
67 | e.printStackTrace();
68 | }
69 | return failSet;
70 | }
71 |
72 | // 处理字符串信息, 将信息转换成Map
73 | public Map, List> getResultMap(Set failSet) {
74 | Map, List> resultMap = new LinkedHashMap, List>();
75 | String className;
76 | List methodList = new ArrayList();
77 | Class> failClass = null;
78 | // 标记Class是否将全部方法放入Map中
79 | Map, Integer> bitMap = new HashMap, Integer>();
80 | for(String str : failSet){
81 | // 先处理不带(), 表示整个类失败
82 | if( ! str.contains("(")){
83 | className = str.substring(str.lastIndexOf("com"), str.length());
84 | try {
85 | failClass = Class.forName(className);
86 | } catch (ClassNotFoundException e) {
87 | // TODO Auto-generated catch block
88 | e.printStackTrace();
89 | }
90 | // 拿失败类中的方法
91 | Method[] met = failClass.getMethods();
92 | for (Method method : met) {
93 | // 只拿@Test 方法
94 | if (method.isAnnotationPresent(Test.class)
95 | && (!method
96 | .isAnnotationPresent(Ignore.class))) {
97 | // method.getName() 返回的格式:testLikeVideo
98 | System.out.println(method.getName());
99 | methodList.add(method.getName());
100 | }
101 | }
102 | resultMap.put(failClass, methodList);
103 | bitMap.put(failClass, 1);
104 | }else{
105 | // 处理单个测试方法
106 | className = str.substring(str.indexOf("(") + 1, str.length() - 1);
107 | try {
108 | failClass = Class.forName(className);
109 | } catch (ClassNotFoundException e) {
110 | // TODO Auto-generated catch block
111 | e.printStackTrace();
112 | }
113 |
114 | // 之后支持 添加JUnitCore格式
115 | int last = str.indexOf("(");
116 | String methodPart = str.substring(str.lastIndexOf(".", last) + 1, last);
117 |
118 |
119 | // 判断该类是否已通过“类”的方式进入错误用例集,不存在,则以“方法(类)”处理
120 | if(!bitMap.containsKey(failClass)){
121 | // 聚合 class-method 一对多
122 | if (resultMap.containsKey(failClass)) {
123 | // 拿到之前的class 对应的list, 并在该list下新增 method, 再放回map
124 | List beforeFailMethod = resultMap
125 | .get(failClass);
126 | beforeFailMethod.add(methodPart);
127 | resultMap.put(failClass, beforeFailMethod);
128 | } else {
129 | // 第一次添加该class时
130 | List firstMethod = new ArrayList();
131 | firstMethod.add(methodPart);
132 | resultMap.put(failClass, firstMethod);
133 | }
134 | }
135 | }
136 | }
137 |
138 | int casesNum = 0;
139 | List myMethod = new ArrayList();
140 | for(Map.Entry, List> myCases: resultMap.entrySet()){
141 |
142 | myMethod = myCases.getValue();
143 | casesNum += myMethod.size();
144 | System.out.println(myCases.getKey() + ":" + myMethod + ":" + myMethod.size() );
145 | }
146 | System.out.println("mvn 找到用例数:" + casesNum);
147 | return resultMap;
148 | }
149 |
150 | @Override
151 | public Map, List> findFailedCases(String logPath) {
152 | return getResultMap(failCasesStr(logPath));
153 | }
154 |
155 | }
156 |
--------------------------------------------------------------------------------
/src/test/java/com/weibo/runfail/NewWriteLogMvn.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runfail;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.BufferedWriter;
5 | import java.io.File;
6 | import java.io.FileReader;
7 | import java.io.FileWriter;
8 | import java.io.IOException;
9 | import java.text.SimpleDateFormat;
10 | import java.util.ArrayList;
11 | import java.util.Date;
12 | import java.util.List;
13 | import java.util.regex.Matcher;
14 | import java.util.regex.Pattern;
15 |
16 | /*
17 | * 将JUnitCore执行结果,回写到源日志
18 | * author hugang
19 | */
20 | public class NewWriteLogMvn {
21 |
22 |
23 | // 格式转换,将JUnitCore装换成Mvn
24 | public List FormatJUnitCoreToMvn(List failStr){
25 | List mvnFailList = new ArrayList();
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | return mvnFailList;
34 | }
35 |
36 |
37 |
38 | public void writeLogMvn(String logPath, String resultPath)
39 | throws IOException {
40 | BufferedWriter writer;
41 | BufferedReader reader;
42 |
43 | // 日志文件
44 | File sourceFile = new File(logPath);
45 | if (!sourceFile.exists()) {
46 | sourceFile.createNewFile();
47 | }
48 | writer = new BufferedWriter(new FileWriter(sourceFile));
49 |
50 | // 结果日志
51 | File readFile = new File(resultPath);
52 | if (!readFile.exists()) {
53 | readFile.createNewFile();
54 | System.out.println("read 文件不存在, Result.txt 不存在");
55 | } else {
56 | System.out.println("" + readFile.canRead() + " "
57 | + readFile.length() + " " + readFile.getAbsolutePath()
58 | + " " + readFile.getCanonicalPath());
59 | }
60 | reader = new BufferedReader(new FileReader(readFile));
61 |
62 | // 1
63 | // 根据Result.txt , 正则表达式找失败用例
64 | // 形如 方法(类) 格式
65 | // [GroupChatNotFrontTest(com.weibo.cases.xiaoyu.FrontAppStatusesTest):
66 | // should create success]
67 | String pattern = "\\[(\\w+)\\((.*)\\):(.*)\\]";
68 | Pattern pt = Pattern.compile(pattern);
69 | Matcher mt;
70 |
71 | List strList = new ArrayList();
72 |
73 | // 2
74 | // 根据Result.txt , 正则表达式找失败用例(只提供失败类信息)
75 | // 形如:
76 | // [com.weibo.cases.xiaoyu.FrontAppStatusesTest: It should get success]
77 | String patternClass = "\\[((\\w+\\.)+(\\w+)):(.*)\\]";
78 | Pattern ptClass = Pattern.compile(patternClass);
79 | Matcher mtClass;
80 |
81 | // 行号
82 | List flags = new ArrayList();
83 | int i = 0;
84 |
85 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
86 |
87 | writer.write(sdf.format(new Date()));
88 | writer.write("mvn 回写失败结果");
89 | writer.newLine();
90 |
91 | String failStackTrace = "CustomResult Failed StackTrace@";
92 | String failInfo = "CustomResult Fail@";
93 | String failMethodStackTraceStr;
94 | String failMethodInfoStr;
95 |
96 | String failClassStackTraceStr;
97 | String failClassInfoStr;
98 | try {
99 | while (reader.ready()) {
100 | String str = reader.readLine();
101 | strList.add(str);
102 | mt = pt.matcher(str);
103 | mtClass = ptClass.matcher(str);
104 | // 匹配1后,记录匹配的行号
105 | if (mt.find()) {
106 | String[] className = mt.group(2).split("\\.");
107 | int size = className.length;
108 | String methodName = mt.group(1);
109 | // 模拟MVN 日志
110 | // 1.错误栈信息,供前端解析
111 | // CustomResult Failed StackTrace@SassPart2ShortUrlStatusTest.testPublicRepost:88 testPublicRepost exception
112 | failMethodStackTraceStr = failStackTrace + className[size - 1] + "."
113 | + methodName + mt.group(3).replaceAll("\n", "");
114 | // 2.用例信息
115 | // CustomResult Fail@com.weibo.cases.wanglei16.SassPart2ShortUrlStatusTest.testPublicRepost(com.weibo.cases.wanglei16.SassPart2ShortUrlStatusTest)
116 | failMethodInfoStr = failInfo + mt.group(2) + "." + methodName + "(" + mt.group(2) + ")";
117 | writer.write(failMethodStackTraceStr);
118 | // 供前端解析
119 | System.out.println(failMethodStackTraceStr);
120 | writer.newLine();
121 | writer.write(failMethodInfoStr);
122 | writer.newLine();
123 | i++;
124 | }
125 | // 类失败
126 | if (mtClass.find()) {
127 | // 模拟MVN 日志
128 | // 1.错误栈信息, group(1) 全限类名, group(4)栈信息
129 | failClassStackTraceStr = failStackTrace + mtClass.group(1) + " " + mtClass.group(4).replaceAll("\n", "");
130 | // com.weibo.cases.maincase.XiaoyuGroupStatusLikeBVTTest.com.weibo.cases.maincase.XiaoyuGroupStatusLikeBVTTest
131 | failClassInfoStr = failInfo + mtClass.group(1) + "." + mtClass.group(1);
132 | writer.write(failClassStackTraceStr);
133 | // 供前端解析
134 | System.out.println(failClassStackTraceStr);
135 | writer.newLine();
136 | writer.write(failClassInfoStr);
137 | writer.newLine();
138 | i++;
139 | }
140 | }
141 |
142 | } finally {
143 | writer.close();
144 | reader.close();
145 |
146 | }
147 |
148 | }
149 |
150 | }
151 |
--------------------------------------------------------------------------------
/src/test/java/com/weibo/runfail/RealClassMvn.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runfail;
2 | /*
3 | * @author hugang
4 | */
5 | public class RealClassMvn {
6 | String[] packageName = {
7 | "com.weibo.cases.hugang", "com.weibo.cases.lingna", "com.weibo.cases.maincase",
8 | "com.weibo.cases.qiaoli", "com.weibo.cases.wanglei16", "com.weibo.cases.xiaoyu",
9 | "com.weibo.cases.xuelian", "com.weibo.cases.beibei12", "com.weibo.cases.publicservice",
10 | "com.weibo.cases.yanlei3", "com.weibo.cases.guanglu"
11 | };
12 |
13 | int now = 0;
14 | int retryNum = packageName.length;
15 |
16 | String realClassName;
17 |
18 |
19 | public String getRealClassName() {
20 | return realClassName;
21 | }
22 |
23 |
24 | public void setRealClassName(String realClassName) {
25 | this.realClassName = realClassName;
26 | }
27 |
28 | // 由于, mvn执行结果中失败的用例只返回类名(ActivitiesTimelineSpActivitiesTest),
29 | // 而不是完全类名
30 | // (包括包名,e.g.com.weibo.cases.xuelian.ActivitiesTimelineSpActivitiesTest)
31 | // 导致Class.forName(类名)抛异常
32 | // 使用递归加上不同包名,进行判断,找到正确完全类名
33 | public void findClass(String className) throws Throwable{
34 | try{
35 | realClassName = packageName[now++] + "." + className;
36 | Class.forName(realClassName);
37 | setRealClassName(realClassName);
38 | }catch(ClassNotFoundException e){
39 | if(now < retryNum){
40 | findClass(className);
41 | }else{
42 | throw e;
43 | }
44 | }
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/test/java/com/weibo/runfail/Result.txt:
--------------------------------------------------------------------------------
1 | (一).Time's Result generated on: 2015.08.31 13:45:18,722
2 | (二).日志类型:ANT
3 | (三).日志名:/Users/hugang/myworkspace/AutoTestContent/src/test/java/com/weibo/runfail/TEST-com.weibo.cases.suite.LikeTestSuite.txt
4 | ===================== 结果集 =====================
5 | 用例总数:4, 成功数:3, 失败数:1, 运行时间:0 分钟 9 秒
6 | =================================================
7 |
8 | [testMultiType(com.weibo.cases.wanglei16.LikesByMeBatchLikeTest): testMultiType fail]
9 |
10 |
--------------------------------------------------------------------------------
/src/test/java/com/weibo/runfail/RunFailedCases.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runfail;
2 |
3 | import java.io.IOException;
4 | import java.util.List;
5 | import java.util.Map;
6 | import java.util.concurrent.ExecutionException;
7 | /*
8 | *
9 | * 根据ant/mvn 执行日志,执行失败用例
10 | *
11 | * @author hugang
12 | */
13 | public class RunFailedCases {
14 |
15 | // 失败日志名
16 | // public static final String LOGNAME = "725.txt";
17 | // // 日志类型,支持MVN, ANT等2种
18 | // public static final String LOGTYPE = "MVN";
19 | //
20 | // // 失败日志名
21 | public static final String LOGNAME = "TEST-com.weibo.cases.suite.HugangTestSuite.txt";
22 | // 日志类型,支持MVN, ANT等2种
23 | public static final String LOGTYPE = "ANT";
24 | // 运行结果日志名,无需修改
25 | public static final String RESULTLOG = "Result.txt";
26 | // 执行用例方式:
27 | // 1.类级别并发(方法串行)
28 | // 2.方法级别并发
29 | // 3.串行
30 | // 默认以1.类级别并发(方法串行)执行
31 | public static final int RUNTYPE = 1;
32 |
33 | public static void main(String[] args) throws ExecutionException, IOException {
34 | // 记录失败用例,key:Class , value:List of methods
35 | Map, List> failMap;
36 |
37 | // 失败用例日志路径
38 | String logPath = System.getProperty("user.dir")
39 | + System.getProperty("file.separator") + "src"
40 | + System.getProperty("file.separator") + "test"
41 | + System.getProperty("file.separator") + "java"
42 | + System.getProperty("file.separator") + "com"
43 | + System.getProperty("file.separator") + "weibo"
44 | + System.getProperty("file.separator") + "runfail"
45 | + System.getProperty("file.separator")
46 | + LOGNAME;
47 |
48 | // 结果日志路径
49 | String resultPath = System.getProperty("user.dir")
50 | + System.getProperty("file.separator") + "src"
51 | + System.getProperty("file.separator") + "test"
52 | + System.getProperty("file.separator") + "java"
53 | + System.getProperty("file.separator") + "com"
54 | + System.getProperty("file.separator") + "weibo"
55 | + System.getProperty("file.separator") + "runfail"
56 | + System.getProperty("file.separator")
57 | + RESULTLOG;
58 |
59 | System.out.println(logPath);
60 | System.out.println(resultPath);
61 |
62 | // "\"的转义字符
63 | logPath = logPath.replace("\\", "\\\\");
64 |
65 | // 简单工厂模式和策略模式, 根据不同的LOGTYPE创建不同实例
66 | FailCasesContext fcc = new FailCasesContext(LOGTYPE);
67 | // 通过扫日志,拿到对应失败case的Map
68 | failMap = fcc.getFailCases(logPath);
69 |
70 | // 执行失败用例
71 | ExecuteCases ec = new ExecuteCases();
72 | // 执行
73 | switch(RUNTYPE){
74 | case 1:
75 | ec.executorClassCases(failMap, logPath, resultPath, LOGTYPE);
76 | break;
77 | case 2:
78 | ec.executorMethodCases(failMap, logPath, resultPath, LOGTYPE);
79 | break;
80 | case 3:
81 | ec.SerialExecutorCases(failMap, logPath, resultPath, LOGTYPE);
82 | break;
83 | default:
84 | ec.executorClassCases(failMap, logPath, resultPath, LOGTYPE);
85 | break;
86 | }
87 |
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/src/test/java/com/weibo/runfail/ThreadRunTest.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runfail;
2 |
3 | import java.util.concurrent.Callable;
4 |
5 | import org.junit.runner.JUnitCore;
6 | import org.junit.runner.Request;
7 | import org.junit.runner.Result;
8 | /*
9 | * @author
10 | */
11 | //Callable实现类,一个线程执行一个case, 返回结果Result
12 | class ThreadRunTest implements Callable{
13 | private Class oneFailClass;
14 | private String oneFailMethod;
15 |
16 | public ThreadRunTest(Class oneFailClass, String oneFailMethod){
17 | this.oneFailClass = oneFailClass;
18 | this.oneFailMethod = oneFailMethod;
19 | }
20 |
21 |
22 | public Result call() throws Exception {
23 | // TODO Auto-generated method stub
24 | // JUnitCore执行JUnit用例
25 | JUnitCore junitRunner = new JUnitCore();
26 | Request request = Request.method(oneFailClass, oneFailMethod);
27 | Result result = junitRunner.run(request);
28 |
29 | return result;
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/test/java/com/weibo/runfail/WriteLogAnt.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runfail;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.BufferedWriter;
5 | import java.io.File;
6 | import java.io.FileReader;
7 | import java.io.FileWriter;
8 | import java.io.IOException;
9 | import java.text.SimpleDateFormat;
10 | import java.util.ArrayList;
11 | import java.util.Date;
12 | import java.util.List;
13 | import java.util.regex.Matcher;
14 | import java.util.regex.Pattern;
15 |
16 |
17 |
18 | /*
19 | * @author hugang
20 | */
21 | public class WriteLogAnt {
22 | public void writeLogAnt(String logPath, String resultPath)
23 | throws IOException {
24 | BufferedWriter writer;
25 | BufferedReader reader;
26 |
27 | // 日志文件
28 | File sourceFile = new File(logPath);
29 | if (!sourceFile.exists()) {
30 | sourceFile.createNewFile();
31 | }
32 | writer = new BufferedWriter(new FileWriter(sourceFile));
33 |
34 | // 结果日志
35 | File readFile = new File(resultPath);
36 | if (!readFile.exists()) {
37 | readFile.createNewFile();
38 | System.out.println("read 文件不存在, Result.txt 不存在");
39 | } else {
40 | System.out.println("" + readFile.canRead() + " "
41 | + readFile.length() + " " + readFile.getAbsolutePath()
42 | + " " + readFile.getCanonicalPath());
43 | }
44 | reader = new BufferedReader(new FileReader(readFile));
45 |
46 | // 根据Result.txt , 正则表达式找失败用例,
47 | // 形如 方法(类) 格式
48 | // [GroupChatNotFrontTest(com.weibo.cases.xiaoyu.FrontAppStatusesTest):
49 | // should create success]
50 | String pattern = "\\[(\\w+)\\((.*)\\)";
51 |
52 | Pattern pt = Pattern.compile(pattern);
53 | Matcher mt;
54 |
55 | // 根据Result.txt , 正则表达式找失败用例(只提供失败类信息)
56 | // 形如:
57 | // [com.weibo.cases.xiaoyu.FrontAppStatusesTest: It should get success]
58 | String patternClass = "\\[((\\w+\\.)+\\w+):";
59 | Pattern ptClass = Pattern.compile(patternClass);
60 | Matcher mtClass;
61 |
62 | List strList = new ArrayList();
63 | // 行号
64 | List flags = new ArrayList();
65 | int i = 0;
66 |
67 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
68 | // 写时间戳
69 | writer.write(sdf.format(new Date()));
70 | writer.newLine();
71 |
72 | try {
73 | while (reader.ready()) {
74 | String str = reader.readLine();
75 | strList.add(str);
76 | mt = pt.matcher(str);
77 | mtClass = ptClass.matcher(str);
78 | // 匹配后,记录匹配的行号
79 | if (mt.find() || mtClass.find()) {
80 | flags.add(i);
81 | }
82 | i++;
83 | }
84 | for (int k = 0; k < flags.size(); k++) {
85 | // 模拟 FindFailTest.java 截取的规则
86 | String failStr = "Testcase:" + strList.get(flags.get(k));
87 | writer.write(failStr);
88 | writer.newLine();
89 | }
90 | // System.out.println("--------------------------------------");
91 | // System.out.println(" Ant Model find failcases number: " + i);
92 | // System.out.println("--------------------------------------");
93 | // Utils.sleep(2000);
94 | } finally {
95 | writer.close();
96 | reader.close();
97 |
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/test/java/com/weibo/runfail/WriteLogFactory.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runfail;
2 |
3 | import java.io.IOException;
4 | /*
5 | * @author hugang
6 | */
7 | public class WriteLogFactory {
8 | public void writeLog(String logPath, String logType, String resultPath)
9 | throws IOException {
10 | // 为了支持JDK6 , case后用数字; JDK7可以直接String类型
11 | int typeNum = 2;
12 | if ("MVN".equals(logType)) {
13 | typeNum = 1;
14 | } else if ("ANT".equals(logType)) {
15 | typeNum = 2;
16 | }
17 |
18 | switch (typeNum) {
19 | case 1:
20 | // new WriteLogMvn().writeLogMvn(logPath, resultPath);
21 | new NewWriteLogMvn().writeLogMvn(logPath, resultPath);
22 | break;
23 | case 2:
24 | new WriteLogAnt().writeLogAnt(logPath, resultPath);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/test/java/com/weibo/runner/Concurrent.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runner;
2 | import java.lang.annotation.ElementType;
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.RetentionPolicy;
5 | import java.lang.annotation.Target;
6 |
7 | @Retention(RetentionPolicy.RUNTIME)
8 | @Target({ ElementType.TYPE })
9 | public @interface Concurrent {
10 | // int threads() default 400;
11 | int threads() default 100;
12 | }
--------------------------------------------------------------------------------
/src/test/java/com/weibo/runner/ConcurrentSuite.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runner;
2 |
3 | import org.junit.Ignore;
4 | import org.junit.Test;
5 | import org.junit.experimental.categories.Categories;
6 | import org.junit.extensions.cpsuite.ClasspathSuite;
7 | import org.junit.internal.builders.AllDefaultPossibilitiesBuilder;
8 | import org.junit.runner.Runner;
9 | import org.junit.runners.ParentRunner;
10 | import org.junit.runners.model.InitializationError;
11 | import org.junit.runners.model.RunnerBuilder;
12 | import org.junit.runners.model.RunnerScheduler;
13 |
14 |
15 | import java.lang.reflect.Method;
16 | import java.util.ArrayList;
17 | import java.util.Arrays;
18 | import java.util.LinkedList;
19 | import java.util.List;
20 | import java.util.Queue;
21 | import java.util.concurrent.CompletionService;
22 | import java.util.concurrent.ExecutorCompletionService;
23 | import java.util.concurrent.ExecutorService;
24 | import java.util.concurrent.Executors;
25 | import java.util.concurrent.Future;
26 | import java.util.concurrent.ThreadFactory;
27 | import java.util.concurrent.TimeUnit;
28 | import java.util.concurrent.atomic.AtomicInteger;
29 |
30 | /**
31 | *
32 | * 自定义runner, 并发执行
33 | *
34 | *
35 | * @author hugang
36 | *
37 | */
38 | public final class ConcurrentSuite extends ClasspathSuite {
39 |
40 | public static Runner MulThread(Runner runner) {
41 | if (runner instanceof ParentRunner) {
42 | // setScheduler(RunnerScheduler scheduler):Sets a scheduler that
43 | // determines the order and parallelization of children
44 | // RunnerScheduler:Represents a strategy for scheduling when
45 | // individual test methods should be run (in serial or parallel)
46 | ((ParentRunner) runner).setScheduler(new RunnerScheduler() {
47 | private final ExecutorService fService = Executors
48 | .newCachedThreadPool();
49 |
50 | // private final ExecutorService fService =
51 | // Executors.newFixedThreadPool(10);
52 |
53 | // Schedule a child statement to run
54 | public void schedule(Runnable childStatement) {
55 | this.fService.submit(childStatement);
56 | }
57 |
58 | // Override to implement any behavior that must occur after all
59 | // children have been scheduled
60 | public void finished() {
61 | try {
62 | this.fService.shutdown();
63 | this.fService.awaitTermination(9223372036854775807L,
64 | TimeUnit.NANOSECONDS);
65 | } catch (InterruptedException e) {
66 | e.printStackTrace(System.err);
67 | }
68 | }
69 | });
70 | }
71 | return runner;
72 | }
73 |
74 | public ConcurrentSuite(final Class> klass) throws InitializationError {
75 | // 调用父类ClasspathSuite构造函数
76 | // AllDefaultPossibilitiesBuilder根据不同的测试类定义(@RunWith的信息)返回Runner,使用职责链模式
77 | super(klass, new AllDefaultPossibilitiesBuilder(true) {
78 | @Override
79 | public Runner runnerForClass(Class> testClass) throws Throwable {
80 | List builders = Arrays
81 | .asList(new RunnerBuilder[] {
82 | // 创建Runner, 工厂类,
83 | // 自定义自己的Runner,找出注解为@Ignore,并输出@Ignore的类和方法名
84 | new RunnerBuilder() {
85 | @Override
86 | public Runner runnerForClass(
87 | Class> testClass)
88 | throws Throwable {
89 | // 获取类的所有方法
90 | Method[] methods = testClass
91 | .getMethods();
92 |
93 | // 如果类有@Ignore,则只输出类名,因为Junit最后计算结果时,会把@Ignore类记为1个用例,
94 | // 不是计算类下面的测试方法数(实验验证过)
95 | // 否则,遍历方法,如果方法有@Ignore,则输出该方法
96 | if (testClass
97 | .isAnnotationPresent(Ignore.class)) {
98 |
99 | System.out.println("Ignore: "
100 | + testClass.getName());
101 |
102 | } else {
103 | for (Method method : methods) {
104 | if (method
105 | .isAnnotationPresent(Ignore.class)) {
106 | System.out.println("Ignore: "
107 | + testClass
108 | .getName()
109 | + "."
110 | + method.getName());
111 | }
112 | }
113 | }
114 | return null;
115 | }
116 | }, ignoredBuilder(), annotatedBuilder(),
117 | suiteMethodBuilder(), junit3Builder(),
118 | junit4Builder() });
119 | for (RunnerBuilder each : builders) {
120 | // 根据不同的测试类定义(@RunWith的信息)返回Runner
121 | Runner runner = each.safeRunnerForClass(testClass);
122 | if (runner != null)
123 | // 方法级别,多线程执行
124 | // return MulThread(runner);
125 | return runner;
126 | }
127 | return null;
128 | }
129 | });
130 |
131 | // 类级别,多线程执行
132 | setScheduler(new RunnerScheduler() {
133 | private final ExecutorService fService = Executors
134 | .newCachedThreadPool();
135 |
136 | public void schedule(Runnable paramRunnable) {
137 | // TODO Auto-generated method stub
138 | fService.submit(paramRunnable);
139 | }
140 |
141 | public void finished() {
142 | // TODO Auto-generated method stub
143 | try {
144 | fService.shutdown();
145 | fService.awaitTermination(Long.MAX_VALUE,
146 | TimeUnit.NANOSECONDS);
147 | } catch (InterruptedException e) {
148 | e.printStackTrace(System.err);
149 | }
150 | }
151 | //
152 | // // ExecutorService executorService =
153 | // Executors.newFixedThreadPool(
154 | // // klass.isAnnotationPresent(Concurrent.class) ?
155 | // // klass.getAnnotation(Concurrent.class).threads() :
156 | // // (int) (Runtime.getRuntime().availableProcessors() * 1.5),
157 | // // new NamedThreadFactory(klass.getSimpleName()));
158 | // // CompletionService completionService = new
159 | // // ExecutorCompletionService(executorService);
160 | // // Queue> tasks = new LinkedList>();
161 | // //
162 | // // @Override
163 | // // public void schedule(Runnable childStatement) {
164 | // // tasks.offer(completionService.submit(childStatement, null));
165 | // // }
166 | // //
167 | // // @Override
168 | // // public void finished() {
169 | // // try {
170 | // // while (!tasks.isEmpty())
171 | // // tasks.remove(completionService.take());
172 | // // } catch (InterruptedException e) {
173 | // // Thread.currentThread().interrupt();
174 | // // } finally {
175 | // // while (!tasks.isEmpty())
176 | // // tasks.poll().cancel(true);
177 | // // executorService.shutdownNow();
178 | // // }
179 | //
180 | });
181 | }
182 |
183 | // static final class NamedThreadFactory implements ThreadFactory {
184 | // static final AtomicInteger poolNumber = new AtomicInteger(1);
185 | // final AtomicInteger threadNumber = new AtomicInteger(1);
186 | // final ThreadGroup group;
187 | //
188 | // NamedThreadFactory(String poolName) {
189 | // group = new ThreadGroup(poolName + "-"
190 | // + poolNumber.getAndIncrement());
191 | // }
192 | //
193 | // @Override
194 | // public Thread newThread(Runnable r) {
195 | // System.out.println(group.getName() + "-thread-");
196 | //
197 | // return new Thread(group, r, group.getName() + "-thread-"
198 | // + threadNumber.getAndIncrement(), 0);
199 | // }
200 | // }
201 |
202 | }
--------------------------------------------------------------------------------
/src/test/java/com/weibo/runner/Retry.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runner;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | import com.weibo.global.ParseProperties;
9 |
10 | // 重试次数,默认2
11 | // 方法会覆盖类,子类会覆盖父类
12 |
13 | // 重试默认值改用配置文件global.properties中 retry 字段指定
14 | @Retention(RetentionPolicy.RUNTIME)
15 | @Target({ElementType.METHOD,ElementType.TYPE})
16 | public @interface Retry {
17 | int value() default 2;
18 | }
19 |
--------------------------------------------------------------------------------
/src/test/java/com/weibo/runner/RetryRunner.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runner;
2 |
3 |
4 |
5 | import java.lang.annotation.Annotation;
6 |
7 | import junit.framework.AssertionFailedError;
8 |
9 | import org.junit.Ignore;
10 | import org.junit.internal.AssumptionViolatedException;
11 | import org.junit.internal.runners.model.EachTestNotifier;
12 | import org.junit.runner.Description;
13 | import org.junit.runner.notification.RunNotifier;
14 | import org.junit.runner.notification.StoppedByUserException;
15 | import org.junit.runners.BlockJUnit4ClassRunner;
16 | import org.junit.runners.model.FrameworkMethod;
17 | import org.junit.runners.model.InitializationError;
18 | import org.junit.runners.model.MultipleFailureException;
19 | import org.junit.runners.model.Statement;
20 |
21 | import com.weibo.global.ParseProperties;
22 |
23 | /**
24 | * 自定义runner, 运行中重试
25 | * @author hugang
26 | *
27 | */
28 | public class RetryRunner extends BlockJUnit4ClassRunner {
29 |
30 | private int retryTime;
31 | private int now = 0;
32 |
33 | public RetryRunner(Class> klass) throws InitializationError {
34 | super(klass);
35 | }
36 |
37 | @Override
38 | protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
39 | Description description = describeChild(method);
40 | if (method.getAnnotation(Ignore.class) != null) {
41 | notifier.fireTestIgnored(description);
42 | } else
43 | try {
44 | if (shouldRetry(method)) { // 需要重试,走重试逻辑
45 | runLeafRetry(methodBlock(method), description, notifier);
46 | } else { // 不需要重试,走原来逻辑
47 | runLeaf(methodBlock(method), description, notifier);
48 | }
49 | } catch (Exception e) {
50 | // TODO Auto-generated catch block
51 | e.printStackTrace();
52 | }
53 | }
54 |
55 | private boolean shouldRetry(final FrameworkMethod method) throws Exception {
56 | Retry retry = null;
57 | // 类上有@Retry
58 | retry = getClassRetry(getTestClass().getJavaClass());
59 | // 方法有@Retry
60 | Retry annotation = method.getAnnotation(Retry.class);
61 | // 方法的@Retry替换类的@Retry
62 | if (annotation != null) {
63 | retry = annotation;
64 | }
65 | if (retry != null) {
66 | if (retry.value() > 0) {
67 | // 之前根据注解@Retry, 获取重试次数
68 | // retryTime = retry.value();
69 | // 现在更改为,根据global.properties中retry判断次数, 为空不重试, 其他值为默认重试次数
70 | String retryProperty = ParseProperties.getSystemProperty("retry");
71 | if("".equals(retryProperty) || (1 == retry.value())){
72 | retryTime = 1;
73 | }else{
74 | retryTime = Integer.parseInt(retryProperty);
75 | }
76 | // System.out.println("test property get retry: " + retryTime);
77 | } else {
78 | // retry.value()<=0时,为1
79 | retryTime = 1;
80 | }
81 | now = 0;
82 | return true;
83 | }
84 | return false;
85 | }
86 |
87 | private Retry getClassRetry(Class> mClass) {
88 | if (mClass == null || mClass == Object.class) {
89 | return null;
90 | }
91 | Retry retry = null;
92 | Annotation[] annotations = mClass.getAnnotations();
93 | for (Annotation annotation : annotations) {
94 | if (annotation instanceof Retry) {
95 | retry = (Retry) annotation;
96 | break;
97 | }
98 | }
99 | // 判断父类
100 | if (null == retry) {
101 | retry = getClassRetry(mClass.getSuperclass());
102 | }
103 | return retry;
104 | }
105 |
106 | protected final void runLeafRetry(Statement statement,
107 | Description description, RunNotifier notifier) {
108 | EachTestNotifier eachNotifier = new EachTestNotifier(notifier,
109 | description);
110 | eachNotifier.fireTestStarted();
111 | try {
112 | retryRun(statement);
113 | // 标记成功用例信息
114 | System.out.println("SuccessCase: " + description);
115 | } catch (AssumptionViolatedException e) {
116 | eachNotifier.addFailedAssumption(e);
117 | } catch (Throwable e) {
118 | eachNotifier.addFailure(e);
119 | } finally {
120 | eachNotifier.fireTestFinished();
121 | }
122 | }
123 |
124 | private void retryRun(Statement statement) throws Throwable {
125 | try {
126 | now++;
127 | statement.evaluate();
128 |
129 | } catch (AssertionFailedError e) {
130 | if (now < retryTime) {
131 | retryRun(statement);
132 | } else {
133 | throw e;
134 | }
135 | } catch (MultipleFailureException e) {
136 | if (now < retryTime) {
137 | retryRun(statement);
138 | } else {
139 | throw e;
140 | }
141 | } catch (AssertionError e) {
142 | // assertThat断言失败,抛AssertionError
143 | if (now < retryTime) {
144 | retryRun(statement);
145 | } else {
146 | throw e;
147 | }
148 | } catch (Throwable e) {
149 | // Throwable 所有异常
150 | if (now < retryTime) {
151 | retryRun(statement);
152 | } else {
153 | throw e;
154 | }
155 | }
156 | }
157 |
158 | }
159 |
--------------------------------------------------------------------------------
/src/test/java/com/weibo/runner/ThreadRunner.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runner;
2 |
3 | import java.util.concurrent.Executor;
4 | import java.util.concurrent.ExecutorService;
5 | import java.util.concurrent.Executors;
6 | import java.util.concurrent.atomic.AtomicInteger;
7 |
8 | import org.junit.runner.notification.RunNotifier;
9 | import org.junit.runners.BlockJUnit4ClassRunner;
10 | import org.junit.runners.model.FrameworkMethod;
11 | import org.junit.runners.model.InitializationError;
12 | import org.junit.runners.model.Statement;
13 |
14 | /**
15 | * Runs all tests in parallel and waits for them to complete.
16 | * Up to {@link #maxThreads} will be run at once.
17 | * 自定义runner: 单个测试类,方法并发执行
18 | * @hugang
19 | *
20 | */
21 | public class ThreadRunner extends BlockJUnit4ClassRunner {
22 |
23 | private AtomicInteger numThreads;
24 |
25 | public static int maxThreads = 25;
26 |
27 | public ThreadRunner(Class> klass) throws InitializationError {
28 | super(klass);
29 | // TODO Auto-generated constructor stub
30 | numThreads = new AtomicInteger(0);
31 | }
32 |
33 | protected void runChild(final FrameworkMethod method, final RunNotifier notifier) {
34 | while(numThreads.get() > maxThreads){
35 | try{
36 | Thread.sleep(1000);
37 | }catch(InterruptedException e){
38 | e.printStackTrace();
39 | return;
40 | }
41 | }
42 |
43 | numThreads.incrementAndGet();
44 | new Thread(new Test(method, notifier)).start();
45 | }
46 |
47 | protected Statement childrenInvoker(final RunNotifier notifier){
48 | return new Statement(){
49 |
50 | @Override
51 | public void evaluate() throws Throwable {
52 | // TODO Auto-generated method stub
53 | ThreadRunner.super.childrenInvoker(notifier).evaluate();
54 | while(numThreads.get() > 0){
55 | Thread.sleep(1000);
56 | }
57 | }
58 |
59 | };
60 | }
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | class Test implements Runnable{
69 | private final FrameworkMethod method;
70 | private final RunNotifier notifier;
71 |
72 | public Test(FrameworkMethod method, RunNotifier notifier){
73 | this.method = method;
74 | this.notifier = notifier;
75 | }
76 |
77 |
78 | public void run() {
79 | ThreadRunner.super.runChild(method, notifier);
80 | // TODO Auto-generated method stub
81 | numThreads.decrementAndGet();
82 |
83 | }
84 |
85 | }
86 |
87 | }
88 |
--------------------------------------------------------------------------------
/src/test/java/com/weibo/userpool/JdbcUtil.java:
--------------------------------------------------------------------------------
1 | package com.weibo.userpool;
2 |
3 | import java.beans.PropertyVetoException;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 | import java.sql.Connection;
7 | import java.sql.ResultSet;
8 | import java.sql.SQLException;
9 | import java.sql.Statement;
10 | import java.util.Properties;
11 |
12 | import org.apache.commons.dbutils.DbUtils;
13 |
14 | import com.mchange.v2.c3p0.ComboPooledDataSource;
15 |
16 | /**
17 | *
18 | *
19 | * jdbc 使用C3PO连接池 获得Connection
20 | * @author hugang
21 | *
22 | */
23 | public class JdbcUtil {
24 | private static Properties enc;
25 | private static InputStream in;
26 | private static ComboPooledDataSource ds = new ComboPooledDataSource();
27 | static {
28 | try {
29 | enc = new Properties();
30 | in = JdbcUtil.class.getResourceAsStream("../../../c3p0.properties");
31 | enc.load(in);
32 | } catch (Exception e) {
33 | throw new ExceptionInInitializerError(e);
34 | }
35 | finally {
36 | try {
37 | in.close();
38 | } catch (IOException e) {
39 | // TODO Auto-generated catch block
40 | e.printStackTrace();
41 | }
42 | }
43 | }
44 |
45 | static {
46 | try {
47 | ds.setDriverClass(enc.getProperty("c3p0.driverClass"));
48 | } catch (PropertyVetoException e) {
49 | // TODO Auto-generated catch block
50 | e.printStackTrace();
51 | }
52 | ds.setUser(enc.getProperty("c3p0.user"));
53 | ds.setPassword(enc.getProperty("c3p0.password"));
54 | ds.setJdbcUrl(enc.getProperty("c3p0.jdbcUrl"));
55 | }
56 |
57 | public static Connection getConnection() {
58 |
59 | try {
60 |
61 | return ds.getConnection();
62 |
63 | } catch (SQLException e) {
64 | // TODO Auto-generated catch block
65 | e.printStackTrace();
66 | }
67 | return null;
68 | }
69 |
70 | public static void close(ResultSet rs, Statement st, Connection con) {
71 | DbUtils.closeQuietly(rs);
72 | DbUtils.closeQuietly(st);
73 | DbUtils.closeQuietly(con);
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/src/test/java/global.properties:
--------------------------------------------------------------------------------
1 | # appkey
2 | source=
3 |
4 |
5 | # web server ip:port
6 | host=
7 | port=
8 |
9 | # run failed cases times(default value)
10 | retry=1
11 |
--------------------------------------------------------------------------------
/src/test/java/log4j.properties:
--------------------------------------------------------------------------------
1 | log4j.rootLogger=debug
2 |
3 | log4j.logger.error=error,errorfile
4 | log4j.logger.info=debug,infofile
5 | log4j.logger.testlog=info,file
6 | log4j.logger.caselog=debug,casefile
7 |
8 | log4j.appender.casefile=org.apache.log4j.DailyRollingFileAppender
9 | log4j.appender.casefile.DatePattern='.'yyyyMMdd-HH
10 | log4j.appender.casefile.File=./logs/execute.log
11 | log4j.appender.casefile.Append=true
12 | log4j.appender.casefile.layout=org.apache.log4j.PatternLayout
13 | log4j.appender.casefile.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%p] %m%n
14 |
15 | log4j.appender.infofile=org.apache.log4j.DailyRollingFileAppender
16 | log4j.appender.infofile.DatePattern='.'yyyyMMdd-HH
17 | log4j.appender.infofile.File=./logs/info.log
18 | log4j.appender.infofile.Append=true
19 | log4j.appender.infofile.Threshold=DEBUG
20 | log4j.appender.infofile.layout=org.apache.log4j.PatternLayout
21 | log4j.appender.infofile.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%p] %m%n
22 |
23 | log4j.appender.errorfile=org.apache.log4j.DailyRollingFileAppender
24 | log4j.appender.errorfile.DatePattern='.'yyyyMMdd-HH
25 | log4j.appender.errorfile.File=./logs/error.log
26 | log4j.appender.errorfile.Append=true
27 | log4j.appender.errorfile.Threshold=ERROR
28 | log4j.appender.errorfile.layout=org.apache.log4j.PatternLayout
29 | log4j.appender.errorfile.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%p] %m%n
30 |
31 | log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
32 | log4j.appender.file.DatePattern='.'yyyyMMdd-HH
33 | log4j.appender.file.File=./logs/test.log
34 | log4j.appender.file.Append=true
35 | log4j.appender.file.Threshold=DEBUG
36 | log4j.appender.file.layout=org.apache.log4j.PatternLayout
37 | log4j.appender.file.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%p] %m%n
38 |
39 |
40 |
--------------------------------------------------------------------------------
/target/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/.DS_Store
--------------------------------------------------------------------------------
/target/classes/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Build-Jdk: 1.7.0_60-ea
3 | Built-By: hugang
4 | Created-By: Maven Integration for Eclipse
5 |
6 |
--------------------------------------------------------------------------------
/target/classes/META-INF/maven/com.weibo/WeTest/pom.properties:
--------------------------------------------------------------------------------
1 | #Generated by Maven Integration for Eclipse
2 | #Tue Jul 19 08:54:43 CST 2016
3 | version=0.0.1
4 | groupId=com.weibo
5 | m2e.projectName=WeTest
6 | m2e.projectLocation=/Users/hugang/WeTest
7 | artifactId=WeTest
8 |
--------------------------------------------------------------------------------
/target/classes/META-INF/maven/com.weibo/WeTest/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | com.weibo
5 | WeTest
6 |
7 | 0.0.1
8 | WeTest Maven Webapp
9 | http://maven.apache.org
10 |
11 |
12 | junit
13 | junit
14 | 4.12
15 | test
16 |
17 |
18 | org.hamcrest
19 | hamcrest-core
20 | 1.3
21 |
22 |
23 | org.hamcrest
24 | hamcrest-all
25 | 1.3
26 |
27 |
28 | com.mchange
29 | c3p0
30 | 0.9.5
31 |
32 |
33 | org.hamcrest
34 | hamcrest-library
35 | 1.3
36 |
37 |
38 | mysql
39 | mysql-connector-java
40 | 5.1.34
41 |
42 |
43 | redis.clients
44 | jedis
45 | 2.7.2
46 | jar
47 | compile
48 |
49 |
50 |
51 |
52 |
53 |
54 | log4j
55 | log4j
56 | 1.2.14
57 |
58 |
59 | org.apache.httpcomponents
60 | httpclient
61 | 4.3.1
62 |
63 |
64 |
65 | org.apache.httpcomponents
66 | httpcore
67 | 4.3
68 |
69 |
70 | org.apache.httpcomponents
71 | httpmime
72 | 4.3.1
73 |
74 |
75 | org.apache.httpcomponents
76 | httpmime
77 | 4.3.1
78 |
79 |
80 | com.fasterxml.jackson.core
81 | jackson-core
82 | 2.2.3
83 |
84 |
85 | com.fasterxml.jackson.core
86 | jackson-annotations
87 | 2.2.3
88 |
89 |
90 | com.fasterxml.jackson.core
91 | jackson-databind
92 | 2.2.3
93 |
94 |
95 |
96 | org.json
97 | json
98 | 20090211
99 |
100 |
101 |
102 | net.sf.json-lib
103 | json-lib
104 | 2.4
105 | jdk15
106 |
107 |
108 |
109 | com.googlecode.json-simple
110 | json-simple
111 | 1.1.1
112 |
113 |
114 |
115 | ant
116 | ant
117 | 1.7.0
118 |
119 |
120 |
121 | org.apache.ant
122 | ant
123 | 1.9.4
124 |
125 |
126 |
127 | org.apache.ant
128 | ant-junit4
129 | 1.9.4
130 |
131 |
132 |
133 | ant-contrib
134 | ant-contrib
135 | 1.0b3
136 |
137 |
138 |
139 | commons-dbutils
140 | commons-dbutils
141 | 1.6
142 |
143 |
144 |
145 | io.takari.junit
146 | takari-cpsuite
147 | 1.2.7
148 |
149 |
150 |
151 | javax.servlet
152 | servlet-api
153 | 2.5
154 | provided
155 |
156 |
157 |
158 |
159 | commons-beanutils
160 | commons-beanutils
161 | 1.9.2
162 |
163 |
164 | commons-logging
165 | commons-logging
166 | 1.2
167 |
168 |
169 |
170 |
171 |
172 |
173 |
175 | org.apache.maven.plugins
176 | maven-surefire-plugin
177 | 2.19.1
178 |
179 |
180 | true
181 | true
182 |
183 |
184 |
185 | org.apache.maven.surefire
186 | surefire-junit47
187 | 2.19
188 |
189 |
190 |
191 |
192 |
194 |
195 |
196 | src/test/java
197 |
198 |
199 |
200 | WeTest
201 |
202 |
203 |
204 | 1.7
205 | 1.7
206 | UTF-8
207 | java
208 |
209 |
210 |
211 |
--------------------------------------------------------------------------------
/target/test-classes/c3p0.properties:
--------------------------------------------------------------------------------
1 | #
2 | # This file is detritus from various testing attempts
3 | # the values below may change, and often do not represent
4 | # reasonable values for the parameters.
5 | #
6 |
7 | c3p0.jdbcUrl=jdbc:mysql://ip:port/dbname?useUnicode=true&characterEncoding=utf-8
8 | c3p0.driverClass=com.mysql.jdbc.Driver
9 | c3p0.user=user
10 | c3p0.password=pwd
11 |
12 |
13 |
14 |
15 | c3p0.minPoolSize=500
16 | c3p0.maxPoolSize=1500
17 |
18 | #c3p0.maxStatements=0
19 | #c3p0.checkoutTimeout=18000
20 |
21 |
22 |
23 | #c3p0.numHelperThreads=6
24 |
25 | #c3p0.testConnectionOnCheckout=true
26 | #c3p0.testConnectionOnCheckin=true
27 |
28 | #c3p0.checkoutTimeout=2000
29 | #c3p0.idleConnectionTestPeriod=5
30 | #c3p0.maxConnectionAge=10
31 | #c3p0.maxIdleTime=2
32 | #c3p0.maxIdleTimeExcessConnections=1
33 | #c3p0.propertyCycle=1
34 | #c3p0.numHelperThreads=10
35 | #c3p0.unreturnedConnectionTimeout=15
36 | #c3p0.debugUnreturnedConnectionStackTraces=true
37 | #c3p0.maxStatements=30
38 | #c3p0.maxStatementsPerConnection=5
39 | #c3p0.maxAdministrativeTaskTime=3
40 | #c3p0.preferredTestQuery=SELECT 1
41 | #c3p0.preferredTestQuery=SELECT a FROM emptyyukyuk WHERE a = 5
42 | #c3p0.preferredTestQuery=SELECT a FROM testpbds WHERE a = 5
43 | #c3p0.usesTraditionalReflectiveProxies=true
44 | #c3p0.automaticTestTable=PoopyTestTable
45 | #c3p0.acquireIncrement=4
46 | #c3p0.acquireRetryDelay=1000
47 | #c3p0.acquireRetryAttempts=60
48 | #c3p0.connectionTesterClassName=com.mchange.v2.c3p0.test.AlwaysFailConnectionTester
49 | #c3p0.initialPoolSize=10
50 | com.mchange.v2.log.MLog=com.mchange.v2.log.log4j.Log4jMLog
51 | #com.mchange.v2.log.MLog=com.mchange.v2.log.jdk14logging.Jdk14MLog
52 | #com.mchange.v2.log.MLog=com.mchange.v2.log.FallbackMLog
53 | com.mchange.v2.log.NameTransformer=com.mchange.v2.log.PackageNames
54 | com.mchange.v2.log.FallbackMLog.DEFAULT_CUTOFF_LEVEL=ALL
55 |
56 | #com.mchange.v2.c3p0.VMID=poop
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/cases/example/ExampleTest.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/cases/example/ExampleTest.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/cases/example/ExampleTest.java:
--------------------------------------------------------------------------------
1 | package com.weibo.cases.example;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import org.junit.Test;
6 | import static org.hamcrest.Matchers.is;
7 |
8 | public class ExampleTest {
9 |
10 | @Test
11 | public void testExampleOne() {
12 | try {
13 | // 构造场景
14 | assertThat("abc", is("abc"));
15 |
16 | } catch (Exception e) {
17 | e.printStackTrace();
18 | fail("testExampleOne excepiton");
19 | } finally {
20 | // 清数据
21 | }
22 | }
23 |
24 | @Test
25 | public void testExampleTwo() {
26 | try {
27 |
28 | assertThat("abc", is("def"));
29 |
30 | } catch (Exception e) {
31 | e.printStackTrace();
32 | fail("testExampleTwo excepiton");
33 | } finally {
34 |
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/cases/suite/ExampleTestSuite.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/cases/suite/ExampleTestSuite.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/cases/suite/ExampleTestSuite.java:
--------------------------------------------------------------------------------
1 | package com.weibo.cases.suite;
2 |
3 |
4 | import org.junit.experimental.categories.Categories;
5 | import org.junit.runner.RunWith;
6 | import org.junit.runners.Suite.SuiteClasses;
7 |
8 | @RunWith(Categories.class)
9 | @SuiteClasses( IntegrationExampleModuleTests.class )
10 | public class ExampleTestSuite {
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/cases/suite/IntegrationExampleModuleTests.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/cases/suite/IntegrationExampleModuleTests.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/cases/suite/IntegrationExampleModuleTests.java:
--------------------------------------------------------------------------------
1 | package com.weibo.cases.suite;
2 | import org.junit.extensions.cpsuite.ClasspathSuite.ClassnameFilters;
3 | import org.junit.runner.RunWith;
4 |
5 | import com.weibo.runner.Concurrent;
6 | import com.weibo.runner.ConcurrentSuite;
7 |
8 | @RunWith(ConcurrentSuite.class)
9 | @ClassnameFilters({"com.weibo.cases.example.*Test"})
10 | @Concurrent
11 | public interface IntegrationExampleModuleTests {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/common/StatusCommon.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/common/StatusCommon.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/common/StatusCommon.java:
--------------------------------------------------------------------------------
1 | package com.weibo.common;
2 |
3 | import java.util.List;
4 |
5 | import org.junit.Ignore;
6 |
7 | import net.sf.json.JSONArray;
8 | import net.sf.json.JSONObject;
9 |
10 | import com.weibo.global.HttpClientBase;
11 | import com.weibo.global.JsonCommon;
12 | import com.weibo.model.Status;
13 |
14 |
15 | public class StatusCommon {
16 | Object status;
17 | Object statusCount;
18 | Object statuses;
19 | Object interest;
20 | Object lastTime;
21 | Object statusesIds;
22 | Object error;
23 | Object exposure;
24 | Object allowComment;
25 | Object userReadCount;
26 | Object darwinTags;
27 | HttpClientBase statusTest = new HttpClientBase();
28 | String relativeurl;
29 | String statusInfo;
30 | Object objectList;
31 | Object midObject;
32 | Object StatusBean;
33 | Object recomm;
34 | Object getExposureTrigger;
35 | Object getSimilarity;
36 | Object atTimeline;
37 | Object readMetas;
38 | Object phototags;
39 | boolean flag;
40 |
41 |
42 |
43 | public Object commonResult(String statusInfo) throws Exception {
44 | // if (statusInfo.contains("error_code")) {
45 | // error = (ErrorInfo) JsonCommon.getJavabean(statusInfo,
46 | // ErrorInfo.class);
47 | // MbLogger.error(statusInfo, new ExceptionCommon(statusInfo));
48 | // return error;
49 | // } else {
50 | status = (Status) JsonCommon.getJavabean(statusInfo, Status.class);
51 | return status;
52 | // }
53 | }
54 |
55 |
56 |
57 | /*
58 | * status feed (statuses/friends_timeline)
59 | *
60 | * @param username
61 | *
62 | * @param password
63 | *
64 | * @param parameters required
65 | *
66 | * @return
67 | *
68 | * @throws Exception
69 | */
70 | public Object friendsTimeline_status(String username, String password,
71 | String parameters) throws Exception {
72 | relativeurl = "/2/statuses/friends_timeline.json";
73 | statusInfo = statusTest.doGet(username, password, relativeurl, parameters);
74 | statuses = commonResult(statusInfo);
75 | return statuses;
76 | }
77 |
78 |
79 | public Object updateStatusPublic(String username, String password,
80 | String parameters) throws Exception {
81 | relativeurl = "/2/statuses/update.json";
82 | if (parameters.isEmpty()) {
83 | parameters = "visible=0&status=test public ";
84 | }
85 | statusInfo = statusTest.doPost(username, password, relativeurl,
86 | parameters);
87 | status = commonResult(statusInfo);
88 |
89 | return status;
90 | }
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/global/Constant.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/global/Constant.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/global/Constant.java:
--------------------------------------------------------------------------------
1 | package com.weibo.global;
2 |
3 | public class Constant {
4 | public static final int FREESTATE = 0;//闲置用户帐号
5 | public static final int BUSYSTATE = 1;//占用用户帐号
6 | }
7 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/global/HttpClientBase.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/global/HttpClientBase.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/global/JsonCommon.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/global/JsonCommon.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/global/JsonCommon.java:
--------------------------------------------------------------------------------
1 | package com.weibo.global;
2 |
3 |
4 | import java.io.IOException;
5 | import java.util.Map;
6 |
7 | import com.fasterxml.jackson.annotation.JsonIgnore;
8 | import com.fasterxml.jackson.core.JsonParseException;
9 | import com.fasterxml.jackson.core.JsonParser.Feature;
10 | import com.fasterxml.jackson.databind.DeserializationFeature;
11 | import com.fasterxml.jackson.databind.JsonMappingException;
12 | import com.fasterxml.jackson.databind.ObjectMapper;
13 |
14 |
15 | //import com.alibaba.fastjson.JSON;
16 |
17 | public class JsonCommon {
18 | // jackSon 反序列化 java对象
19 | public static Object getJavabean(String jsonString, Class classes)
20 | throws JsonParseException, JsonMappingException, IOException {
21 | if (jsonString == null || jsonString.equals("") || classes == null)
22 | return null;
23 | ObjectMapper mapper = new ObjectMapper();
24 | mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
25 | false);
26 | mapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
27 | // System.out.println("---------------------------"+classes.getName());
28 | Object myObject = mapper.readValue(jsonString, classes);
29 | return myObject;
30 | }
31 |
32 | /** @author yanlei3
33 | * write for the JSONobject with unset key
34 | */
35 | public static Map getMap(String jsonString)
36 | throws JsonParseException, JsonMappingException, IOException {
37 | if (jsonString == null || jsonString.equals(""))
38 | return null;
39 | ObjectMapper mapper = new ObjectMapper();
40 | mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
41 | false);
42 | mapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
43 | // System.out.println("---------------------------"+classes.getName());
44 | Map myMap = mapper.readValue(jsonString, Map.class);
45 | return myMap;
46 | }
47 |
48 | @JsonIgnore
49 | public static Object[] getJavabeans(String jsonString, Class classes)
50 | throws JsonParseException, JsonMappingException, IOException {
51 | if (jsonString == null || jsonString.equals("") || classes == null)
52 | return null;
53 | ObjectMapper mapper = new ObjectMapper();
54 | mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
55 | false);
56 | mapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
57 | Object[] myObject = (Object[]) mapper.readValue(jsonString, classes);
58 | return myObject;
59 | }
60 |
61 | ////使用fastjson 反序列为java 对象
62 | // @SuppressWarnings("unchecked")
63 | // public static Object getJavabean(String jsonString, @SuppressWarnings("rawtypes") Class classes) {
64 | // if (jsonString == null || jsonString.equals("") || classes == null)
65 | // return null;
66 | //// ObjectMapper mapper = new ObjectMapper();
67 | //// mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
68 | //// false);
69 | //// mapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
70 | //// // System.out.println("---------------------------"+classes.getName());
71 | //// Object myObject = mapper.readValue(jsonString, classes);
72 | //// return myObject;
73 | // Object myObject = JSON.parseObject(jsonString, classes);
74 | // return myObject;
75 | // }
76 | //
77 | // @SuppressWarnings("unchecked")
78 | // @JsonIgnore
79 | // public static Object[] getJavabeans(String jsonString, @SuppressWarnings("rawtypes") Class classes) {
80 | // if (jsonString == null || jsonString.equals("") || classes == null)
81 | // return null;
82 | //// ObjectMapper mapper = new ObjectMapper();
83 | //// mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
84 | //// false);
85 | //// mapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
86 | // Object[] myObject = (Object[]) JSON.parseObject(jsonString, classes);
87 | // return myObject;
88 | // }
89 |
90 |
91 | public static String writeEntity2Json(Object object) throws IOException {
92 | String jsonResult = null;
93 | ObjectMapper objectMapper = new ObjectMapper();
94 | jsonResult = objectMapper.writeValueAsString(object);
95 | return jsonResult;
96 | }
97 |
98 | }
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/global/LogFormatter.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/global/LogFormatter.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/global/LogFormatter.java:
--------------------------------------------------------------------------------
1 | package com.weibo.global;
2 |
3 | //import java.util.Date;
4 | import java.util.logging.Formatter;
5 | import java.util.logging.LogRecord;
6 |
7 | public class LogFormatter extends Formatter {
8 | @Override
9 | public String format(LogRecord record) {
10 | // Date date = new Date();
11 | // String sDate = date.toString();
12 | // return "[" + sDate + "]" + "[" + record.getLevel() + "]"
13 | // + record.getClass() + record.getMessage() + "\n";
14 | return "[" + record.getMessage() + "]" + "\n";
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/global/ParseProperties.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/global/ParseProperties.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/global/ParseProperties.java:
--------------------------------------------------------------------------------
1 | package com.weibo.global;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.util.Properties;
6 |
7 | public class ParseProperties {
8 |
9 | private static final String SYSTEMPROPERTY = "../../../global.properties";
10 | private static String HOST = null;
11 | private static String PORT = null;
12 | private static String SOURCE = null;
13 | // add retry
14 | private static String RETRY = null;
15 |
16 | private static Properties enc= null;
17 | private static InputStream ins = null;
18 | static {
19 | try {
20 | enc = new Properties();
21 | ins = ParseProperties.class
22 | .getResourceAsStream(SYSTEMPROPERTY);
23 | enc.load(ins);
24 | HOST = enc.getProperty("host");
25 | SOURCE = enc.getProperty("source");
26 | PORT = enc.getProperty("port");
27 | RETRY = enc.getProperty("retry");
28 |
29 | } catch (Exception e) {
30 | throw new ExceptionInInitializerError(e);
31 |
32 | }finally
33 | {
34 | try {
35 | ins.close();
36 | } catch (IOException e) {
37 | // TODO Auto-generated catch block
38 | e.printStackTrace();
39 | }
40 | }
41 |
42 | }
43 |
44 | /**
45 | * 根据属性文件和key得到属性的value
46 | *
47 | * @param fileRelativePath
48 | * @param propertyName
49 | * @return
50 | * @throws Exception
51 | */
52 | public static String getProperty(String fileRelativePath,
53 | String propertyName) throws Exception {
54 | if (fileRelativePath == null || fileRelativePath.equals("")
55 | || propertyName == null || propertyName.equals(""))
56 | throw new Exception("传入参数为空!");
57 | InputStream ins = ParseProperties.class
58 | .getResourceAsStream(fileRelativePath);
59 | if (ins == null)
60 | throw new Exception("系统配置文件global.peroperties文件不存在!");
61 | Properties p = new Properties();
62 | String value = "";
63 | try {
64 | p.load(ins);
65 | value = p.getProperty(propertyName);
66 | } catch (Exception ex) {
67 | throw new Exception("读取属性文件异常");
68 | } finally {
69 | ins.close();
70 | }
71 | return value;
72 |
73 | }
74 |
75 | /**
76 | * 根据key得到系统属性的value
77 | *
78 | * @param propertyName
79 | * @throws Exception
80 | */
81 | public static String getSystemProperty(String propertyName)
82 | throws Exception {
83 | if (propertyName == null || propertyName.equals(""))
84 | throw new Exception("传入参数为空!");
85 | if(propertyName.equals("port"))
86 | return PORT;
87 | else if(propertyName.equals("host"))
88 | return HOST;
89 | else if(propertyName.equals("source"))
90 | return SOURCE;
91 | else if(propertyName.equals("retry"))
92 | return RETRY;
93 | return null;
94 | }
95 |
96 | public static void main(String args[]) {
97 | try {
98 | System.out.println("host======"+getSystemProperty("host"));
99 | System.out.println("port======"+getSystemProperty("port"));
100 | System.out.println("source===="+getSystemProperty("source"));
101 | System.out.println("retry====" + getSystemProperty("retry"));
102 | } catch (Exception e) {
103 | e.printStackTrace();
104 | }
105 | }
106 | }
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/global/TestLog.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/global/TestLog.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/global/TestLog.java:
--------------------------------------------------------------------------------
1 | package com.weibo.global;
2 |
3 | import java.io.IOException;
4 | import java.util.Date;
5 | import java.util.logging.FileHandler;
6 | import java.util.logging.Formatter;
7 | import java.util.logging.Level;
8 | import java.util.logging.LogRecord;
9 | import java.util.logging.Logger;
10 |
11 |
12 | //import org.apache.log4j.Logger;
13 | //import org.apache.log4j.PropertyConfigurator;
14 |
15 | /*
16 | * 记录 测试步骤
17 | * @author hugang
18 | */
19 |
20 | public class TestLog {
21 |
22 | public final static String PATH = "./logs/caseinfo.log";
23 | public final static Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
24 |
25 |
26 | public static void Comment(String comment) {
27 | try {
28 | LOGGER.setLevel(Level.ALL);
29 | FileHandler fileHandler;
30 | fileHandler = new FileHandler(PATH);
31 | fileHandler.setLevel(Level.ALL);
32 | fileHandler.setFormatter(new LogFormatter());
33 | LOGGER.addHandler(fileHandler);
34 | LOGGER.info(comment);
35 | } catch (SecurityException e) {
36 | // TODO Auto-generated catch block
37 | e.printStackTrace();
38 | } catch (IOException e) {
39 | // TODO Auto-generated catch block
40 | e.printStackTrace();
41 | }
42 |
43 | }
44 | }
45 |
46 |
47 | //public class TestLog {
48 | //
49 | //
50 | // public final static Logger LOGGER = Logger.getLogger(TestLog.class);
51 | // public final static String LOG4JPATH = ".../../../log4j.properties";
52 | //
53 | // public static void Comment(String comment) {
54 | // try {
55 | // PropertyConfigurator.configure(LOG4JPATH);
56 | // LOGGER.info(comment);
57 | // } catch (SecurityException e) {
58 | // // TODO Auto-generated catch block
59 | // e.printStackTrace();
60 | // }
61 | //
62 | // }
63 | //}
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/model/Account.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/model/Account.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/model/Account.java:
--------------------------------------------------------------------------------
1 | package com.weibo.model;
2 |
3 | public class Account {
4 | private long uid;
5 | private String screen_name;
6 | private String email;
7 | private int id;
8 | private String password;
9 | private int state;
10 | private String groupID;
11 | public long getUid() {
12 | return uid;
13 | }
14 | public void setUid(long uid) {
15 | this.uid = uid;
16 | }
17 | public String getScreen_name() {
18 | return screen_name;
19 | }
20 | public void setScreen_name(String screen_name) {
21 | this.screen_name = screen_name;
22 | }
23 | public String getEmail() {
24 | return email;
25 | }
26 | public void setEmail(String email) {
27 | this.email = email;
28 | }
29 | public int getId() {
30 | return id;
31 | }
32 | public void setId(int id) {
33 | this.id = id;
34 | }
35 | public String getPassword() {
36 | return password;
37 | }
38 | public void setPassword(String password) {
39 | this.password = password;
40 | }
41 | public int getState() {
42 | return state;
43 | }
44 | public void setState(int state) {
45 | this.state = state;
46 | }
47 | public String getGroupID() {
48 | return groupID;
49 | }
50 | public void setGroupID(String groupID) {
51 | this.groupID = groupID;
52 | }
53 |
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/model/Status.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/model/Status.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/model/Status.java:
--------------------------------------------------------------------------------
1 | package com.weibo.model;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
7 |
8 | @JsonIgnoreProperties(value = { "geo" })
9 | public class Status {
10 | private String created_at;
11 |
12 | private long id;
13 | private long mid;
14 | private String idstr;
15 | private List pic_ids = new ArrayList();
16 |
17 | public List getPic_ids() {
18 | return pic_ids;
19 | }
20 |
21 | public void setPic_ids(List pic_ids) {
22 | this.pic_ids = pic_ids;
23 | }
24 |
25 | int position;
26 | String mark;
27 |
28 | public int getPosition() {
29 | return position;
30 | }
31 |
32 | public void setPosition(int position) {
33 | this.position = position;
34 | }
35 |
36 | public String getMark() {
37 | return mark;
38 | }
39 |
40 | public void setMark(String mark) {
41 | this.mark = mark;
42 | }
43 |
44 | private String result;
45 | private int reposts_count;
46 | private int comments_count;
47 | private int attitudes_count;
48 | private int read_count;
49 | private int mlevel;
50 |
51 | private String cover_image;
52 | private int state;
53 | private String deleted;
54 |
55 | private boolean liked;
56 | private boolean truncated;
57 |
58 | private String rid;
59 | private int mblogtype;
60 | private String ctrlType;
61 | private List cmt_picids = new ArrayList();
62 | private long uid;
63 |
64 | long expire_time;
65 |
66 | private int source_type;
67 | private int source_allowclick;
68 | private long original_mblog_read_count;
69 | private long original_article_read_count;
70 | private long original_status_count;
71 | private long original_article_count;
72 | private String type;
73 | private String text;
74 | private String pid;
75 | private String source;
76 |
77 | private boolean favorited;
78 |
79 | private String in_reply_to_status_id;
80 |
81 | private String in_reply_to_user_id;
82 |
83 | private String in_reply_to_screen_name;
84 |
85 | private String thumbnail_pic;
86 |
87 | private String bmiddle_pic;
88 |
89 | private String original_pic;
90 |
91 | private Status retweeted_status;
92 |
93 | public long getExpire_time() {
94 | return expire_time;
95 | }
96 |
97 | public void setExpire_time(long expire_time) {
98 | this.expire_time = expire_time;
99 | }
100 |
101 | public int getSource_type() {
102 | return source_type;
103 | }
104 |
105 | public void setSource_type(int source_type) {
106 | this.source_type = source_type;
107 | }
108 |
109 | public long getOriginal_mblog_read_count() {
110 | return original_mblog_read_count;
111 | }
112 |
113 | public void setOriginal_mblog_read_count(long original_mblog_read_count) {
114 | this.original_mblog_read_count = original_mblog_read_count;
115 | }
116 |
117 | public long getOriginal_article_read_count() {
118 | return original_article_read_count;
119 | }
120 |
121 | public void setOriginal_article_read_count(long original_article_read_count) {
122 | this.original_article_read_count = original_article_read_count;
123 | }
124 |
125 | public long getOriginal_status_count() {
126 | return original_status_count;
127 | }
128 |
129 | public void setOriginal_status_count(long original_status_count) {
130 | this.original_status_count = original_status_count;
131 | }
132 |
133 | public long getOriginal_article_count() {
134 | return original_article_count;
135 | }
136 |
137 | public void setOriginal_article_count(long original_article_count) {
138 | this.original_article_count = original_article_count;
139 | }
140 |
141 | public int getState() {
142 | return state;
143 | }
144 |
145 | public void setState(int state) {
146 | this.state = state;
147 | }
148 |
149 | public String getCover_image() {
150 | return cover_image;
151 | }
152 |
153 | public void setCover_image(String cover_image) {
154 | this.cover_image = cover_image;
155 | }
156 |
157 | public int getReposts_count() {
158 | return reposts_count;
159 | }
160 |
161 | public void setReposts_count(int reposts_count) {
162 | this.reposts_count = reposts_count;
163 | }
164 |
165 | public int getComments_count() {
166 | return comments_count;
167 | }
168 |
169 | public void setComments_count(int comments_count) {
170 | this.comments_count = comments_count;
171 | }
172 |
173 | public int getAttitudes_count() {
174 | return attitudes_count;
175 | }
176 |
177 | public void setAttitudes_count(int attitudes_count) {
178 | this.attitudes_count = attitudes_count;
179 | }
180 |
181 | public int getMlevel() {
182 | return mlevel;
183 | }
184 |
185 | public void setMlevel(int mlevel) {
186 | this.mlevel = mlevel;
187 | }
188 |
189 | public String getIdstr() {
190 | return idstr;
191 | }
192 |
193 | public void setIdstr(String idstr) {
194 | this.idstr = idstr;
195 | }
196 |
197 | public long getMid() {
198 | return mid;
199 | }
200 |
201 | public void setMid(long mid) {
202 | this.mid = mid;
203 | }
204 |
205 | public String getPid() {
206 | return pid;
207 | }
208 |
209 | public void setPid(String pid) {
210 | this.pid = pid;
211 | }
212 |
213 | public String getBmiddle_pic() {
214 | return bmiddle_pic;
215 | }
216 |
217 | public void setBmiddle_pic(String bmiddle_pic) {
218 | this.bmiddle_pic = bmiddle_pic;
219 | }
220 |
221 | public String getCreated_at() {
222 | return created_at;
223 | }
224 |
225 | public void setCreated_at(String created_at) {
226 | this.created_at = created_at;
227 | }
228 |
229 | public boolean isFavorited() {
230 | return favorited;
231 | }
232 |
233 | public void setFavorited(boolean favorited) {
234 | this.favorited = favorited;
235 | }
236 |
237 | public long getId() {
238 | return id;
239 | }
240 |
241 | public void setId(long id) {
242 | this.id = id;
243 | }
244 |
245 | public String getIn_reply_to_screen_name() {
246 | return in_reply_to_screen_name;
247 | }
248 |
249 | public void setIn_reply_to_screen_name(String in_reply_to_screen_name) {
250 | this.in_reply_to_screen_name = in_reply_to_screen_name;
251 | }
252 |
253 | public String getIn_reply_to_status_id() {
254 | return in_reply_to_status_id;
255 | }
256 |
257 | public void setIn_reply_to_status_id(String in_reply_to_status_id) {
258 | this.in_reply_to_status_id = in_reply_to_status_id;
259 | }
260 |
261 | public String getIn_reply_to_user_id() {
262 | return in_reply_to_user_id;
263 | }
264 |
265 | public void setIn_reply_to_user_id(String in_reply_to_user_id) {
266 | this.in_reply_to_user_id = in_reply_to_user_id;
267 | }
268 |
269 | public String getOriginal_pic() {
270 | return original_pic;
271 | }
272 |
273 | public void setOriginal_pic(String original_pic) {
274 | this.original_pic = original_pic;
275 | }
276 |
277 | public Status getRetweeted_status() {
278 | return retweeted_status;
279 | }
280 |
281 | public void setRetweeted_status(Status retweeted_status) {
282 | this.retweeted_status = retweeted_status;
283 | }
284 |
285 | public String getSource() {
286 | return source;
287 | }
288 |
289 | public void setSource(String source) {
290 | this.source = source;
291 | }
292 |
293 | public String getText() {
294 | return text;
295 | }
296 |
297 | public void setText(String text) {
298 | this.text = text;
299 | }
300 |
301 | public String getThumbnail_pic() {
302 | return thumbnail_pic;
303 | }
304 |
305 | public void setThumbnail_pic(String thumbnail_pic) {
306 | this.thumbnail_pic = thumbnail_pic;
307 | }
308 |
309 | public boolean isTruncated() {
310 | return truncated;
311 | }
312 |
313 | public void setTruncated(boolean truncated) {
314 | this.truncated = truncated;
315 | }
316 |
317 | public boolean isLiked() {
318 | return liked;
319 | }
320 |
321 | public void setLiked(boolean liked) {
322 | this.liked = liked;
323 | }
324 |
325 | public String getRid() {
326 | return rid;
327 | }
328 |
329 | public void setRid(String rid) {
330 | this.rid = rid;
331 | }
332 |
333 | public int getMblogtype() {
334 | return mblogtype;
335 | }
336 |
337 | public void setMblogtype(int mblogtype) {
338 | this.mblogtype = mblogtype;
339 | }
340 |
341 | public String getCtrlType() {
342 | return ctrlType;
343 | }
344 |
345 | public void setCtrlType(String ctrlType) {
346 | this.ctrlType = ctrlType;
347 | }
348 |
349 | public List getCmt_picids() {
350 | return cmt_picids;
351 | }
352 |
353 | public void setCmt_picids(List cmt_picids) {
354 | this.cmt_picids = cmt_picids;
355 | }
356 |
357 | public long getUid() {
358 | return uid;
359 | }
360 |
361 | public void setUid(long uid) {
362 | this.uid = uid;
363 | }
364 |
365 | public String getDeleted() {
366 | return deleted;
367 | }
368 |
369 | public void setDeleted(String deleted) {
370 | this.deleted = deleted;
371 | }
372 |
373 | public int getSource_allowclick() {
374 | return source_allowclick;
375 | }
376 |
377 | public void setSource_allowclick(int source_allowclick) {
378 | this.source_allowclick = source_allowclick;
379 | }
380 |
381 | public String getResult() {
382 | return result;
383 | }
384 |
385 | public void setResult(String result) {
386 | this.result = result;
387 | }
388 |
389 |
390 |
391 |
392 |
393 | public int getRead_count() {
394 | return read_count;
395 | }
396 |
397 | public void setRead_count(int read_count) {
398 | this.read_count = read_count;
399 | }
400 |
401 | public String getType() {
402 | return type;
403 | }
404 |
405 | public void setType(String type) {
406 | this.type = type;
407 | }
408 |
409 | }
410 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/ClassThreadRunTest.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runfail/ClassThreadRunTest.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/ClassThreadRunTest.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runfail;
2 |
3 | /**
4 | * @hugang
5 | */
6 | import java.util.ArrayList;
7 | import java.util.Collections;
8 | import java.util.List;
9 | import java.util.Map;
10 | import java.util.concurrent.Callable;
11 |
12 | import org.junit.runner.JUnitCore;
13 | import org.junit.runner.Request;
14 | import org.junit.runner.Result;
15 |
16 |
17 |
18 | // 类并发执行,方法级别串行
19 | public class ClassThreadRunTest implements Callable> {
20 |
21 |
22 | Class> testClass;
23 | List failMethod;
24 |
25 | // 类的方法集 结果,线程安全的List
26 | List singClassResult = Collections.synchronizedList(new ArrayList());
27 |
28 | public ClassThreadRunTest(Class> testClass, List failMethod){
29 | this.testClass = testClass;
30 | this.failMethod = failMethod;
31 | }
32 |
33 | // 线程执行体
34 | public List call() {
35 | // TODO Auto-generated method stub
36 | // 一个类下顺序执行方法
37 | for(int i = 0; i < failMethod.size(); i++){
38 | JUnitCore junitRunner = new JUnitCore();
39 | Request request = Request.method(testClass, failMethod.get(i));
40 | Result result = junitRunner.run(request);
41 | singClassResult.add(result);
42 | }
43 | return singClassResult;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/ExecuteCases.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runfail/ExecuteCases.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/ExecuteCases.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runfail;
2 |
3 | import java.io.File;
4 | import java.io.FileOutputStream;
5 | import java.io.IOException;
6 | import java.text.SimpleDateFormat;
7 | import java.util.ArrayList;
8 | import java.util.Date;
9 | import java.util.List;
10 | import java.util.Map;
11 | import java.util.concurrent.ExecutionException;
12 | import java.util.concurrent.ExecutorService;
13 | import java.util.concurrent.Executors;
14 | import java.util.concurrent.Future;
15 | import java.util.regex.Matcher;
16 | import java.util.regex.Pattern;
17 |
18 | import org.junit.runner.JUnitCore;
19 | import org.junit.runner.Request;
20 | import org.junit.runner.Result;
21 |
22 |
23 | /*
24 | * @author hugang
25 | */
26 | public class ExecuteCases {
27 | // 线程池大小
28 | final static int THREADCOUNT = 50;
29 |
30 | public void writeResult(String resultPath, List methodsResult,
31 | int failNum, int successNum, int casesNum, long runTime,
32 | String logPath, String logType) throws IOException {
33 | String filePath = resultPath;
34 | File file = new File(filePath);
35 | if (file.exists()) {
36 | file.delete();
37 | }
38 | if (!file.exists()) {
39 | file.createNewFile();
40 | }
41 | FileOutputStream fop = new FileOutputStream(file);
42 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss,SSS");
43 | fop.write("(一).Time's Result generated on: ".getBytes());
44 | fop.write(sdf.format(new Date()).getBytes());
45 | fop.write("\n".getBytes());
46 |
47 | StringBuffer sb = new StringBuffer();
48 | sb.append("(二).日志类型:" + logType);
49 | sb.append("\n");
50 | sb.append("(三).日志名:" + logPath);
51 | sb.append("\n");
52 | sb.append("===================== 结果集 =====================");
53 | sb.append("\n");
54 | sb.append("用例总数:" + casesNum);
55 | sb.append(", 成功数:" + successNum);
56 | sb.append(", 失败数:" + failNum);
57 | sb.append(", 运行时间:" + (runTime / 1000) / 60 + " 分钟 " + (runTime / 1000)
58 | % 60 + " 秒");
59 | sb.append("\n");
60 | sb.append("=================================================");
61 | sb.append("\n");
62 | sb.append("\n");
63 | fop.write(sb.toString().getBytes());
64 | for (int j = 0; j < methodsResult.size(); j++) {
65 | // 将JUnitCore失败信息中的换行符去掉, harmcrest中断言是多行显示
66 | String LineFailStr = methodsResult.get(j).getFailures().toString().replaceAll("\n", "");
67 | fop.write(LineFailStr.getBytes());
68 | fop.write("\n".getBytes());
69 | fop.write("\n".getBytes());
70 | }
71 | // 输出结果mvn格式, 便于前端展示
72 | // Tests run: 5, Failures: 2, Errors: 0, Skipped: 0
73 | System.out.println("Tests run: " + casesNum + ", Failures: " + failNum + ", Errors: 0, Skipped: 0");
74 | fop.flush();
75 | fop.close();
76 | }
77 |
78 |
79 | // 方法级别并发执行
80 | public void executorMethodCases(Map, List> failcasesMap,
81 | String logPath, String resultPath, String logType)
82 | throws ExecutionException, IOException {
83 | // 失败cases, key:Class, value:List of methods
84 | Map, List> runcaseMap;
85 | runcaseMap = failcasesMap;
86 |
87 | int failNum = 0;
88 | int successNum = 0;
89 | int casesNum = 0;
90 | long runTime = 0L;
91 | List methodsResult = new ArrayList();
92 |
93 | // 线程池
94 | ExecutorService executorService = Executors
95 | .newFixedThreadPool(THREADCOUNT);
96 | // 存运行结果
97 | List> listFr = new ArrayList>();
98 | long startTime = System.currentTimeMillis();
99 | // 多线程执行用例
100 | for (Map.Entry, List> entry : runcaseMap.entrySet()) {
101 | Class> testClass = entry.getKey();
102 | List failMethod = entry.getValue();
103 | casesNum += failMethod.size();
104 | for (int i = 0; i < failMethod.size(); i++) {
105 | Future fr = executorService.submit(new ThreadRunTest(
106 | testClass, failMethod.get(i)));
107 | listFr.add(fr);
108 | }
109 | }
110 | // 记录结果
111 | for (Future fr : listFr) {
112 | try {
113 | while (!fr.isDone())
114 | ;
115 | Result result = fr.get();
116 | if (result.wasSuccessful()) {
117 | successNum++;
118 | } else {
119 | failNum++;
120 | methodsResult.add(result);
121 | }
122 | } catch (InterruptedException e) {
123 | e.printStackTrace();
124 | } finally {
125 | executorService.shutdown();
126 | }
127 | }
128 | long endTime = System.currentTimeMillis();
129 | runTime = endTime - startTime;
130 | // 写结果日志
131 | writeResult(resultPath, methodsResult, failNum, successNum, casesNum,
132 | runTime, logPath, logType);
133 |
134 | // 回写日志, 根据logType回写不同格式的运行失败用例回日志文件, 简单工厂模式
135 | WriteLogFactory wlf = new WriteLogFactory();
136 | wlf.writeLog(logPath, logType, resultPath);
137 | }
138 |
139 | // 类级别并发执行
140 | public void executorClassCases(Map, List> failcasesMap,
141 | String logPath, String resultPath, String logType)
142 | throws ExecutionException, IOException {
143 | // 失败cases, key:Class, value:List of methods
144 | Map, List> runcaseMap;
145 | runcaseMap = failcasesMap;
146 |
147 | int failNum = 0;
148 | int successNum = 0;
149 | int casesNum = 0;
150 | long runTime = 0L;
151 | List methodsResult = new ArrayList();
152 |
153 | // 线程池
154 | // ExecutorService executorService = Executors
155 | // .newFixedThreadPool(THREADCOUNT);
156 | ExecutorService executorService = Executors.newCachedThreadPool();
157 | // 存运行结果
158 | List>> listFr = new ArrayList>>();
159 | long startTime = System.currentTimeMillis();
160 | // 多线程执行用例
161 | for (Map.Entry, List> entry : runcaseMap.entrySet()) {
162 | Class> testClass = entry.getKey();
163 | List failMethod = entry.getValue();
164 | casesNum += failMethod.size();
165 | Future> fr = executorService
166 | .submit(new ClassThreadRunTest(testClass, failMethod));
167 | listFr.add(fr);
168 | }
169 | // 记录结果
170 | for (Future> fr : listFr) {
171 | try {
172 | while (!fr.isDone())
173 | ;
174 | // 单个类的结果
175 | List listResult = fr.get();
176 | for (int i = 0; i < listResult.size(); i++) {
177 | if (listResult.get(i).wasSuccessful()) {
178 | successNum++;
179 | } else {
180 | failNum++;
181 | methodsResult.add(listResult.get(i));
182 | }
183 | }
184 |
185 | } catch (InterruptedException e) {
186 | e.printStackTrace();
187 | } finally {
188 | executorService.shutdown();
189 | }
190 | }
191 | long endTime = System.currentTimeMillis();
192 | runTime = endTime - startTime;
193 | // 写结果日志
194 | writeResult(resultPath, methodsResult, failNum, successNum, casesNum,
195 | runTime, logPath, logType);
196 |
197 | // 回写日志, 根据logType回写不同格式的运行失败用例回日志文件, 简单工厂模式
198 | WriteLogFactory wlf = new WriteLogFactory();
199 | wlf.writeLog(logPath, logType, resultPath);
200 |
201 | }
202 |
203 | // 串行执行
204 | public void SerialExecutorCases(Map, List> failcasesMap,
205 | String logPath, String resultPath, String logType)
206 | throws ExecutionException, IOException {
207 | // 失败cases, key:Class, value:List of methods
208 | Map, List> runcaseMap;
209 | runcaseMap = failcasesMap;
210 |
211 | int failNum = 0;
212 | int successNum = 0;
213 | int casesNum = 0;
214 | long runTime = 0L;
215 |
216 | // 记录失败用例
217 | List methodsResult = new ArrayList();
218 |
219 | // 存运行结果
220 | List listFr = new ArrayList();
221 | long startTime = System.currentTimeMillis();
222 |
223 | // 遍历执行用例
224 | for (Map.Entry, List> entry : runcaseMap.entrySet()) {
225 | Class> testClass = entry.getKey();
226 | List failMethod = entry.getValue();
227 | casesNum += failMethod.size();
228 | for (int i = 0; i < failMethod.size(); i++) {
229 | JUnitCore junitRunner = new JUnitCore();
230 | Request request = Request.method(testClass, failMethod.get(i));
231 | Result result = junitRunner.run(request);
232 | listFr.add(result);
233 | }
234 | }
235 |
236 | // 将失败用例添加到methodsResult, 并统计成功和失败数
237 | for (Result finResult : listFr) {
238 | if (finResult.wasSuccessful()) {
239 | ++successNum;
240 | } else {
241 | ++failNum;
242 | methodsResult.add(finResult);
243 | }
244 | }
245 |
246 | long endTime = System.currentTimeMillis();
247 | runTime = endTime - startTime;
248 | // 写结果日志
249 | writeResult(resultPath, methodsResult, failNum, successNum, casesNum,
250 | runTime, logPath, logType);
251 |
252 | // 回写日志, 根据logType回写不同格式的运行失败用例回日志文件, 简单工厂模式
253 | WriteLogFactory wlf = new WriteLogFactory();
254 | wlf.writeLog(logPath, logType, resultPath);
255 |
256 | }
257 | }
258 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/FailCases.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runfail/FailCases.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/FailCases.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runfail;
2 |
3 | import java.util.List;
4 | import java.util.Map;
5 | /*
6 | * @author hugang
7 | */
8 | public abstract class FailCases {
9 | public abstract Map, List> findFailedCases(String logPath);
10 | }
11 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/FailCasesAnt.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runfail/FailCasesAnt.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/FailCasesAnt.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runfail;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.FileNotFoundException;
6 | import java.io.FileReader;
7 | import java.io.IOException;
8 | import java.io.Reader;
9 | import java.lang.reflect.Method;
10 | import java.util.ArrayList;
11 | import java.util.Iterator;
12 | import java.util.LinkedHashMap;
13 | import java.util.List;
14 | import java.util.Map;
15 | import java.util.Set;
16 | import java.util.TreeSet;
17 | import java.util.regex.Matcher;
18 | import java.util.regex.Pattern;
19 |
20 | import org.junit.Ignore;
21 | import org.junit.Test;
22 |
23 | /*
24 | * @atuhor hugang
25 | */
26 | public class FailCasesAnt extends FailCases {
27 |
28 | @Override
29 | public Map, List> findFailedCases(String logPath) {
30 | // TODO Auto-generated method stub
31 | // 文本每一行
32 | List strList = new ArrayList();
33 | // 行号
34 | List flags = new ArrayList();
35 | // 记录FAILED和ERROR
36 | Set failSet = new TreeSet();
37 | // String regexStr =
38 | // "(Testcase:\\s\\w*([\\w]*.{3,}\\w*.):\\sFAILED)|(Testcase:\\s\\w*([\\w]*.{3,}\\w*.):\\sCaused\\san\\sERROR)";
39 | Pattern p = Pattern.compile("Testcase");
40 | Matcher m;
41 | int i = 0;
42 |
43 | try {
44 | Reader re = new FileReader(new File(logPath));
45 | BufferedReader bre = new BufferedReader(re);
46 | while (bre.ready()) {
47 | String str = bre.readLine();
48 | strList.add(str);
49 | m = p.matcher(str);
50 | // 匹配后,记录匹配的行号
51 | if (m.find()) {
52 | flags.add(i);
53 | System.out.println("find " + i);
54 | }
55 | i++;
56 | }
57 | for (int k = 0; k < flags.size(); k++) {
58 | // 去除SKIPPED, 只存 FAILED和ERROR
59 | if (!strList.get(flags.get(k)).contains("SKIPPED")) {
60 | // 从文本中取满足匹配的那行字符串
61 | failSet.add(strList.get(flags.get(k)));
62 | }
63 | }
64 | bre.close();
65 | re.close();
66 | } catch (IOException e) {
67 | // TODO Auto-generated catch block
68 | e.printStackTrace();
69 | }
70 |
71 | System.out.println("找到失败用例数: " + failSet.size());
72 | // 存失败用例
73 | Map, List> myClassMethodMap = new LinkedHashMap();
74 |
75 | // JUnitCore执行结果中,形如这种结果,某个方法初始化失败直接抛错,“[com.weibo.cases.xiaoyu.FrontAppStatusesTest:
76 | // It should get success]”
77 | // 有“方法(类)”和“类”, 运行其类下所有方法,不让其方法(类)再进myClassMethodMap:
78 | // [GroupChatNotFrontTest(com.weibo.cases.xiaoyu.FrontAppStatusesTest):
79 | // should create success]
80 | // [com.weibo.cases.xiaoyu.FrontAppStatusesTest: It should get success]
81 |
82 | // 标记该类是否通过“类”记录到myClassMethodMap
83 | Map, Integer> bitMap = new LinkedHashMap();
84 |
85 | List className = new ArrayList();
86 | List methodName = new ArrayList();
87 |
88 | for (Iterator it = failSet.iterator(); it.hasNext();) {
89 | // System.out.println(it.next().toString());
90 | // Testcase:
91 | // testAPIRequest(com.weibo.cases.xuelian.FeedWithDarwinTagsForMovieStatusTest):
92 | // FAILED
93 | // 取出失败的行
94 | String str = it.next().toString();
95 |
96 |
97 | // 先处理只有类信息的失败用例,执行该类所有方法(无法判断该方法是什么)
98 | // “[com.weibo.cases.xiaoyu.FrontAppStatusesTest: It should get success]”格式的失败用例
99 |
100 | // 标记当个类
101 | Class> singleFailClass = null;
102 |
103 | if (!str.contains("(")) {
104 | // ant 生成的单个类失败
105 | // 处理单个失败类,形如:
106 | // Testcase:
107 | // com.weibo.cases.xiaoyu.TopicFrontAddHasNewAndTopStatusTopicTest:
108 | // FAILED
109 |
110 | // JUnitCore生成的,单个类报错, 形如:
111 | // Testcase:[com.weibo.cases.xiaoyu.StatusTopicTest: null]
112 |
113 | List singleClassMethod = new ArrayList();
114 | int singleClassLeft = 10;
115 | // 从singleClassLeft开始找
116 | int singleClassRight = str.indexOf(":", singleClassLeft);
117 | String singleFail = str.substring(singleClassLeft,
118 | singleClassRight);
119 | try {
120 | singleFailClass = Class.forName(singleFail);
121 | // 拿失败类中的方法
122 | Method[] met = singleFailClass.getMethods();
123 | for (Method method : met) {
124 | // 只拿@Test 方法
125 | if (method.isAnnotationPresent(Test.class)
126 | && (!method.isAnnotationPresent(Ignore.class))) {
127 | // method.getName() 返回的格式:testLikeVideo
128 | System.out.println(method.getName());
129 | singleClassMethod.add(method.getName());
130 | }
131 | }
132 | // 将类下所有的用例放到myClassMethodMap下
133 | myClassMethodMap.put(singleFailClass, singleClassMethod);
134 | // 标记该类已通过“类”的方式进入失败用例集,无须进入“方法(类)”的方式进入失败用例集
135 | bitMap.put(singleFailClass, 1);
136 | } catch (ClassNotFoundException e) {
137 | // TODO Auto-generated catch block
138 | e.printStackTrace();
139 | }
140 |
141 | } else {
142 | // Ant生成的正常失败信息
143 | // 形如
144 | // Testcase:
145 | // testStatusWangYiGCard(com.weibo.cases.xiaoyu.StatusMusicStatusTest):
146 | // FAILED
147 | // JUnitCore 生成的正常失败信息
148 | // Testcase:[testFriendsTimelineMuti(com.weibo.cases.xiaoyu.IsReadStatusTest):
149 | // expected:<{"3859449779315109":[1]}> but
150 | // was:<{"3859449779315109":[0]}>]
151 | // 方法(类)
152 | int classBegin = str.indexOf("(");
153 | int classEnd = str.indexOf(")");
154 | // 类名
155 | String classPart = str.substring(classBegin + 1, classEnd);
156 | // 方法名,起始位置为10(固定)
157 | int beginFind = 10;
158 | String methodPart = str.substring(beginFind, classBegin);
159 |
160 | Class> failClass = null;
161 | try {
162 | failClass = Class.forName(classPart);
163 | // 判断该类是否已通过“类”的方式进入错误用例集,不存在,则以“方法(类)”处理
164 | if(!bitMap.containsKey(failClass)){
165 | // 聚合 class-method 一对多
166 | if (myClassMethodMap.containsKey(failClass)) {
167 | // 拿到之前的class 对应的list, 并在该list下新增 method, 再放回map
168 | List beforeFailMethod = myClassMethodMap
169 | .get(failClass);
170 | beforeFailMethod.add(methodPart);
171 | myClassMethodMap.put(failClass, beforeFailMethod);
172 | } else {
173 | // 第一次添加该class时
174 | List firstMethod = new ArrayList();
175 | firstMethod.add(methodPart);
176 | myClassMethodMap.put(failClass, firstMethod);
177 | }
178 | }
179 |
180 | } catch (ClassNotFoundException e) {
181 | // TODO Auto-generated catch block
182 | e.printStackTrace();
183 | }
184 | }
185 |
186 |
187 | }
188 | return myClassMethodMap;
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/FailCasesContext.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runfail/FailCasesContext.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/FailCasesContext.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runfail;
2 |
3 | import java.util.List;
4 | import java.util.Map;
5 | /*
6 | * @author hugang
7 | */
8 | public class FailCasesContext {
9 | FailCases fc = null;
10 |
11 | // 简单工厂模式和策略模式, 根据type声明,实例化不同实例
12 | public FailCasesContext(String type) {
13 | // 为了支持JDK6 , case后用数字; JDK7可以直接String类型
14 | // 默认为2, ant
15 | int typeNum =2;
16 | if("MVN".equals(type)){
17 | typeNum = 1;
18 | }else if("ANT".equals(type)){
19 | typeNum = 2;
20 | }
21 | switch (typeNum) {
22 | case 1:
23 | // FailCasesMvn fcm = new FailCasesMvn();
24 | // 重构匹配mvn test
25 | NewFailCasesMvn fcm = new NewFailCasesMvn();
26 | fc = fcm;
27 | break;
28 | case 2:
29 | FailCasesAnt fca = new FailCasesAnt();
30 | fc = fca;
31 | break;
32 | }
33 | }
34 |
35 | public Map,List> getFailCases(String logPath) {
36 | return fc.findFailedCases(logPath);
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/NewFailCasesMvn.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runfail/NewFailCasesMvn.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/NewFailCasesMvn.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runfail;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.FileNotFoundException;
6 | import java.io.FileReader;
7 | import java.io.IOException;
8 | import java.io.Reader;
9 | import java.lang.reflect.Method;
10 | import java.util.ArrayList;
11 | import java.util.HashMap;
12 | import java.util.HashSet;
13 | import java.util.LinkedHashMap;
14 | import java.util.List;
15 | import java.util.Map;
16 | import java.util.Set;
17 | import java.util.regex.Matcher;
18 | import java.util.regex.Pattern;
19 |
20 | import org.junit.Ignore;
21 | import org.junit.Test;
22 |
23 |
24 | /*
25 | *
26 | * 正则匹配出失败用例,maven-surefire-customresult自定义输出格式
27 | *
28 | * CustomResult Fail@后面
29 | *
30 | * CustomResult Error@后面
31 | *
32 | * 1) 后面带(),com.weibo.cases.wanglei16.PublicMentionsStatusTest.testFilterType(com.weibo.cases.wanglei16.PublicMentionsStatusTest)
33 | * 2)后面不带(),com.weibo.cases.maincase.XiaoyuGroupStatusLikeBVTTest.com.weibo.cases.maincase.XiaoyuGroupStatusLikeBVTTest
34 | *
35 | *
36 | *
37 | *
38 | *
39 | * @author hugang
40 | */
41 | public class NewFailCasesMvn extends FailCases {
42 |
43 | // 找出所有失败用例 每行字符串信息
44 | public Set failCasesStr(String logPath){
45 | String failRegex = "^CustomResult Fail@(.*)";
46 | Pattern failPattern = Pattern.compile(failRegex);
47 | Matcher matchFail;
48 |
49 | String errorRegex = "^CustomResult Error@(.*)";
50 | Pattern errorPattern = Pattern.compile(errorRegex);
51 | Matcher matchError;
52 |
53 | // 去掉重复的
54 | Set failSet = new HashSet();
55 |
56 | try (BufferedReader bre = new BufferedReader(new FileReader(new File(logPath)));){
57 | while (bre.ready()) {
58 | String str = bre.readLine();
59 | matchFail = failPattern.matcher(str);
60 | matchError = errorPattern.matcher(str);
61 | if(matchFail.matches() || matchError.matches()){
62 | failSet.add(str);
63 | }
64 | }
65 | } catch (IOException e) {
66 | // TODO Auto-generated catch block
67 | e.printStackTrace();
68 | }
69 | return failSet;
70 | }
71 |
72 | // 处理字符串信息, 将信息转换成Map
73 | public Map, List> getResultMap(Set failSet) {
74 | Map, List> resultMap = new LinkedHashMap, List>();
75 | String className;
76 | List methodList = new ArrayList();
77 | Class> failClass = null;
78 | // 标记Class是否将全部方法放入Map中
79 | Map, Integer> bitMap = new HashMap, Integer>();
80 | for(String str : failSet){
81 | // 先处理不带(), 表示整个类失败
82 | if( ! str.contains("(")){
83 | className = str.substring(str.lastIndexOf("com"), str.length());
84 | try {
85 | failClass = Class.forName(className);
86 | } catch (ClassNotFoundException e) {
87 | // TODO Auto-generated catch block
88 | e.printStackTrace();
89 | }
90 | // 拿失败类中的方法
91 | Method[] met = failClass.getMethods();
92 | for (Method method : met) {
93 | // 只拿@Test 方法
94 | if (method.isAnnotationPresent(Test.class)
95 | && (!method
96 | .isAnnotationPresent(Ignore.class))) {
97 | // method.getName() 返回的格式:testLikeVideo
98 | System.out.println(method.getName());
99 | methodList.add(method.getName());
100 | }
101 | }
102 | resultMap.put(failClass, methodList);
103 | bitMap.put(failClass, 1);
104 | }else{
105 | // 处理单个测试方法
106 | className = str.substring(str.indexOf("(") + 1, str.length() - 1);
107 | try {
108 | failClass = Class.forName(className);
109 | } catch (ClassNotFoundException e) {
110 | // TODO Auto-generated catch block
111 | e.printStackTrace();
112 | }
113 |
114 | // 之后支持 添加JUnitCore格式
115 | int last = str.indexOf("(");
116 | String methodPart = str.substring(str.lastIndexOf(".", last) + 1, last);
117 |
118 |
119 | // 判断该类是否已通过“类”的方式进入错误用例集,不存在,则以“方法(类)”处理
120 | if(!bitMap.containsKey(failClass)){
121 | // 聚合 class-method 一对多
122 | if (resultMap.containsKey(failClass)) {
123 | // 拿到之前的class 对应的list, 并在该list下新增 method, 再放回map
124 | List beforeFailMethod = resultMap
125 | .get(failClass);
126 | beforeFailMethod.add(methodPart);
127 | resultMap.put(failClass, beforeFailMethod);
128 | } else {
129 | // 第一次添加该class时
130 | List firstMethod = new ArrayList();
131 | firstMethod.add(methodPart);
132 | resultMap.put(failClass, firstMethod);
133 | }
134 | }
135 | }
136 | }
137 |
138 | int casesNum = 0;
139 | List myMethod = new ArrayList();
140 | for(Map.Entry, List> myCases: resultMap.entrySet()){
141 |
142 | myMethod = myCases.getValue();
143 | casesNum += myMethod.size();
144 | System.out.println(myCases.getKey() + ":" + myMethod + ":" + myMethod.size() );
145 | }
146 | System.out.println("mvn 找到用例数:" + casesNum);
147 | return resultMap;
148 | }
149 |
150 | @Override
151 | public Map, List> findFailedCases(String logPath) {
152 | return getResultMap(failCasesStr(logPath));
153 | }
154 |
155 | }
156 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/NewWriteLogMvn.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runfail/NewWriteLogMvn.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/NewWriteLogMvn.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runfail;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.BufferedWriter;
5 | import java.io.File;
6 | import java.io.FileReader;
7 | import java.io.FileWriter;
8 | import java.io.IOException;
9 | import java.text.SimpleDateFormat;
10 | import java.util.ArrayList;
11 | import java.util.Date;
12 | import java.util.List;
13 | import java.util.regex.Matcher;
14 | import java.util.regex.Pattern;
15 |
16 | /*
17 | * 将JUnitCore执行结果,回写到源日志
18 | * author hugang
19 | */
20 | public class NewWriteLogMvn {
21 |
22 |
23 | // 格式转换,将JUnitCore装换成Mvn
24 | public List FormatJUnitCoreToMvn(List failStr){
25 | List mvnFailList = new ArrayList();
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | return mvnFailList;
34 | }
35 |
36 |
37 |
38 | public void writeLogMvn(String logPath, String resultPath)
39 | throws IOException {
40 | BufferedWriter writer;
41 | BufferedReader reader;
42 |
43 | // 日志文件
44 | File sourceFile = new File(logPath);
45 | if (!sourceFile.exists()) {
46 | sourceFile.createNewFile();
47 | }
48 | writer = new BufferedWriter(new FileWriter(sourceFile));
49 |
50 | // 结果日志
51 | File readFile = new File(resultPath);
52 | if (!readFile.exists()) {
53 | readFile.createNewFile();
54 | System.out.println("read 文件不存在, Result.txt 不存在");
55 | } else {
56 | System.out.println("" + readFile.canRead() + " "
57 | + readFile.length() + " " + readFile.getAbsolutePath()
58 | + " " + readFile.getCanonicalPath());
59 | }
60 | reader = new BufferedReader(new FileReader(readFile));
61 |
62 | // 1
63 | // 根据Result.txt , 正则表达式找失败用例
64 | // 形如 方法(类) 格式
65 | // [GroupChatNotFrontTest(com.weibo.cases.xiaoyu.FrontAppStatusesTest):
66 | // should create success]
67 | String pattern = "\\[(\\w+)\\((.*)\\):(.*)\\]";
68 | Pattern pt = Pattern.compile(pattern);
69 | Matcher mt;
70 |
71 | List strList = new ArrayList();
72 |
73 | // 2
74 | // 根据Result.txt , 正则表达式找失败用例(只提供失败类信息)
75 | // 形如:
76 | // [com.weibo.cases.xiaoyu.FrontAppStatusesTest: It should get success]
77 | String patternClass = "\\[((\\w+\\.)+(\\w+)):(.*)\\]";
78 | Pattern ptClass = Pattern.compile(patternClass);
79 | Matcher mtClass;
80 |
81 | // 行号
82 | List flags = new ArrayList();
83 | int i = 0;
84 |
85 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
86 |
87 | writer.write(sdf.format(new Date()));
88 | writer.write("mvn 回写失败结果");
89 | writer.newLine();
90 |
91 | String failStackTrace = "CustomResult Failed StackTrace@";
92 | String failInfo = "CustomResult Fail@";
93 | String failMethodStackTraceStr;
94 | String failMethodInfoStr;
95 |
96 | String failClassStackTraceStr;
97 | String failClassInfoStr;
98 | try {
99 | while (reader.ready()) {
100 | String str = reader.readLine();
101 | strList.add(str);
102 | mt = pt.matcher(str);
103 | mtClass = ptClass.matcher(str);
104 | // 匹配1后,记录匹配的行号
105 | if (mt.find()) {
106 | String[] className = mt.group(2).split("\\.");
107 | int size = className.length;
108 | String methodName = mt.group(1);
109 | // 模拟MVN 日志
110 | // 1.错误栈信息,供前端解析
111 | // CustomResult Failed StackTrace@SassPart2ShortUrlStatusTest.testPublicRepost:88 testPublicRepost exception
112 | failMethodStackTraceStr = failStackTrace + className[size - 1] + "."
113 | + methodName + mt.group(3).replaceAll("\n", "");
114 | // 2.用例信息
115 | // CustomResult Fail@com.weibo.cases.wanglei16.SassPart2ShortUrlStatusTest.testPublicRepost(com.weibo.cases.wanglei16.SassPart2ShortUrlStatusTest)
116 | failMethodInfoStr = failInfo + mt.group(2) + "." + methodName + "(" + mt.group(2) + ")";
117 | writer.write(failMethodStackTraceStr);
118 | // 供前端解析
119 | System.out.println(failMethodStackTraceStr);
120 | writer.newLine();
121 | writer.write(failMethodInfoStr);
122 | writer.newLine();
123 | i++;
124 | }
125 | // 类失败
126 | if (mtClass.find()) {
127 | // 模拟MVN 日志
128 | // 1.错误栈信息, group(1) 全限类名, group(4)栈信息
129 | failClassStackTraceStr = failStackTrace + mtClass.group(1) + " " + mtClass.group(4).replaceAll("\n", "");
130 | // com.weibo.cases.maincase.XiaoyuGroupStatusLikeBVTTest.com.weibo.cases.maincase.XiaoyuGroupStatusLikeBVTTest
131 | failClassInfoStr = failInfo + mtClass.group(1) + "." + mtClass.group(1);
132 | writer.write(failClassStackTraceStr);
133 | // 供前端解析
134 | System.out.println(failClassStackTraceStr);
135 | writer.newLine();
136 | writer.write(failClassInfoStr);
137 | writer.newLine();
138 | i++;
139 | }
140 | }
141 |
142 | } finally {
143 | writer.close();
144 | reader.close();
145 |
146 | }
147 |
148 | }
149 |
150 | }
151 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/RealClassMvn.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runfail/RealClassMvn.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/RealClassMvn.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runfail;
2 | /*
3 | * @author hugang
4 | */
5 | public class RealClassMvn {
6 | String[] packageName = {
7 | "com.weibo.cases.hugang", "com.weibo.cases.lingna", "com.weibo.cases.maincase",
8 | "com.weibo.cases.qiaoli", "com.weibo.cases.wanglei16", "com.weibo.cases.xiaoyu",
9 | "com.weibo.cases.xuelian", "com.weibo.cases.beibei12", "com.weibo.cases.publicservice",
10 | "com.weibo.cases.yanlei3", "com.weibo.cases.guanglu"
11 | };
12 |
13 | int now = 0;
14 | int retryNum = packageName.length;
15 |
16 | String realClassName;
17 |
18 |
19 | public String getRealClassName() {
20 | return realClassName;
21 | }
22 |
23 |
24 | public void setRealClassName(String realClassName) {
25 | this.realClassName = realClassName;
26 | }
27 |
28 | // 由于, mvn执行结果中失败的用例只返回类名(ActivitiesTimelineSpActivitiesTest),
29 | // 而不是完全类名
30 | // (包括包名,e.g.com.weibo.cases.xuelian.ActivitiesTimelineSpActivitiesTest)
31 | // 导致Class.forName(类名)抛异常
32 | // 使用递归加上不同包名,进行判断,找到正确完全类名
33 | public void findClass(String className) throws Throwable{
34 | try{
35 | realClassName = packageName[now++] + "." + className;
36 | Class.forName(realClassName);
37 | setRealClassName(realClassName);
38 | }catch(ClassNotFoundException e){
39 | if(now < retryNum){
40 | findClass(className);
41 | }else{
42 | throw e;
43 | }
44 | }
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/Result.txt:
--------------------------------------------------------------------------------
1 | (一).Time's Result generated on: 2015.08.31 13:45:18,722
2 | (二).日志类型:ANT
3 | (三).日志名:/Users/hugang/myworkspace/AutoTestContent/src/test/java/com/weibo/runfail/TEST-com.weibo.cases.suite.LikeTestSuite.txt
4 | ===================== 结果集 =====================
5 | 用例总数:4, 成功数:3, 失败数:1, 运行时间:0 分钟 9 秒
6 | =================================================
7 |
8 | [testMultiType(com.weibo.cases.wanglei16.LikesByMeBatchLikeTest): testMultiType fail]
9 |
10 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/RunFailedCases.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runfail/RunFailedCases.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/RunFailedCases.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runfail;
2 |
3 | import java.io.IOException;
4 | import java.util.List;
5 | import java.util.Map;
6 | import java.util.concurrent.ExecutionException;
7 | /*
8 | *
9 | * 根据ant/mvn 执行日志,执行失败用例
10 | *
11 | * @author hugang
12 | */
13 | public class RunFailedCases {
14 |
15 | // 失败日志名
16 | // public static final String LOGNAME = "725.txt";
17 | // // 日志类型,支持MVN, ANT等2种
18 | // public static final String LOGTYPE = "MVN";
19 | //
20 | // // 失败日志名
21 | public static final String LOGNAME = "TEST-com.weibo.cases.suite.HugangTestSuite.txt";
22 | // 日志类型,支持MVN, ANT等2种
23 | public static final String LOGTYPE = "ANT";
24 | // 运行结果日志名,无需修改
25 | public static final String RESULTLOG = "Result.txt";
26 | // 执行用例方式:
27 | // 1.类级别并发(方法串行)
28 | // 2.方法级别并发
29 | // 3.串行
30 | // 默认以1.类级别并发(方法串行)执行
31 | public static final int RUNTYPE = 1;
32 |
33 | public static void main(String[] args) throws ExecutionException, IOException {
34 | // 记录失败用例,key:Class , value:List of methods
35 | Map, List> failMap;
36 |
37 | // 失败用例日志路径
38 | String logPath = System.getProperty("user.dir")
39 | + System.getProperty("file.separator") + "src"
40 | + System.getProperty("file.separator") + "test"
41 | + System.getProperty("file.separator") + "java"
42 | + System.getProperty("file.separator") + "com"
43 | + System.getProperty("file.separator") + "weibo"
44 | + System.getProperty("file.separator") + "runfail"
45 | + System.getProperty("file.separator")
46 | + LOGNAME;
47 |
48 | // 结果日志路径
49 | String resultPath = System.getProperty("user.dir")
50 | + System.getProperty("file.separator") + "src"
51 | + System.getProperty("file.separator") + "test"
52 | + System.getProperty("file.separator") + "java"
53 | + System.getProperty("file.separator") + "com"
54 | + System.getProperty("file.separator") + "weibo"
55 | + System.getProperty("file.separator") + "runfail"
56 | + System.getProperty("file.separator")
57 | + RESULTLOG;
58 |
59 | System.out.println(logPath);
60 | System.out.println(resultPath);
61 |
62 | // "\"的转义字符
63 | logPath = logPath.replace("\\", "\\\\");
64 |
65 | // 简单工厂模式和策略模式, 根据不同的LOGTYPE创建不同实例
66 | FailCasesContext fcc = new FailCasesContext(LOGTYPE);
67 | // 通过扫日志,拿到对应失败case的Map
68 | failMap = fcc.getFailCases(logPath);
69 |
70 | // 执行失败用例
71 | ExecuteCases ec = new ExecuteCases();
72 | // 执行
73 | switch(RUNTYPE){
74 | case 1:
75 | ec.executorClassCases(failMap, logPath, resultPath, LOGTYPE);
76 | break;
77 | case 2:
78 | ec.executorMethodCases(failMap, logPath, resultPath, LOGTYPE);
79 | break;
80 | case 3:
81 | ec.SerialExecutorCases(failMap, logPath, resultPath, LOGTYPE);
82 | break;
83 | default:
84 | ec.executorClassCases(failMap, logPath, resultPath, LOGTYPE);
85 | break;
86 | }
87 |
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/ThreadRunTest.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runfail/ThreadRunTest.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/ThreadRunTest.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runfail;
2 |
3 | import java.util.concurrent.Callable;
4 |
5 | import org.junit.runner.JUnitCore;
6 | import org.junit.runner.Request;
7 | import org.junit.runner.Result;
8 | /*
9 | * @author
10 | */
11 | //Callable实现类,一个线程执行一个case, 返回结果Result
12 | class ThreadRunTest implements Callable{
13 | private Class oneFailClass;
14 | private String oneFailMethod;
15 |
16 | public ThreadRunTest(Class oneFailClass, String oneFailMethod){
17 | this.oneFailClass = oneFailClass;
18 | this.oneFailMethod = oneFailMethod;
19 | }
20 |
21 |
22 | public Result call() throws Exception {
23 | // TODO Auto-generated method stub
24 | // JUnitCore执行JUnit用例
25 | JUnitCore junitRunner = new JUnitCore();
26 | Request request = Request.method(oneFailClass, oneFailMethod);
27 | Result result = junitRunner.run(request);
28 |
29 | return result;
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/WriteLogAnt.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runfail/WriteLogAnt.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/WriteLogAnt.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runfail;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.BufferedWriter;
5 | import java.io.File;
6 | import java.io.FileReader;
7 | import java.io.FileWriter;
8 | import java.io.IOException;
9 | import java.text.SimpleDateFormat;
10 | import java.util.ArrayList;
11 | import java.util.Date;
12 | import java.util.List;
13 | import java.util.regex.Matcher;
14 | import java.util.regex.Pattern;
15 |
16 |
17 |
18 | /*
19 | * @author hugang
20 | */
21 | public class WriteLogAnt {
22 | public void writeLogAnt(String logPath, String resultPath)
23 | throws IOException {
24 | BufferedWriter writer;
25 | BufferedReader reader;
26 |
27 | // 日志文件
28 | File sourceFile = new File(logPath);
29 | if (!sourceFile.exists()) {
30 | sourceFile.createNewFile();
31 | }
32 | writer = new BufferedWriter(new FileWriter(sourceFile));
33 |
34 | // 结果日志
35 | File readFile = new File(resultPath);
36 | if (!readFile.exists()) {
37 | readFile.createNewFile();
38 | System.out.println("read 文件不存在, Result.txt 不存在");
39 | } else {
40 | System.out.println("" + readFile.canRead() + " "
41 | + readFile.length() + " " + readFile.getAbsolutePath()
42 | + " " + readFile.getCanonicalPath());
43 | }
44 | reader = new BufferedReader(new FileReader(readFile));
45 |
46 | // 根据Result.txt , 正则表达式找失败用例,
47 | // 形如 方法(类) 格式
48 | // [GroupChatNotFrontTest(com.weibo.cases.xiaoyu.FrontAppStatusesTest):
49 | // should create success]
50 | String pattern = "\\[(\\w+)\\((.*)\\)";
51 |
52 | Pattern pt = Pattern.compile(pattern);
53 | Matcher mt;
54 |
55 | // 根据Result.txt , 正则表达式找失败用例(只提供失败类信息)
56 | // 形如:
57 | // [com.weibo.cases.xiaoyu.FrontAppStatusesTest: It should get success]
58 | String patternClass = "\\[((\\w+\\.)+\\w+):";
59 | Pattern ptClass = Pattern.compile(patternClass);
60 | Matcher mtClass;
61 |
62 | List strList = new ArrayList();
63 | // 行号
64 | List flags = new ArrayList();
65 | int i = 0;
66 |
67 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
68 | // 写时间戳
69 | writer.write(sdf.format(new Date()));
70 | writer.newLine();
71 |
72 | try {
73 | while (reader.ready()) {
74 | String str = reader.readLine();
75 | strList.add(str);
76 | mt = pt.matcher(str);
77 | mtClass = ptClass.matcher(str);
78 | // 匹配后,记录匹配的行号
79 | if (mt.find() || mtClass.find()) {
80 | flags.add(i);
81 | }
82 | i++;
83 | }
84 | for (int k = 0; k < flags.size(); k++) {
85 | // 模拟 FindFailTest.java 截取的规则
86 | String failStr = "Testcase:" + strList.get(flags.get(k));
87 | writer.write(failStr);
88 | writer.newLine();
89 | }
90 | // System.out.println("--------------------------------------");
91 | // System.out.println(" Ant Model find failcases number: " + i);
92 | // System.out.println("--------------------------------------");
93 | // Utils.sleep(2000);
94 | } finally {
95 | writer.close();
96 | reader.close();
97 |
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/WriteLogFactory.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runfail/WriteLogFactory.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runfail/WriteLogFactory.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runfail;
2 |
3 | import java.io.IOException;
4 | /*
5 | * @author hugang
6 | */
7 | public class WriteLogFactory {
8 | public void writeLog(String logPath, String logType, String resultPath)
9 | throws IOException {
10 | // 为了支持JDK6 , case后用数字; JDK7可以直接String类型
11 | int typeNum = 2;
12 | if ("MVN".equals(logType)) {
13 | typeNum = 1;
14 | } else if ("ANT".equals(logType)) {
15 | typeNum = 2;
16 | }
17 |
18 | switch (typeNum) {
19 | case 1:
20 | // new WriteLogMvn().writeLogMvn(logPath, resultPath);
21 | new NewWriteLogMvn().writeLogMvn(logPath, resultPath);
22 | break;
23 | case 2:
24 | new WriteLogAnt().writeLogAnt(logPath, resultPath);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runner/Concurrent.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runner/Concurrent.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runner/Concurrent.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runner;
2 | import java.lang.annotation.ElementType;
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.RetentionPolicy;
5 | import java.lang.annotation.Target;
6 |
7 | @Retention(RetentionPolicy.RUNTIME)
8 | @Target({ ElementType.TYPE })
9 | public @interface Concurrent {
10 | // int threads() default 400;
11 | int threads() default 100;
12 | }
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runner/ConcurrentSuite$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runner/ConcurrentSuite$1.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runner/ConcurrentSuite$2$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runner/ConcurrentSuite$2$1.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runner/ConcurrentSuite$2.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runner/ConcurrentSuite$2.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runner/ConcurrentSuite$3.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runner/ConcurrentSuite$3.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runner/ConcurrentSuite.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runner/ConcurrentSuite.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runner/ConcurrentSuite.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runner;
2 |
3 | import org.junit.Ignore;
4 | import org.junit.Test;
5 | import org.junit.experimental.categories.Categories;
6 | import org.junit.extensions.cpsuite.ClasspathSuite;
7 | import org.junit.internal.builders.AllDefaultPossibilitiesBuilder;
8 | import org.junit.runner.Runner;
9 | import org.junit.runners.ParentRunner;
10 | import org.junit.runners.model.InitializationError;
11 | import org.junit.runners.model.RunnerBuilder;
12 | import org.junit.runners.model.RunnerScheduler;
13 |
14 |
15 | import java.lang.reflect.Method;
16 | import java.util.ArrayList;
17 | import java.util.Arrays;
18 | import java.util.LinkedList;
19 | import java.util.List;
20 | import java.util.Queue;
21 | import java.util.concurrent.CompletionService;
22 | import java.util.concurrent.ExecutorCompletionService;
23 | import java.util.concurrent.ExecutorService;
24 | import java.util.concurrent.Executors;
25 | import java.util.concurrent.Future;
26 | import java.util.concurrent.ThreadFactory;
27 | import java.util.concurrent.TimeUnit;
28 | import java.util.concurrent.atomic.AtomicInteger;
29 |
30 | /**
31 | *
32 | * 自定义runner, 并发执行
33 | *
34 | *
35 | * @author hugang
36 | *
37 | */
38 | public final class ConcurrentSuite extends ClasspathSuite {
39 |
40 | public static Runner MulThread(Runner runner) {
41 | if (runner instanceof ParentRunner) {
42 | // setScheduler(RunnerScheduler scheduler):Sets a scheduler that
43 | // determines the order and parallelization of children
44 | // RunnerScheduler:Represents a strategy for scheduling when
45 | // individual test methods should be run (in serial or parallel)
46 | ((ParentRunner) runner).setScheduler(new RunnerScheduler() {
47 | private final ExecutorService fService = Executors
48 | .newCachedThreadPool();
49 |
50 | // private final ExecutorService fService =
51 | // Executors.newFixedThreadPool(10);
52 |
53 | // Schedule a child statement to run
54 | public void schedule(Runnable childStatement) {
55 | this.fService.submit(childStatement);
56 | }
57 |
58 | // Override to implement any behavior that must occur after all
59 | // children have been scheduled
60 | public void finished() {
61 | try {
62 | this.fService.shutdown();
63 | this.fService.awaitTermination(9223372036854775807L,
64 | TimeUnit.NANOSECONDS);
65 | } catch (InterruptedException e) {
66 | e.printStackTrace(System.err);
67 | }
68 | }
69 | });
70 | }
71 | return runner;
72 | }
73 |
74 | public ConcurrentSuite(final Class> klass) throws InitializationError {
75 | // 调用父类ClasspathSuite构造函数
76 | // AllDefaultPossibilitiesBuilder根据不同的测试类定义(@RunWith的信息)返回Runner,使用职责链模式
77 | super(klass, new AllDefaultPossibilitiesBuilder(true) {
78 | @Override
79 | public Runner runnerForClass(Class> testClass) throws Throwable {
80 | List builders = Arrays
81 | .asList(new RunnerBuilder[] {
82 | // 创建Runner, 工厂类,
83 | // 自定义自己的Runner,找出注解为@Ignore,并输出@Ignore的类和方法名
84 | new RunnerBuilder() {
85 | @Override
86 | public Runner runnerForClass(
87 | Class> testClass)
88 | throws Throwable {
89 | // 获取类的所有方法
90 | Method[] methods = testClass
91 | .getMethods();
92 |
93 | // 如果类有@Ignore,则只输出类名,因为Junit最后计算结果时,会把@Ignore类记为1个用例,
94 | // 不是计算类下面的测试方法数(实验验证过)
95 | // 否则,遍历方法,如果方法有@Ignore,则输出该方法
96 | if (testClass
97 | .isAnnotationPresent(Ignore.class)) {
98 |
99 | System.out.println("Ignore: "
100 | + testClass.getName());
101 |
102 | } else {
103 | for (Method method : methods) {
104 | if (method
105 | .isAnnotationPresent(Ignore.class)) {
106 | System.out.println("Ignore: "
107 | + testClass
108 | .getName()
109 | + "."
110 | + method.getName());
111 | }
112 | }
113 | }
114 | return null;
115 | }
116 | }, ignoredBuilder(), annotatedBuilder(),
117 | suiteMethodBuilder(), junit3Builder(),
118 | junit4Builder() });
119 | for (RunnerBuilder each : builders) {
120 | // 根据不同的测试类定义(@RunWith的信息)返回Runner
121 | Runner runner = each.safeRunnerForClass(testClass);
122 | if (runner != null)
123 | // 方法级别,多线程执行
124 | // return MulThread(runner);
125 | return runner;
126 | }
127 | return null;
128 | }
129 | });
130 |
131 | // 类级别,多线程执行
132 | setScheduler(new RunnerScheduler() {
133 | private final ExecutorService fService = Executors
134 | .newCachedThreadPool();
135 |
136 | public void schedule(Runnable paramRunnable) {
137 | // TODO Auto-generated method stub
138 | fService.submit(paramRunnable);
139 | }
140 |
141 | public void finished() {
142 | // TODO Auto-generated method stub
143 | try {
144 | fService.shutdown();
145 | fService.awaitTermination(Long.MAX_VALUE,
146 | TimeUnit.NANOSECONDS);
147 | } catch (InterruptedException e) {
148 | e.printStackTrace(System.err);
149 | }
150 | }
151 | //
152 | // // ExecutorService executorService =
153 | // Executors.newFixedThreadPool(
154 | // // klass.isAnnotationPresent(Concurrent.class) ?
155 | // // klass.getAnnotation(Concurrent.class).threads() :
156 | // // (int) (Runtime.getRuntime().availableProcessors() * 1.5),
157 | // // new NamedThreadFactory(klass.getSimpleName()));
158 | // // CompletionService completionService = new
159 | // // ExecutorCompletionService(executorService);
160 | // // Queue> tasks = new LinkedList>();
161 | // //
162 | // // @Override
163 | // // public void schedule(Runnable childStatement) {
164 | // // tasks.offer(completionService.submit(childStatement, null));
165 | // // }
166 | // //
167 | // // @Override
168 | // // public void finished() {
169 | // // try {
170 | // // while (!tasks.isEmpty())
171 | // // tasks.remove(completionService.take());
172 | // // } catch (InterruptedException e) {
173 | // // Thread.currentThread().interrupt();
174 | // // } finally {
175 | // // while (!tasks.isEmpty())
176 | // // tasks.poll().cancel(true);
177 | // // executorService.shutdownNow();
178 | // // }
179 | //
180 | });
181 | }
182 |
183 | // static final class NamedThreadFactory implements ThreadFactory {
184 | // static final AtomicInteger poolNumber = new AtomicInteger(1);
185 | // final AtomicInteger threadNumber = new AtomicInteger(1);
186 | // final ThreadGroup group;
187 | //
188 | // NamedThreadFactory(String poolName) {
189 | // group = new ThreadGroup(poolName + "-"
190 | // + poolNumber.getAndIncrement());
191 | // }
192 | //
193 | // @Override
194 | // public Thread newThread(Runnable r) {
195 | // System.out.println(group.getName() + "-thread-");
196 | //
197 | // return new Thread(group, r, group.getName() + "-thread-"
198 | // + threadNumber.getAndIncrement(), 0);
199 | // }
200 | // }
201 |
202 | }
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runner/Retry.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runner/Retry.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runner/Retry.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runner;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | import com.weibo.global.ParseProperties;
9 |
10 | // 重试次数,默认2
11 | // 方法会覆盖类,子类会覆盖父类
12 |
13 | // 重试默认值改用配置文件global.properties中 retry 字段指定
14 | @Retention(RetentionPolicy.RUNTIME)
15 | @Target({ElementType.METHOD,ElementType.TYPE})
16 | public @interface Retry {
17 | int value() default 2;
18 | }
19 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runner/RetryRunner.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runner/RetryRunner.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runner/RetryRunner.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runner;
2 |
3 |
4 |
5 | import java.lang.annotation.Annotation;
6 |
7 | import junit.framework.AssertionFailedError;
8 |
9 | import org.junit.Ignore;
10 | import org.junit.internal.AssumptionViolatedException;
11 | import org.junit.internal.runners.model.EachTestNotifier;
12 | import org.junit.runner.Description;
13 | import org.junit.runner.notification.RunNotifier;
14 | import org.junit.runner.notification.StoppedByUserException;
15 | import org.junit.runners.BlockJUnit4ClassRunner;
16 | import org.junit.runners.model.FrameworkMethod;
17 | import org.junit.runners.model.InitializationError;
18 | import org.junit.runners.model.MultipleFailureException;
19 | import org.junit.runners.model.Statement;
20 |
21 | import com.weibo.global.ParseProperties;
22 |
23 | /**
24 | * 自定义runner, 运行中重试
25 | * @author hugang
26 | *
27 | */
28 | public class RetryRunner extends BlockJUnit4ClassRunner {
29 |
30 | private int retryTime;
31 | private int now = 0;
32 |
33 | public RetryRunner(Class> klass) throws InitializationError {
34 | super(klass);
35 | }
36 |
37 | @Override
38 | protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
39 | Description description = describeChild(method);
40 | if (method.getAnnotation(Ignore.class) != null) {
41 | notifier.fireTestIgnored(description);
42 | } else
43 | try {
44 | if (shouldRetry(method)) { // 需要重试,走重试逻辑
45 | runLeafRetry(methodBlock(method), description, notifier);
46 | } else { // 不需要重试,走原来逻辑
47 | runLeaf(methodBlock(method), description, notifier);
48 | }
49 | } catch (Exception e) {
50 | // TODO Auto-generated catch block
51 | e.printStackTrace();
52 | }
53 | }
54 |
55 | private boolean shouldRetry(final FrameworkMethod method) throws Exception {
56 | Retry retry = null;
57 | // 类上有@Retry
58 | retry = getClassRetry(getTestClass().getJavaClass());
59 | // 方法有@Retry
60 | Retry annotation = method.getAnnotation(Retry.class);
61 | // 方法的@Retry替换类的@Retry
62 | if (annotation != null) {
63 | retry = annotation;
64 | }
65 | if (retry != null) {
66 | if (retry.value() > 0) {
67 | // 之前根据注解@Retry, 获取重试次数
68 | // retryTime = retry.value();
69 | // 现在更改为,根据global.properties中retry判断次数, 为空不重试, 其他值为默认重试次数
70 | String retryProperty = ParseProperties.getSystemProperty("retry");
71 | if("".equals(retryProperty) || (1 == retry.value())){
72 | retryTime = 1;
73 | }else{
74 | retryTime = Integer.parseInt(retryProperty);
75 | }
76 | // System.out.println("test property get retry: " + retryTime);
77 | } else {
78 | // retry.value()<=0时,为1
79 | retryTime = 1;
80 | }
81 | now = 0;
82 | return true;
83 | }
84 | return false;
85 | }
86 |
87 | private Retry getClassRetry(Class> mClass) {
88 | if (mClass == null || mClass == Object.class) {
89 | return null;
90 | }
91 | Retry retry = null;
92 | Annotation[] annotations = mClass.getAnnotations();
93 | for (Annotation annotation : annotations) {
94 | if (annotation instanceof Retry) {
95 | retry = (Retry) annotation;
96 | break;
97 | }
98 | }
99 | // 判断父类
100 | if (null == retry) {
101 | retry = getClassRetry(mClass.getSuperclass());
102 | }
103 | return retry;
104 | }
105 |
106 | protected final void runLeafRetry(Statement statement,
107 | Description description, RunNotifier notifier) {
108 | EachTestNotifier eachNotifier = new EachTestNotifier(notifier,
109 | description);
110 | eachNotifier.fireTestStarted();
111 | try {
112 | retryRun(statement);
113 | // 标记成功用例信息
114 | System.out.println("SuccessCase: " + description);
115 | } catch (AssumptionViolatedException e) {
116 | eachNotifier.addFailedAssumption(e);
117 | } catch (Throwable e) {
118 | eachNotifier.addFailure(e);
119 | } finally {
120 | eachNotifier.fireTestFinished();
121 | }
122 | }
123 |
124 | private void retryRun(Statement statement) throws Throwable {
125 | try {
126 | now++;
127 | statement.evaluate();
128 |
129 | } catch (AssertionFailedError e) {
130 | if (now < retryTime) {
131 | retryRun(statement);
132 | } else {
133 | throw e;
134 | }
135 | } catch (MultipleFailureException e) {
136 | if (now < retryTime) {
137 | retryRun(statement);
138 | } else {
139 | throw e;
140 | }
141 | } catch (AssertionError e) {
142 | // assertThat断言失败,抛AssertionError
143 | if (now < retryTime) {
144 | retryRun(statement);
145 | } else {
146 | throw e;
147 | }
148 | } catch (Throwable e) {
149 | // Throwable 所有异常
150 | if (now < retryTime) {
151 | retryRun(statement);
152 | } else {
153 | throw e;
154 | }
155 | }
156 | }
157 |
158 | }
159 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runner/ThreadRunner$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runner/ThreadRunner$1.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runner/ThreadRunner$Test.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runner/ThreadRunner$Test.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runner/ThreadRunner.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/runner/ThreadRunner.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/runner/ThreadRunner.java:
--------------------------------------------------------------------------------
1 | package com.weibo.runner;
2 |
3 | import java.util.concurrent.Executor;
4 | import java.util.concurrent.ExecutorService;
5 | import java.util.concurrent.Executors;
6 | import java.util.concurrent.atomic.AtomicInteger;
7 |
8 | import org.junit.runner.notification.RunNotifier;
9 | import org.junit.runners.BlockJUnit4ClassRunner;
10 | import org.junit.runners.model.FrameworkMethod;
11 | import org.junit.runners.model.InitializationError;
12 | import org.junit.runners.model.Statement;
13 |
14 | /**
15 | * Runs all tests in parallel and waits for them to complete.
16 | * Up to {@link #maxThreads} will be run at once.
17 | * 自定义runner: 单个测试类,方法并发执行
18 | * @hugang
19 | *
20 | */
21 | public class ThreadRunner extends BlockJUnit4ClassRunner {
22 |
23 | private AtomicInteger numThreads;
24 |
25 | public static int maxThreads = 25;
26 |
27 | public ThreadRunner(Class> klass) throws InitializationError {
28 | super(klass);
29 | // TODO Auto-generated constructor stub
30 | numThreads = new AtomicInteger(0);
31 | }
32 |
33 | protected void runChild(final FrameworkMethod method, final RunNotifier notifier) {
34 | while(numThreads.get() > maxThreads){
35 | try{
36 | Thread.sleep(1000);
37 | }catch(InterruptedException e){
38 | e.printStackTrace();
39 | return;
40 | }
41 | }
42 |
43 | numThreads.incrementAndGet();
44 | new Thread(new Test(method, notifier)).start();
45 | }
46 |
47 | protected Statement childrenInvoker(final RunNotifier notifier){
48 | return new Statement(){
49 |
50 | @Override
51 | public void evaluate() throws Throwable {
52 | // TODO Auto-generated method stub
53 | ThreadRunner.super.childrenInvoker(notifier).evaluate();
54 | while(numThreads.get() > 0){
55 | Thread.sleep(1000);
56 | }
57 | }
58 |
59 | };
60 | }
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | class Test implements Runnable{
69 | private final FrameworkMethod method;
70 | private final RunNotifier notifier;
71 |
72 | public Test(FrameworkMethod method, RunNotifier notifier){
73 | this.method = method;
74 | this.notifier = notifier;
75 | }
76 |
77 |
78 | public void run() {
79 | ThreadRunner.super.runChild(method, notifier);
80 | // TODO Auto-generated method stub
81 | numThreads.decrementAndGet();
82 |
83 | }
84 |
85 | }
86 |
87 | }
88 |
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/userpool/JdbcUtil.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/target/test-classes/com/weibo/userpool/JdbcUtil.class
--------------------------------------------------------------------------------
/target/test-classes/com/weibo/userpool/JdbcUtil.java:
--------------------------------------------------------------------------------
1 | package com.weibo.userpool;
2 |
3 | import java.beans.PropertyVetoException;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 | import java.sql.Connection;
7 | import java.sql.ResultSet;
8 | import java.sql.SQLException;
9 | import java.sql.Statement;
10 | import java.util.Properties;
11 |
12 | import org.apache.commons.dbutils.DbUtils;
13 |
14 | import com.mchange.v2.c3p0.ComboPooledDataSource;
15 |
16 | /**
17 | *
18 | *
19 | * jdbc 使用C3PO连接池 获得Connection
20 | * @author hugang
21 | *
22 | */
23 | public class JdbcUtil {
24 | private static Properties enc;
25 | private static InputStream in;
26 | private static ComboPooledDataSource ds = new ComboPooledDataSource();
27 | static {
28 | try {
29 | enc = new Properties();
30 | in = JdbcUtil.class.getResourceAsStream("../../../c3p0.properties");
31 | enc.load(in);
32 | } catch (Exception e) {
33 | throw new ExceptionInInitializerError(e);
34 | }
35 | finally {
36 | try {
37 | in.close();
38 | } catch (IOException e) {
39 | // TODO Auto-generated catch block
40 | e.printStackTrace();
41 | }
42 | }
43 | }
44 |
45 | static {
46 | try {
47 | ds.setDriverClass(enc.getProperty("c3p0.driverClass"));
48 | } catch (PropertyVetoException e) {
49 | // TODO Auto-generated catch block
50 | e.printStackTrace();
51 | }
52 | ds.setUser(enc.getProperty("c3p0.user"));
53 | ds.setPassword(enc.getProperty("c3p0.password"));
54 | ds.setJdbcUrl(enc.getProperty("c3p0.jdbcUrl"));
55 | }
56 |
57 | public static Connection getConnection() {
58 |
59 | try {
60 |
61 | return ds.getConnection();
62 |
63 | } catch (SQLException e) {
64 | // TODO Auto-generated catch block
65 | e.printStackTrace();
66 | }
67 | return null;
68 | }
69 |
70 | public static void close(ResultSet rs, Statement st, Connection con) {
71 | DbUtils.closeQuietly(rs);
72 | DbUtils.closeQuietly(st);
73 | DbUtils.closeQuietly(con);
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/target/test-classes/global.properties:
--------------------------------------------------------------------------------
1 | # appkey
2 | source=
3 |
4 |
5 | # web server ip:port
6 | host=
7 | port=
8 |
9 | # run failed cases times(default value)
10 | retry=1
11 |
--------------------------------------------------------------------------------
/target/test-classes/log4j.properties:
--------------------------------------------------------------------------------
1 | log4j.rootLogger=debug
2 |
3 | log4j.logger.error=error,errorfile
4 | log4j.logger.info=debug,infofile
5 | log4j.logger.testlog=info,file
6 | log4j.logger.caselog=debug,casefile
7 |
8 | log4j.appender.casefile=org.apache.log4j.DailyRollingFileAppender
9 | log4j.appender.casefile.DatePattern='.'yyyyMMdd-HH
10 | log4j.appender.casefile.File=./logs/execute.log
11 | log4j.appender.casefile.Append=true
12 | log4j.appender.casefile.layout=org.apache.log4j.PatternLayout
13 | log4j.appender.casefile.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%p] %m%n
14 |
15 | log4j.appender.infofile=org.apache.log4j.DailyRollingFileAppender
16 | log4j.appender.infofile.DatePattern='.'yyyyMMdd-HH
17 | log4j.appender.infofile.File=./logs/info.log
18 | log4j.appender.infofile.Append=true
19 | log4j.appender.infofile.Threshold=DEBUG
20 | log4j.appender.infofile.layout=org.apache.log4j.PatternLayout
21 | log4j.appender.infofile.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%p] %m%n
22 |
23 | log4j.appender.errorfile=org.apache.log4j.DailyRollingFileAppender
24 | log4j.appender.errorfile.DatePattern='.'yyyyMMdd-HH
25 | log4j.appender.errorfile.File=./logs/error.log
26 | log4j.appender.errorfile.Append=true
27 | log4j.appender.errorfile.Threshold=ERROR
28 | log4j.appender.errorfile.layout=org.apache.log4j.PatternLayout
29 | log4j.appender.errorfile.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%p] %m%n
30 |
31 | log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
32 | log4j.appender.file.DatePattern='.'yyyyMMdd-HH
33 | log4j.appender.file.File=./logs/test.log
34 | log4j.appender.file.Append=true
35 | log4j.appender.file.Threshold=DEBUG
36 | log4j.appender.file.layout=org.apache.log4j.PatternLayout
37 | log4j.appender.file.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%p] %m%n
38 |
39 |
40 |
--------------------------------------------------------------------------------
/test-output/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neven7/WeTest/af1b3d35ed270d01a34656fc8dc9421e0590a5ad/test-output/.DS_Store
--------------------------------------------------------------------------------