I want to test that when I receive push, Notification will be showing up. And it might be as well to check its properties (like title, set intent and so on.)
How can I do so?
#Before
public void setupTest() {
mData.putString(PushNotificator.KEY_PUSH_TYPE, PushType.PROJECT_OFFER.toString());
mData.putString(PushNotificator.KEY_PUSH_OBJECT, pushObjectJsonString);
mContext = InstrumentationRegistry.getContext();
}
#Test
public void projectOfferCreatedFromBundle() {
mPushNotificator = new PushNotificator(mContext);
mPushNotificator.processPush(mData);
onView(withText("111")).check(matches(withText("111"))); //how to find notification?
}
Espresso UI test framework doesn't see more than actual View. I doubt seriously that you can check any notification with Espresso.
For this purpose use another Googles testing framework uiautomator, which is described as:
UI Automator is a UI testing framework suitable for cross-app functional UI testing across system and installed apps.
Here you would find how to use it with Espresso: http://qathread.blogspot.com/2015/05/espresso-uiautomator-perfect-tandem.html
More information:
Documentation(I):
https://google.github.io/android-testing-support-library/docs/uiautomator/index.html
Documentation(II):
http://developer.android.com/intl/es/training/testing/ui-testing/uiautomator-testing.html
Visit also: Android Testing: UIAutomator vs Espresso
Related
I have Android instrumentation tests with Espresso. Some of my tests must be run on an emulator - due to using LinkedIn's TestButler (https://github.com/linkedin/test-butler) library. This library toggles wifi/gsm for specific test runs, and that is why these tests must be run on an emulator.
My question is - can I annotate any specific tests to run on an emulator, while having the other tests run on a real device?
Thanks
Yes, you can use a #ConditionalIgnore annotation as described in http://www.codeaffine.com/2013/11/18/a-junit-rule-to-conditionally-ignore-tests/.
You will have something like
public class SomeTest {
#Rule
public ConditionalIgnoreRule rule = new ConditionalIgnoreRule();
#Test
#ConditionalIgnore( condition = NotRunningOnEmulator.class )
public void testSomething() {
// ...
}
}
public class NotRunningOnEmulator implements IgnoreCondition {
public boolean isSatisfied() {
return !Build.PRODUCT.startsWith("sdk_google");
}
}
EDIT
For this specific case of detecting a device or emulator you can also use #RequiresDevice.
The most straightforward solution I found is to use JUnit Assume API: http://junit.org/junit4/javadoc/4.12/org/junit/Assume.html
So, inside the test methods that can only be run on an emulator, I put this code:
Assume.assumeTrue("This test must be run in an emulator!", Build.PRODUCT.startsWith("sdk_google"));
This results in the said test being ignored when it isn't run on an emulator, and a handy error msg in the run window:
As you can see, the other two tests passed fine (in the green), and the entire test suite was able to run.
I searched this question but didn't find answers.
Suppose there is a system app, which is installed together with android system, e.g. Dialer app.
Now I want to unit-test or instrumentation-test this app. I don't want to use AOSP Android.mk. Are there alternative ways? e.g. Can I create a gradle project to test it?
For instrumentation tests I personally create an independent app that consumes uiautomator: https://developer.android.com/topic/libraries/testing-support-library/index.html#UIAutomator
This allows simulation of a user:
#org.junit.Test
public void testCheckContact() throws InterruptedException {
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
assertThat(device, notNullValue());
device.pressHome();
Context context = InstrumentationRegistry.getInstrumentation().getContext();
Intent intent = context.getPackageManager().getLaunchIntentForPackage("systempackageName");
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intent);
...
...
PhoneActivityPage phoneActivityPage = new PhoneActivityPage();
phoneActivityPage.clickContacts();
assertEquals("Contacts", phoneActivityPage.getSelectedTab());
}
Where you can define PhoneActivityPage and the interface in a separate class within this independent test project.
I hope this helps.
You can use the UiAutomator system to test arbitrary apps, including system ones. However, the inputs and outputs are somewhat limited.
I'm trying to carry out junit test for the Android-DDP library.
To initialize the meteor object, we need a reference to a android context which I'm able to achieve using Robolectric. But the web-sockets is probably talking to the server on a different thread because of which the callback methods are not called and the test methods are getting end.
I used netstat to check if the android client is trying to communicate or not. It shows various ping/pong messages. So, Yes it is trying to talk to the server.
I went through this tutorial as well,
Android AsyncTask testing with Android Test Framework. This one tells how to handle the network on UI thread. But nothing seems right.
The sample code, I have worked is:
#Config(constants = BuildConfig.class, sdk = Build.VERSION_CODES.LOLLIPOP)
#RunWith(RobolectricGradleTestRunner.class)
public class MainActivityTest {
private MainActivity activity;
private Meteor meteor;
private String globalUrl = "ws://10.0.3.222:3000/websocket";
#Before
public void setup() {
activity = Robolectric.setupActivity(MainActivity.class);
meteor = new Meteor(activity, globalUrl);
meteor.reconnect();
/*
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
*/
}
#Test
public void validateMeteorIsConnected() {
assertTrue(meteor.isConnected());
}
}
Any help would be appreciable. Thanks in advance.
You defined two methods, setup() and validateMeteorIsConnected(), but where are they called?
First, your setup is not correct. After your call to new Meteor(...), you don't need the reconnect() call because the constructor does already establish the connection.
Moreover, you must set up a listener so that you know when the connection has been established or data comes in. This is done with mMeteor.setCallback(...); where the parameter is this or activity.
As you said, the work is done on a different thread and everything is asynchronous.
So you can't just call validateMeteorIsConnected() immediately after connecting.
You need some timer, as shown in the question that you linked to.
Has anyone used Ranorex to test Forms UI's? I don't see any UI id properties that I could set from the View/Element class so I was wondering if I can set automation id's through the Forms objects. One option would be to wrap all Forms views around custom renderers and expose an ID field but that isn't an ideal solution for obvious reasons.
For iOS the method that works for Xamarin Cloud also works well with Ranorex. It doesn't work on Android though so that is still an open issue.
http://developer.xamarin.com/guides/cross-platform/xamarin-forms/uitest-and-test-cloud/
Forms.ViewInitialized += (object sender, ViewInitializedEventArgs e) => {
// http://developer.xamarin.com/recipes/testcloud/set-accessibilityidentifier-ios/
if (!string.IsNullOrWhiteSpace(e.View.StyleId)) {
e.NativeView.AccessibilityIdentifier = e.View.StyleId;
}
};
after each test execution junit goes to the next test. And activity closes automatically after each test execution.
Its OK when I test functions, but NOT OK when I test views. I want to see execution results on the screen before junit will execute next test.
So, I want to make small delay between tests.
There is one way I can do it:
public void testMyView() throws InterruptedException {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
// viewOperations...
}
});
Thread.sleep(3000);
}
But I dont like this way because this code is dirty (especially when I have a lot of such tests).
Another way seems much better:
#UiThreadTest
public void testHandleEmptyAlphabetList() throws InterruptedException {
// view operations
Thread.sleep(3000);
}
BUT: It will block UI thread but NOT test thread. I need to block a test thread.
Is there any way to run Thread.sleep(3000); from this code separately in a test thread?
So, what is the best way to make thread delays between tests?
p.s. Please don't recommend me additional test frameworks, I want to solve my problem using embed tools. Thank you.
I suggest ditching this cumbersome way of unit testing and using Robolectric, so your tests run in the JVM and you don't have to deal with all this nasty setup. You'll be pleasantly surprised on how quickly your View testing runs, and that you don't need to run an emulator!
Try to use Robotium for the tests that need a real android running.
solo = new Solo(getInstrumentation(), getActivity());
[...]
if (failure) {
solo.takeScreenshot();
}
This will save a screenshot to your SD card (needs WRITE_EXTERNAL_STORAGE permission)
Or if you prefer not to use another testing framework (though I would recommend you take a look at it), just steal the code that is used there for taking screenshots