• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • JUnit源碼解析(4)

    發表于:2016-10-04來源:saymagic作者:saymagic點擊數: 標簽:junit
    return befores.isEmpty() ? statement : new RunBefores(statement, befores, target); } 這個函數里首先拿到了所有被@Before標注的方法,將其封裝為RunBefores,我們看下其構造函數
            return befores.isEmpty() ? statement : new RunBefores(statement,
                    befores, target);
    }
    這個函數里首先拿到了所有被@Before標注的方法,將其封裝為RunBefores,我們看下其構造函數和
     
    public RunBefores(Statement next, List<FrameworkMethod> befores, Object target) {
            this.next = next;
            this.befores = befores;
            this.target = target;
    }
    public void evaluate() throws Throwable {
           for (FrameworkMethod before : befores) {
                before.invokeExplosively(target);
           }
           next.evaluate();
    }
    很是明了,evaluate執行時,首先將before方法全部invoke來執行,然后才調用原始statement的evaluate方法。其余幾個函數與此類似,感興趣可以繼續查看。
     
    如此,我們就明白了runLeaf方法的第一個參數Statement的由來,接下來就看下這個runLeaf方法做了什么,runLeaf在ParentRunner中有默認的實現:
     
     protected final void runLeaf(Statement statement, Description description,
                RunNotifier notifier) {
            EachTestNotifier eachNotifier = new EachTestNotifier(notifier, description);
            eachNotifier.fireTestStarted();
            try {
                statement.evaluate();
            } catch (AssumptionViolatedException e) {
                eachNotifier.addFailedAssumption(e);
            } catch (Throwable e) {
                eachNotifier.addFailure(e);
            } finally {
                eachNotifier.fireTestFinished();
            }
    }
    非常簡單,直接執行了statement的evaluate方法,需要注意的是這里的statement實例不一定是什么了,有可能是RunBefores,也有可能是RunAfters,這就和被測試類中的注解有關了。
     
    講到這里,還記得前面我們說過的存檔A嗎?我們回到存檔A:
     
    protected Statement classBlock(final RunNotifier notifier) {
         Statement statement = childrenInvoker(notifier);
         if (!areAllChildrenIgnored()) {
             statement = withBeforeClasses(statement);
             statement = withAfterClasses(statement);
             statement = withClassRules(statement);
         }
         return statement;
    }
    剛剛存檔后所發生的一起,其實就是在執行Statement statement = childrenInvoker(notifier)這個代碼。換句話說,childrenInvoker的作用就是將所有需要執行的測試用例用一個Statement封裝起來。進而點燃這個Statement,就會觸發所有的測試用例。但同樣需要注意到被if語句包圍的代碼,我們又看到了熟悉的語句,Statement還在被不斷的轉換,但此時是在類的層面,withBeforeClasses函數操作的就是@BeforeClass注解了:
     
    protected Statement withBeforeClasses(Statement statement) {
            List<FrameworkMethod> befores = testClass
                    .getAnnotatedMethods(BeforeClass.class);
            return befores.isEmpty() ? statement :
                    new RunBefores(statement, befores, null);
    }
    需要注意的是這回RunBefores的第三個參數為null,說明被@BeforeClass注解的方法只能是static的。
     
    如上,我們分析了BlockJUnit4ClassRunner的運行流程,也就是說當測試類為一個的時候JUnit是如何工作的。前文也提到過,ParentRunner還有一個子類Suite,表示需要運行一組測試,BlockJUnit4ClassRunner的一個運行單元為FrameworkMethod,而Suite的一個運行單元為Runner,我們看其runChild方法:
     
    protected void runChild(Runner runner, final RunNotifier notifier) {

    原文轉自:http://blog.saymagic.cn/2016/09/30/understand-Junit.html

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>