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:xmlplainbrief 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

1 0