Is black-box testing possible for Robotium Eclipse? - android

I started to learning about Android lately.
Now i'm trying to test some random Application with Robotium with Black-box testing method with no sources code or ID.
The app i tried to test:
https://play.google.com/store/apps/details?id=com.zing.zalo&hl=en
.
Just some simple function like: Open the app, login, log out.
I implented External Jar "robotium" in the JUnit test project, build path is checked with robotium and everything else.
I struggled with Pkg name, and activity name, then i saw some adb platform-toll "adb shell dumpsys activity" in the site below to get the name from my phone.
ADB - Android - Getting the name of the current activity
And many hours i read and searched from many sites this is the code i came up with:
public class LoginZalo extends ActivityInstrumentationTestCase2 {
public static Class LauncherActivityFullClass;
public Solo solo;
String pkg = "com.zing.zalo";
private static String launcher_activity_full_class = "/.ui.ZaloLauncherActivity";//login interface
static{
try {
LauncherActivityFullClass = Class.forName(launcher_activity_full_class);
} catch (Exception e) {
throw new RuntimeException();
}
}
public LoginZalo()
{
super(LauncherActivityFullClass);
}
protected void setUp() throws Exception {
solo = new Solo(getInstrumentation(),getActivity());
}
public void ZaloLogin()
{
solo.clickOnButton("LOGIN");
//also tried solo.clickOnButton(0); or solo.clickOnButton(1); or even clickOnText("LOGIN");
}
#Override
protected void tearDown() throws Exception {
// TODO Auto-generated method stub
solo.finishOpenedActivities();
}
}
AndroidManifest add target package.
<instrumentation
android:name="android.test.InstrumenttationTestRunner"
android:targetPackage="com.zing.zalo" />
But i only got a red error "Test run failed: No test results"in the console. I saw there is an comment on Robotium GitHub said Robotium can't do Black-box testing. I tried so many things from many site for many hours but getting nowhere. So i wonder, can Robotium Eclipse can do Black-box testing ? Maybe i did something wrong, because on Github site, they said Robotium can do black-box testing. Or i have to do it with Android Studio + Robotium Recorder ? Or maybe i should try something else like Appium ?

Related

Tell Espresso to run specific tests on an emulator

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.

Integration testing Android

I'm new to testing on Android. I see a lot of articles and tutorial about unit testing and with end-to-end testing (with espresso). It's ok. But what about integration testing ?
For the exemple, I use Firebase Database for my app. Is it possible to do this kind of test in the instrumentation test :
#Test
public void tryFirebaseTest() throws FieldRequiredException, InvalidPhoneException, InvalidEmailException, InterruptedException {
UserManager userManager = new UserManager(new FIRUserStorage(FirebaseDatabase.getInstance().getReference()));
userManager.createUser("test#test.com", "test", "+4778787", "", new CreateUserCallback() {
#Override
public void userCreated(User user) {
assertNotNull(user);
}
#Override
public void userExistError() {
fail();
}
#Override
public void userDatabaseError(String errorMessage) {
fail();
}
});
}
In this case, the test don't get in the callback.
For integration testing a Firebase app, you currently have two options:
Run local-firebase server, as discussed in this article, and write integration tests in jUnit/TestNG or whatever automation framework you like.
Write Espresso tests to test the complete integration
There are a few tools to help with the mocking like fingular, but you'll have to play with it a bit to see what kind of mileage you'll get out per your project and to what extent you integration test.

Reinstalling and resuming crawling of Android app

