在JUnit中多個testCase只執行一次setup和tearDown的方法


http://tin.javaeye.com/blog/35114
這個問題出現在這種情況,你的每個testCase都需要使用某一種初始化比較耗時的對象(資源),舉例如數據庫連接、Spring Context。我們遇到的問題是Selenium測試中開啓和關閉瀏覽器,如果一個test啓動關閉(我們的程序還需要登錄和註銷),這樣測試的時間會 拖的很長,給持續集成帶來了困難。
所以,我們需要在每組不會衝突的test中間共享一個瀏覽器窗口,這樣也就需要一個全局的setUp和 tearDown。問題是JUnit 3.8.1裏面的setUp和tearDown是在每個test之前和之後運行的,如果在裏面初始化和關閉瀏覽器就會造成上面所說的問題。要解決它,就產 生了如下3種思路:
1、升級,使用JUnit4
JUnit4從TestNG裏面吸取了兩個註釋:@BeforeClass和@AfterClass
用它們註釋過的方法就會只初始化一次,完全符合我們的需求。
仍然有setUp/tearDown,標籤爲@Before/@After [winnerbao add ]

public   class  SeleniumTestCase [ extends  SeleneseTestCase4這個extends沒有必要 winnerbao add ] {

    
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

 
發佈了36 篇原創文章 · 獲贊 0 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章