換種順序來執行TestCase(Junit適用)

Junit的TestCase,總是按固定的順序執行的. 正如你在Eclipse中跑Run As Junit Test, 無論你跑多少次, TestCase的執行順序都是一致的,可重複的. 這就導致一個問題, TestCase之間的獨立性無法保證.

例如下面一個Test類中的2個TestCase:

public class DaoTest {

    @Test
    public void test_count() {
        dao.insert(new User("root", "123456"));
        assertEquals(1, dao.count(User.class));
    }

    @Test
    public void test_insert() {
        dao.clear(User.class, null);
        dao.insert(new User("admin", "123456"));
        assertEquals(1, dao.count(User.class));
    }

}

如果先執行test_count()然後執行test_insert(),兩個TestCase都能通過.

但如果先執行test_insert(),然後執行test_count(),則test_count()會失敗.

所以,有必要去打亂TestCase的默認執行順序,以暴露出TestCase本身的問題. TestCase更可靠,才能讓主代碼更可靠.

我實現了一個簡單的方式,使用的是Junit的公開API, 測試過4.3和4.8.2,均可使用:

  //得到所有帶@Test的方法,這裏用的是Nutz的資源掃描,反正你能得到全部Test類就行
        List<Class> list = Scans.me().scanPackage("org.nutz");
        List<request> reqs = new ArrayList<request>();
        Map<Request, Method> reqMap = new HashMap<Request, Method>();
        for (Class clazz : list) {
            Method[] methods = clazz.getMethods();
            for (Method method : methods) {
                if (method.getAnnotation(Test.class) != null) {
                    //將單個TestCase(即一個Test Method),封裝爲Junit的Test Request
                    Request req = Request.method(clazz, method.getName());
                    reqs.add(req);
                    reqMap.put(req , method);//在最終打印測試結果時,方便查找具體出錯的Method
                }
            }
        }

        // 因爲reqs 是一個List,我們可以按需調整TestCase的順序
        // 正序 //nothing change.
        // 反序Collections.reverse(reqs)
        // 亂序Collections.shuffle(reqs)

        //把執行順序保存下來,方便重現執行順序
        try {
            FileWriter fw = new FileWriter("./test_order.txt");
            for (Request request : reqs) {
                fw.write(reqMap.get(request).toString());
                fw.write("\n");
            }
            fw.flush();
            fw.close();
        }
        catch (IOException e) {}

        //到這裏, List已經按我們預期的方式排好,可以執行測試了
        final TestResult result = new TestResult();
        RunNotifier notifier = new RunNotifier();
        notifier.addListener(new RunListener() { //需要設置一個RunListener,以便收集測試結果

            public void testFailure(Failure failure) throws Exception {
                result.addError(asTest(failure.getDescription()), failure.getException());
            }
            public void testFinished(Description description) throws Exception {
                result.endTest(asTest(description));
            }
            public void testStarted(Description description) throws Exception {
                result.startTest(asTest(description));
            }

            public junit.framework.Test asTest(Description description) {
                return new junit.framework.Test() {

                    public void run(TestResult result) {
                        throw Lang.noImplement();
                    }

                    public int countTestCases() {
                        return 1;
                    }
                };
            }
        });
        //來吧,執行之!!
        for (Request request : reqs) {
            request.getRunner().run(notifier);
        }

        //接下來,就是打印結果了.
        System.out.printf("Run %d , Fail %d , Error %d \n", result.runCount(), result.failureCount(), result.errorCount());

        if (result.failureCount() > 0) { //斷言失敗的TestCase
            Enumeration<testfailure> enu = result.failures();
            while (enu.hasMoreElements()) {
                TestFailure testFailure = (TestFailure) enu.nextElement();
                System.out.println("--Fail------------------------------------------------");
                System.out.println(testFailure.trace());
                testFailure.thrownException().printStackTrace(System.out);
            }
        }

        if (result.errorCount() > 0) { //拋異常的TestCase
            Enumeration<testfailure> enu = result.errors();
            while (enu.hasMoreElements()) {
                TestFailure testFailure = (TestFailure) enu.nextElement();
                System.out.println("--ERROR------------------------------------------------");
                System.out.println(testFailure.trace());
                testFailure.thrownException().printStackTrace(System.out);
            }
        }

來, 考驗一下你的TestCase吧!! 讓它在亂序中多次執行. Nutz按這種思路,已經爆出幾個Bug(當然,我已經迅速fix了)

轉自:http://wendal.net/453.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章