I'm currently implementing a UI crawler for hybrid Android apps (i.e., Android apps implemented using PhoneGap), and the crawler requires periodic restarts to generate a model of the UI. Here, by "restart", I mean uninstall the app, do a fresh install of the same app, and resume execution of the crawler. (The idea is to get to the same initial state as before. One could argue that I can just reload the initial HTML page, but this would only work if the app does not save and reuse any data like login information, etc. The data needs to be fresh - i.e., what it was when the app was installed for the first time).
I'm quite new to Android app development, so I decided to test out what is perhaps the most naive method possible. The test code I've written is shown below. The method testReinstall() runs as an Android JUnit test, and I'm using Robotium 4.3 to execute clicks and other events on the app.
package com.example.googleauthenticator.test;
import java.io.IOException;
import android.test.ActivityInstrumentationTestCase2;
import com.example.googleauthenticator.MainActivity;
import com.jayway.android.robotium.solo.By;
import com.jayway.android.robotium.solo.Solo;
public class ReinstallTest extends ActivityInstrumentationTestCase2<MainActivity> {
private Solo solo;
public ReinstallTest() {
super(MainActivity.class);
}
#Override
protected void setUp() throws Exception {
super.setUp();
solo = new Solo(getInstrumentation(), getActivity());
}
public void testReinstall() {
//Reinstall app
Runtime rt = Runtime.getRuntime();
Process pr;
try {
pr = rt.exec("adb uninstall com.example.googleauthenticator"); //Uninstall
pr.waitFor();
pr = rt.exec("adb install GoogleAuthenticator.apk"); //Install
pr.waitFor();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException ie) {
// TODO Auto-generated catch block
ie.printStackTrace();
}
System.out.println("Reinstall done!");
//Perform some action
if (solo.waitForWebElement(By.id("add"))) {
solo.clickOnWebElement(By.id("add"));
}
}
#Override
protected void tearDown() throws Exception{
solo.finishOpenedActivities();
super.tearDown();
}
}
I tried running the above code and it seems like it was able to successfully uninstall the app (or, at the very least, I know for a fact that the data/data/com.example.googleauthenticator folder was removed). However, the app does not get reinstalled (i.e., the data/data/com.example.googleauthenticator folder is still not there), and I presume this is related to the fact that by the time the first call to pr.waitFor() is reached, testReinstall() terminates due to a "Process crash", and the following message appears in the LogCat:
11-08 17:08:32.763: W/PluginManager(9285): Can't find plugin: com.example.googleauthenticator
What am I missing here? Is there a better/more correct way?
EDIT: To be clear, I'm also getting the following error message:
11-08 17:33:40.883: D/WebKit(14828): Unabled to create LocalStorage database path /data/data/com.example.googleauthenticator/app_database/localstorage
You cannot remove the application you are testing, infact exiting the application you are testing will mean that your test stops running this is because with instrumentation your test and your application are the same process.
Just because you cannot do what you want via robotium/instrumentation though does not mean what you want to do is impossible, you will just need to use an automation tool not based on instrumentation that runs off device, Calabash for example will automatically reinstall the application for you depending on if you use the correct annotation, this might be a better fit for what you want to do.

Android Junit Testing Freezes

I have an android app that I am unit testing. I have 4 test classes each with multiple test methods. I run them all at the same time from a test suite. I ran into a problem on the emulator where the test would just freeze in the middle of running the tests. I switched to using an actual device and the problem went away.
Fast forward a few weeks and I'm not having the same problem while running tests on my device. I have been on Google for the last couple days trying to find a solution but nothing I have found has helped.
The Issue
When I try to run all the tests the test will freeze eventually. And by freeze I mean the test itself freezes. I saw one solution that it might be the phone or eclipse. I restarted my phone, updated everything in eclipse including eclipse itself. I tried changing views to see if maybe the eclipse view was not refreshing but none of that helped. I also tried using the junit v4 library instead of v3.
If I run the test methods individually they all run and pass. Its only when I run them all from the test suite that they fail.
The Log
I checked the log and this is what I get:
03-13 12:11:04.526: I/TestRunner(23175): started: testCheckShowDialogEnabled(com.package.name.MainActivityTest)
after that there is nothing else in the log.
On The Device
The app is finished and is removed from the screen. It it not reopened again at the beginning of the next test.
The Code
Here is the code that I think might be relevant. If you need any more code just let me know.
public class AllTests extends TestSuite {
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTestSuite(MainActivityTest.class);
suite.addTestSuite(DatabaseHandlerTest.class);
suite.addTestSuite(ClassOneTest.class);
suite.addTestSuite(AnotherActivityTest.class);
return suite;
}
}
public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
public MainActivityTest() {
super("com.package.name", MainActivity.class);
}
#Override
public void setUp() throws Exception {
super.setUp();
mMainActivity = getActivity();
mSolo = new Solo(getInstrumentation(), mMainActivity);
}
#Override
protected void tearDown() throws Exception {
super.tearDown();
mMainActivity = null;
}
// all the test methods
}
All my test classes implement setup() and tearDown() similarly.
Anyone out there know why my tests keep freezing? Any help or suggestions are greatly appreciated.
#smk pointed me in the direction to find a solution to this. I just changed my tearDown() to this:
#Override
protected void tearDown() throws Exception {
mSolo.finishOpenActivities();
super.tearDown();
}
Now it works great!

