Tin's Blog

          You are coming a long way, baby~Thinking, feeling, memory...

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            128 隨筆 :: 0 文章 :: 221 評論 :: 0 Trackbacks
          這個問題出現在這種情況,你的每個testCase都需要使用某一種初始化比較耗時的對象(資源),舉例如數據庫連接、Spring Context。我們遇到的問題是Selenium測試中開啟和關閉瀏覽器,如果一個test啟動關閉(我們的程序還需要登錄和注銷),這樣測試的時間會拖的很長,給持續集成帶來了困難。
          所以,我們需要在每組不會沖突的test中間共享一個瀏覽器窗口,這樣也就需要一個全局的setUp和tearDown。問題是JUnit 3.8.1里面的setUp和tearDown是在每個test之前和之后運行的,如果在里面初始化和關閉瀏覽器就會造成上面所說的問題。要解決它,就產生了如下3種思路:
          1、升級,使用JUnit4
          JUnit4從TestNG里面吸取了兩個注釋:@BeforeClass和@AfterClass
          用它們注釋過的方法就會只初始化一次,完全符合我們的需求。
          public?class?SeleniumTestCase?extends?SeleneseTestCase4?{

          ????
          protected?static?final?Log?log?=?LogFactory.getLog(SeleniumTestCase.class);
          ????
          protected?static?Selenium?selenium?=?null;

          ????
          /**
          ?????*?包含了登錄的代碼,保證在一個測試內部只執行一次開啟瀏覽器并登錄操作
          ?????*?
          @throws?Exception
          ?????
          */

          ????@BeforeClass
          ????
          public?static?void?startSelenium()?throws?Exception?{
          ????????log.debug(
          "Starting?Selenium");
          ????????selenium?
          =?SeleniumSession.getCurrentSession().getSelenium();
          ????}


          ????
          /**
          ?????*?在該類包含的所有測試結束之后關閉瀏覽器
          ?????*?
          @throws?Exception
          ?????
          */

          ????@AfterClass
          ????
          public?static?void?stopSelenium()?throws?Exception?{
          ????????log.debug(
          "Stoping?Selenium");
          ????????selenium.stop();
          ????}

          }
          這個里面的selenium = SeleniumSession.getCurrentSession().getSelenium();其實是個singleton,第一次open new,后來就直接返回selenium的instance(具體參考其它文章)。
          這樣做非常舒服,因為完全不是Trick,而是新的feature,用起來踏實。這樣,這個類的所有@Test就會公用一個selenium打開的瀏覽器了。
          那么缺點是什么呢?缺點是放到CI環境的時候如果使用我們習慣的Ant寫執行腳本的話必須將Ant升級到1.7Beta3,因為Ant 1.6.5的Junit task不支持JUnit4……當然升級并不會帶來代碼的變化,但是問題在于Ant 1.7還是Beta,而且JUnit4需要JDK5的Annotation,你的PM估計要撇嘴了

          2、JVM級別鉤子法
          因為JVM支持關閉時執行制定代碼的鉤子,而static代碼會在類初始化時執行,再加上Ant調用的是類似命令行的java命令,實際上每一個測試運行在一個完整的JVM啟動關閉周期里面,所以也就產生了這種解決方案。
          這個方案來自taowen同學的兩則Selenium經驗
          代碼我恢復了一下,大概是這樣:
          public?abstract?class?SomeTestCase?extends?TestCase?{

          ??
          static?{
          ????
          //?perform?the?"global"?set?up?logic
          ????
          //這里的代碼會在類初始化時執行,所以相當于BeforeClass
          ????log.debug("Starting?Selenium");
          ????????selenium?
          =?SeleniumSession.getCurrentSession().getSelenium();

          ????
          //?and?now?register?the?shutdown?hook?for?tear?down?logic
          ????
          //將一個匿名方法寫到這里,就相當于AfterClass
          ????Runtime.getRuntime().addShutdownHook(
          ??????
          new?Thread(){
          ??????????
          public?void?run()?{
          ???????????? log.debug(
          "Stoping?Selenium");
          ???????????? selenium.stop();
          ?????????? }
          ?????? }
          ???? );
          ??}

          }

          這個方法挺酷的,我認為完全可以被稱作“奇技淫巧”。缺點就是,有點不好看。

          3、還有別的方法,這個來自Selenium網站,似乎是不錯的中庸方案。
          import?junit.framework.*;
          import?junit.extensions.TestSetup;

          public?class?AllTestsOneTimeSetup?{

          ????
          public?static?Test?suite()?{

          ????????TestSuite?suite?
          =?new?TestSuite();

          ????????suite.addTest(SomeTest.suite());
          ????????suite.addTest(AnotherTest.suite());

          ????????TestSetup?wrapper?
          =?new?TestSetup(suite)?{

          ????????????
          protected?void?setUp()?{
          ????????????????oneTimeSetUp();
          ????????????}

          ????????????
          protected?void?tearDown()?{
          ????????????????oneTimeTearDown();
          ????????????}
          ????????};

          ????????
          return?wrapper;
          ????}

          ????
          public?static?void?oneTimeSetUp()?{
          ????????
          //?one-time?initialization?code
          ????}

          ????
          public?static?void?oneTimeTearDown()?{
          ????????
          //?one-time?cleanup?code
          ????}
          }


          這個好像是比較正統的方案,不好意思我并沒有試驗,但是看起來這的確可能是限定用JDK 1.4或JUnit 3.8.1的最佳解決方案。歡迎嘗試。相關的連接參考這里:http://www.cs.wm.edu/~noonan/junit/doc/faq/faq.htm#organize_3?

          posted on 2006-11-17 17:29 Tin 閱讀(13553) 評論(1)  編輯  收藏 所屬分類: 開源

          評論

          # re: 在JUnit中多個testCase只執行一次setup和tearDown的方法 2006-11-28 16:58 coolfish
          我前兩天也恰好遇到這樣的問題,竟然以前不知道setUp() 和 tearDown()對每個test*方法運行一次.汗. 我是用類似第三種解決方法,手工寫靜態的suite()方法組織testcase  回復  更多評論
            

          主站蜘蛛池模板: 北川| 两当县| 建湖县| 来宾市| 赣州市| 宜川县| 开原市| 上饶县| 星座| 泗阳县| 巴彦县| 黄冈市| 樟树市| 柘城县| 扬中市| 林甸县| 苏尼特左旗| 东源县| 潢川县| 揭西县| 庆元县| 塔城市| 洞口县| 五台县| 乌兰县| 马鞍山市| 卓资县| 汝州市| 东阳市| 阳江市| 固安县| 蒙城县| 册亨县| 隆化县| 长泰县| 芜湖县| 建始县| 松潘县| 汝城县| 开远市| 会宁县|