JUnit4---实践一:运行指定类的某些测试方法
来源:互联网 发布:五十知天命 英文 编辑:程序博客网 时间:2024/05/16 19:45
一.需求(小组内接口自动化由junit4+重试[用例]+HttpClient[调接口,获取数据]+多线程[执行用例]+数据库连接池[测试账号]组成,由ant生成junit报告)
最近,小组内有人提出了,是否能单独运行某些失败的cases,因为在eclipse中只能运行一个类的全部cases或某个cases; 不能指定跑单个类某些方法或多个类的某些方法。juint4中有@RunWith(Suite.class) 和 @Suite.SuiteClasses({A.class, B.class}) 聚合类A和B;但是不能指定某些方法。
在Ant执行Junit中有个formatter(结果的类型type:xml
, plain
, brief
or failure
),其中type=failure, collects all failing testXXX()
methods and creates a new TestCase
which delegates only these failing methods. 我尝试了,执行ant ***.xml报错为substring空指针,查看源码FailureRecorder.java; 该文件就是用来创建新的测试类(聚合失败cases),但是用Junit3(继承TestCase),并有bug,不能用:
public static class TestInfos implements Comparable {private final String className;private final String methodName;public TestInfos(Test test) {this.className = test.getClass().getName();String _methodName = test.toString();this.methodName = _methodName.substring(0, _methodName.indexOf(40));} ...}
TestInfos带参构造函数TestInfos(Test test)中
_methodName.substring(0, _methodName.indexOf(40)) // ( 的 ASCII码:40
_methodName并没有‘(’导致空指针。
二.方案
使用注解
@SuiteClassesMethods;指定
Class<?>[] className 类名
int[] methodsNumPerClass(); 每个类对应的方法数量
String[] methodsName() 方法名
实现代码如下:
SuiteClassesMethods.java
package com.weibo.failmethods;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)@Target({java.lang.annotation.ElementType.TYPE})public @interface SuiteClassesMethods { public Class<?>[] className(); public int[] methodsNumPerClass(); public String[] methodsName();}
FailMethodsTest.java
package com.weibo.failmethods;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.util.ArrayList;import java.util.LinkedHashMap;import java.util.List;import java.util.Map;import org.junit.runner.JUnitCore;import org.junit.runner.Request;import org.junit.runner.Result;import com.weibo.cases.hugang.AccountUpdatePrivacyCommentTest;import com.weibo.cases.hugang.AttitudeRemindTest;/** * @author hugang */@SuiteClassesMethods(className = { AccountUpdatePrivacyCommentTest.class, AttitudeRemindTest.class }, methodsNumPerClass = { 2, 1 }, methodsName = { "testAllNonAttentionByComment", "testFriendAllAttByComment", "testAttitudeSomeOneQunStatusPushCount2" })public class FailMethodsTest { public static void main(String[] args) throws Exception { Class<FailMethodsTest> clazz = FailMethodsTest.class; SuiteClassesMethods scm = clazz.getAnnotation(SuiteClassesMethods.class); Class<?>[] className = scm.className(); int[] methodsNumPerClass = scm.methodsNumPerClass(); String[] methodsName = scm.methodsName(); // 根据注解 传的方法,与每个测试类对应 Map<Class<?>, List<String>> myClassMethodMap = new LinkedHashMap(); List<List<String>> listMethodsName = new ArrayList<List<String>>(); // k游标,遍历methodsName int k = 0; // 外层for循环,表示类个数 for (int i = 0; i < className.length; i++) { List<String> temp = new ArrayList<String>(); // 内层for循环,为每个类赋方法 for (int m = 0; m < methodsNumPerClass[i]; m++) { temp.add(methodsName[k]); k++; } listMethodsName.add(i, temp); myClassMethodMap.put(className[i], listMethodsName.get(i)); } JUnitCore junitRunner = new JUnitCore(); List<Result> methodsResult = new ArrayList<Result>(); // 运行测试方法 for(Map.Entry<Class<?>, List<String>> entry : myClassMethodMap.entrySet()){ Class testClass = entry.getKey(); List<String> failMethod = entry.getValue(); for(int i = 0; i < failMethod.size(); i++){ Request request = Request.method(testClass, failMethod.get(i)); Result result = junitRunner.run(request); methodsResult.add(result); } } // 将错误集记录到file中 try{ File file = new File("/Users/hugang/Desktop/failMethod.txt"); FileOutputStream fop = new FileOutputStream(file); for(int j = 0; j < methodsResult.size(); j++){ byte[] fail = methodsResult.get(j).getFailures().toString().getBytes(); fop.write(fail); } fop.flush(); fop.close(); }catch(IOException e){ e.printStackTrace(); } }}
结果:
三.优化输出
由于之前输出结果不太明晰,修改FailMethodsTest.java
package com.weibo.failmethods;/** * @author hugang *///import java.io.File;//import java.io.FileOutputStream;//import java.io.IOException;import java.io.*;import java.text.SimpleDateFormat;import java.util.*;//import org.junit.runner.JUnitCore;//import org.junit.runner.Request;//import org.junit.runner.Result;import org.junit.runner.*;import com.weibo.cases.hugang.*;@SuiteClassesMethods(className = { AttitudeRemindTest.class }, methodsNumPerClass = { 1 }, methodsName = { "testAttitudeSomeOneQunStatusPushCount2" })public class FailMethodsTest { public static void main(String[] args) throws Exception { Class<FailMethodsTest> clazz = FailMethodsTest.class; SuiteClassesMethods scm = clazz.getAnnotation(SuiteClassesMethods.class); Class<?>[] className = scm.className(); int[] methodsNumPerClass = scm.methodsNumPerClass(); String[] methodsName = scm.methodsName(); // 根据注解 传的方法,与每个测试类对应 Map<Class<?>, List<String>> myClassMethodMap = new LinkedHashMap(); List<List<String>> listMethodsName = new ArrayList<List<String>>(); // k游标,遍历methodsName int k = 0; // 外层for循环,表示类个数 for (int i = 0; i < className.length; i++) { List<String> temp = new ArrayList<String>(); // 内层for循环,为每个类赋方法 for (int m = 0; m < methodsNumPerClass[i]; m++) { temp.add(methodsName[k]); k++; } listMethodsName.add(i, temp); myClassMethodMap.put(className[i], listMethodsName.get(i)); } JUnitCore junitRunner = new JUnitCore(); List<Result> methodsResult = new ArrayList<Result>(); // 失败数 int failNum = 0; // 成功数 int successNum = 0; // 运行时间 long runTime = 0L; // 运行测试方法 for(Map.Entry<Class<?>, List<String>> entry : myClassMethodMap.entrySet()){ Class testClass = entry.getKey(); List<String> failMethod = entry.getValue(); for(int i = 0; i < failMethod.size(); i++){ Request request = Request.method(testClass, failMethod.get(i)); Result result = junitRunner.run(request); runTime += result.getRunTime(); // 只添加失败的 if(result.wasSuccessful()){ successNum++; }else{ failNum++; methodsResult.add(result); } } } // for(int j = 0; j < methodsResult.size(); j++){// methodsResult.get(j).wasSuccessful();// methodsResult.get(j).getFailures().toString();// } // 将错误集记录到file中 try{ String filePath = System.getProperty("user.dir") + "/src/com/weibo/failmethods/failMethods.txt"; File file = new File(filePath); if(!file.exists()){ file.createNewFile(); } FileOutputStream fop = new FileOutputStream(file);SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss,SSS");fop.write("// Second Time Result generated on: ".getBytes());fop.write(sdf.format(new Date()).getBytes());fop.write("\n".getBytes());StringBuffer sb = new StringBuffer();sb.append("===================== 结果集 =====================");sb.append("\n");sb.append("用例总数:" + methodsName.length);sb.append(", 成功数:" + successNum);sb.append(", 失败数:" + failNum);sb.append(", 运行时间:" + (runTime/1000)/60 + " 分钟 " + (runTime/1000)%60 + " 秒");sb.append("\n");sb.append("=================================================");sb.append("\n");sb.append("\n");fop.write(sb.toString().getBytes());for(int j = 0; j < methodsResult.size(); j++){byte[] fail = methodsResult.get(j).getFailures().toString().getBytes(); fop.write(fail); fop.write("\n".getBytes()); fop.write("\n".getBytes()); } fop.flush(); fop.close(); }catch(IOException e){ e.printStackTrace(); } } }输出结果:有结果统计
参考:
junit wiki: http://junit.sourceforge.net/javadoc/overview-summary.html
- JUnit4---实践一:运行指定类的某些测试方法
- JUnit4---实践二:拓展之运行指定类的某些测试方法-自动生成该文件
- Junit4.x扩展:运行指定方法
- Junit指定运行的测试方法
- JUnit4:在测试用例中用FixMethodOrder指定测试方法的执行顺序
- JUnit4的测试类
- JUnit4的测试类
- JUnit4---实践三:支持多线程,失败重试执行测试case的方法
- junit4的测试方法的执行顺序
- JUnit4 测试带参数的方法
- JUnit4测试出错(一)
- Junit4:测试方法执行顺序
- Junit4测试Service中的方法
- Junit4+spring测试类
- SELinux阻止某些程序运行的处理方法
- 基于spring的Junit4测试
- Junit4测试套件的使用
- spring Boot测试的最佳实践和测试架构的启发(JUnit4和mockito,包括MockMvc)
- python返回函数/函数编程
- LVS+Keepalived实现高可用集群
- 无奈人心渐开明 贪嗔痴恨爱恶欲
- linux下github的搭建使用
- Python练手之6种经典排序算法
- JUnit4---实践一:运行指定类的某些测试方法
- hdu 1021 斐波那契2,找规律
- HDU2028 Lowest Common Multiple Plus【stein算法】【水题】
- 类似spring的AOP框架,动态获得代理类或目标类
- Git 分支创建与合并
- 使用Vitamio打造自己的Android万能播放器
- onethink 中在后台创建模型的时候 在字段里面添加的函数
- UVA 340-Master-Mind Hints(STL-map)
- ffmpeg scenecut