Android test annotations with Robotium

I'm currently building an app in Android, and using Robotium to do functional tests (By the way, don't use Robotium on anything less that Android 1.6, it is way too buggy).
Some of these tests have a random tendency to fail, mainly Robotium missing a text field, or timing out, not reading text. I am trying to use the #FlakyTest annotation, so they will run two or three times before throwing out a failed test error. However, the annotation is not working, the tests do not re-run after a failure.
Here is how I am using the annotation:
public class ClassName extends ActivityInstrumentationTestCase2<HomeActivity>{
#LargeTest
#FlakyTest(tolerance=3)
public void testMethod(){
//Here I run my roboitium scripts.
}
}
Then I run it from the command line:
adb shell am instrument -w com.jayway.test/android.test.InstrumentationTestRunner
Neither eclipse nor the command line execution of the tests takes into account the flaky test annotation. Does anyone see an error with how I am trying to apply #FlakyTest?
I can't see any issue with your use of the #FlakyTest annotation.
I put together a quick test case to test #FlakyTest and Robotium (v2.2):
public class FlakyTestCase extends ActivityInstrumentationTestCase2<Main> {
private static int count = 0;
private Solo solo;
public FlakyTestCase() {
super("com.stackoverflow.example", Main.class);
}
#Override
public void setUp() throws Exception {
solo = new Solo(getInstrumentation(), getActivity());
}
#LargeTest
#FlakyTest(tolerance=3)
public void testFlaky(){
Log.e("FlakeyTestCase", "Execution Count:" + ++count);
solo.assertCurrentActivity(null,Main.class);
solo.clickOnText("Doesn't Exist");
Log.e("FlakeyTestCase", "Shouldn't make it here");
}
}
LogCat showed the following messages:
Execution Count: 1
Execution Count: 2
Execution Count: 3
So the #FlakyTest annotation was definitely being invoked. The (final) failure of the test was shown as:
junit.framework.AssertionFailedError: The text: Doesn't Exist is not found!
And the message "Shouldn't make it here" was never logged.
So as far as I can see, there is no issue with how you've declared your annotation or any problems with #FlakyTest and Robotium, v2.2 anyway.
Perhaps there is an issue with another part of your test code?
In general, when writing tests for Android (with or without Robotium) you have to be much more careful. You can't just say "is this visible". You need to wrap everything in a "wait for" cycle, so would say "wait for this to be visible". This is particularly a problem when running in the emulators, because sometimes things take long without any good reason. Without the waiting cycles, you will never have a consistent run. We have a few hundred tests and we have never needed to use the FlakyTest annotation.
Robotium missing a text field, or timing out, not reading text means
We have to check clearly if the text or any existed on the screen then only need to perform the actions like
if(solo.searchText("Doesn't Exist", true){
solo.clickOnText("Doesn't Exist");
}
Similar if any components like button or others we can achieve this by above logic.
Add this to your code:
import android.util.Log;

Categories

Resources