0

I am stuck and will be glad to get any help!

I am writing tests for an android library. The task is to make some actions in an activity and check that library responds correctly. My problem is that my test finishes just after all actions in activity are done but I get the test result via a callback (and I receive this callback only when the test is over). So, I want to somehow tell testing framework that the test is not over until the callback is received (or until time runs out). Here is what I have now:

@Test
public void testSimpleSetup() {

    /* ... */

    InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
        @Override
        public void run() {
            testManager.startTest(MAX_WAIT_TIME); // this object calls onTestResult(boolean) after time t (t <= MAX_WAIT_TIME)

            /* working with activity here */
        }
    });
    InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}

@Override
public void onTestResult(boolean passed) {
    // assertTrue(passed);
    Assert.fail();
}

I expect this test to fail but in fact onTestResult is called after testSimpleSetup finishes and Assert has no influence on the result of the test.

Thanks in advance.

antonpp
  • 2,333
  • 23
  • 28

2 Answers2

2

Check this post. I modified a bit the code, since I read the following:

As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:

Object mon = new Object(); //reference in your Activity
boolean testOnGoing = true;
/*...*/

InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
        @Override
        public void run() {
           synchronized (mon) {
           testManager.startTest(MAX_WAIT_TIME); 
           /* working with activity here */
           while(testOnGoing)
              mon.wait();
           } 
        }
});

InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}

@Override
public void onTestResult(boolean passed) {
synchronized (mon) {    
    //assertTrue(passed);
    Assert.fail();
    testOnGoing = false;
    mon.notify();
   } 
}
Community
  • 1
  • 1
Gordak
  • 2,060
  • 22
  • 32
  • this will deadlock if onTestResult() is called "to early" which might happen due to Thead-sheduling. Therefore I prefer using a CountDownLatch – qwerty May 26 '15 at 18:50
2

Thanks to @Gordak. His answer has almost worked. But, unfortunately, it blocks the main thread so the test never ends. I modified it a little bit so now it works.

@Before
public void setUp() throws Exception {
    activity = testRule.getActivity();
    latch = new CountDownLatch(1);
}

@Test
public void testSimpleSetup() {

    /* ... */

    InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
        @Override
        public void run() {
            testManager.startTest(MAX_WAIT_TIME); // this object calls onTestResult(boolean) after time t (t <= MAX_WAIT_TIME)

            /* working with activity here */
        }
    });
    InstrumentationRegistry.getInstrumentation().waitForIdleSync();

    latch.await(); // here we block test thread and not UI-thread
                   // presumably, you will want to set the timeout here
}

@Override
public void onTestResult(boolean passed) {
    // assertTrue(passed);
    Assert.fail();
    latch.countDown();
}
antonpp
  • 2,333
  • 23
  • 28