2011-08-26 26 views
10

我想在备份测试夹具之前备份我的应用程序的数据库。由于Android的限制,我不得不使用Junit3,并且我想实现@BeforeClass和@AfterClass的等效行为。如何在Junit3中获得@BeforeClass和@AfterClass等效项?

更新:现在有一个工具(Junit4Android)在Android上获得对 Junit4的支持。这是一个混乱,但应该工作。

为了实现@BeforeClass等同,我一直在使用一个静态变量,像这样在第一次运行时初始化它,但我需要能够运行所有测试后恢复数据库。我无法想象的,当最后的测试已经运行检测的方式

public class MyTest extends ActivityInstrumentationTestCase2<MainActivity> { 
    private static boolean firstRun = true; 

    @Override 
    protected void setUp() { 
     if(firstRun) { 
      firstRun = false; 
      setUpDatabaseFixture(); 
     } 
    } 
    ... 
} 
+0

但在你的情况下测试将视对方,并在某些特定状态将被期待数据库意味着它们不是真正的单元测试。你应该是一个模拟数据库。 –

+1

这些都是验收测试,而且绝大多数不是单元测试。这些完全集成在平台上,由Android工具Robotium驱动。 –

+0

另请参见http://stackoverflow.com/questions/3023091/does-junit-3-have-something-analogous-to-beforeclass – Vadzim

回答

8

junit website(因为我相信这是测试执行的顺序没有保证。):

包裹套件中的setUp和tearDown方法。如果您想运行单个YourTestClass测试用例,则这是针对 的情况。

public static Test suite() { 
    return new TestSetup(new TestSuite(YourTestClass.class)) { 

     protected void setUp() throws Exception { 
      System.out.println(" Global setUp "); 
     } 
     protected void tearDown() throws Exception { 
      System.out.println(" Global tearDown "); 
     } 
    }; 
} 

如果您想为所有的测试用例 只运行一个安装和拆卸,使一套房,并添加TestClass中给它,并通过在TestSetup constructor.But套房 对象我想有这并没有太大的用处 ,并以某种方式违反了JUnit哲学。

+0

请注意TestSetup似乎在'junit.extensions.TestSetup' –

+3

@PeterAjtai和Nicholas ,尽管这可以在其他平台上工作,Android [不包括支持](http://stackoverflow.com/q/10691737/403455)适用于'junit.extensions.TestSetup'。 –

+0

你在ANdroid上运行这段代码吗?你能不能与我分享完整的代码?我正在努力实施Global setUp/tearDown .. –

1

最近,我也在寻找类似的解决方案。幸运的是,在我的情况下,JVM在最后一次测试运行后退出。所以我可以通过添加JVM关闭挂钩来实现这一点。

// Restore database after running all tests 
Runtime.getRuntime().addShutdownHook(new Thread() { 
    public void run() { 
     restoreDatabase(); 
    } 
}); 

希望这有助于。

+0

+1好主意。可能需要小心这个,虽然... –

0

我建议避免这种类型的依赖关系,您需要知道测试运行的顺序。如果您只需要恢复被setUpDatabaseFixture()取代的真实数据库,那么您的解决方案可能来自使用RenamingDelegatingContext。无论如何,如果你不能避免知道最后的测试运行时,您可以使用这样的事情:

... 

private static final int NUMBER_OF_TESTS = 5; // count your tests here 
private static int sTestsRun = 0; 

... 

protected void tearDown() throws Exception { 
    super.tearDown(); 
    sTestsRun += countTestCases(); 

    if (sTestsRun >= NUMBER_OF_TESTS) { 
     android.util.Log.d("tearDow", "*** Last test run ***"); 
    } 
} 
1

这不是(与数据处理优雅,所以你不必担心恢复它)testing with mock objects是为了什么? Android supports mocking

我问一个问题,因为我从来没有嘲笑过Android。


在我的经验,并从this blog post,当Android的测试制作成一套,并由InstrumentationTestRunner运行 - ActivityInstrumentationTestCase2ActivityTestCase的延伸范围的InstrumentationTestCase的extendsion - 它们使用android.test.suitebuilder.TestGrouping.SORT_BY_FULLY_QUALIFIED_NAME按字母顺序排列,所以你可以用你的测试名称中字母低的方法恢复你的DB,例如:

// underscore is low in the alphabet 
public void test___________Restore() { 
    ... 
} 

注:

你必须要注意继承的测试,因为他们不会在这个顺序运行。解决方案是覆盖所有继承的测试,只需从覆盖中调用super()。这将再一次按字母顺序执行。

例子:

// Reusable class w only one time setup and finish. 
// Abstract so it is not run by itself. 
public abstract class Parent extends InstrumentationTestCase { 
    @LargeTest 
    public void test_001_Setup() { ... } 

    @LargeTest 
    public void test_____Finish() { ... } 
} 

/*-----------------------------------------------------------------------------*/ 

// These will run in order shown due to naming. 
// Inherited tests would not run in order shown w/o the use of overrides & supers 
public class Child extends Parent { 
    @LargeTest 
    public void test_001_Setup() { super.test_001_Setup(); } 

    @SmallTest 
    public void test_002_MainViewIsVisible() { ... } 

    ... 

    @LargeTest 
    public void test_____Finish() { super.test_____Finish(); } 
} 
+0

谢谢,但这是验收测试,而不是单元测试。我已经使用PowerMock + Mockito创建了用于在主机上运行快速单元测试的模拟。 –

+0

@glen - 噢好吧,这很有道理。我认为Android测试是按字母顺序运行的,所以你可以创建一个testZZZZZ()来恢复一切。从http://blogprogramistyandroid.blogspot.com/2011/02/randomizing-order-of-tests.html android.test.suitebuilder.TestGrouping.SORT_BY_FULLY_QUALIFIED_NAME –

相关问题