perform a task when android automation pass or fail (robotium) - android

I am trying to perform a task when android is fail or pass, is there a way to do this, and where should I put my code?
was thinking to do it in tearDown, but is there a way to check whether the testcase is pass or not??

When your test fails - that is an exception which is thrown.
I would suggest you to put the code related to your test case in try/catch block and in catch block do the stuff you want to do on test failure.
In order to mark that test case as failure you can throw the exception at the end of catch block.
e.g:
try
{
solo.....
//do your stuff
}
catch(Throwable e)
{
//Do what you want to do on test failure.
throw e;
}

You will need to register a test listener to get the pass or fail stance automatically, this however is a little bit of a pain, you will either need to override your instrumentation test runner, or use reflection to get the AndroidTestRunner from your current instrumentation test runner and then you can add in the listener as seen here http://developer.android.com/reference/android/test/AndroidTestRunner.html
There are other ways too but they are all a little bit of manual work (such as catching assertion exceptions within test methods and doing failure case that way.

looks like I've found the solution.
we can override the runTest() method, and do this:
super.runTest():
doSomething()
doSomething() will be executed when test passed..

Related

Espresso test passes individually, fails when run in the suite

I have the following Espresso test. It always passes if I run it by itself, but always fails when I run all the tests in the class together.
What's also a bit strange is that it used to work even as part of the suite. I'm not sure why now it stopped working. It must be something I've done but I don't know what.
#Test
public void itemHasImage_ShowsImage() {
closeSoftKeyboard();
if (mItem.getImageUrl() != null) {
onView(withId(R.id.edit_item_image)).perform(scrollTo())
.check(matches(isDisplayed()));
}
}
The error I'm getting is:
Error performing 'scroll to'...
...
Caused by: java.lang.RuntimeException: Action will not be performed
because the target view does not match one or more of the following
constraints:(view has effective visibility=VISIBLE and is descendant
of a: (is assignable from class: class android.widget.ScrollView...
The view is visible and a descendant of a scroll view, as evidenced by it passing when run on it's own.
When it gets to this test (in the suite) it just doesn't scroll. But when I run it by itself it scrolls just fine.
In another stack overflow question I asked recently Espresso not starting Activity the same for second iteration in parameterised test, I found out that onDestroy from the previous test was getting called after onResume in the current test, causing it to set a value to null and fail the test. Again in that situation, the problem was that the test passed by itself but not in the suite. I now have a similar problem but no obvious way to fix it. (Edit: the workaround for the other question can no longer be applied).
Any ideas anyone? Could it be reading the wrong Activity somehow? Like maybe it's looking at the one from the previous test. That sounds ridiculous but after that last problem I had it seems possible.
Edit: Ok it turns out that when running this test as part of the suite, the image is in fact not visible causing the test to fail. I found this using the debugger and scrolling the view manually. But why?
I think it's a bug and have logged an issue here:
https://code.google.com/p/android/issues/detail?id=235247
It can able to solve using Orchestrator android testing utility library, It will executing each test case independently, so there is no chance of breaking in test suite
When using AndroidJUnitRunner version 1.0 or higher, you have access to a tool called Android Test Orchestrator, which allows you to run each of your app's tests within its own invocation of Instrumentation.
Enabling using build.gradle
android {
defaultConfig {
...
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
testOptions {
execution 'ANDROID_TEST_ORCHESTRATOR'
}
}
dependencies {
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestUtil 'com.android.support.test:orchestrator:1.0.1'
}
For more info:https://developer.android.com/training/testing/junit-runner.html#using-android-test-orchestrator
I had a similar issue but the cause was different, #Rakshith-Kumar suggestion of using Orchestrator might work, also putting each test method in a TestSuite could also be a solution, since the flakiness could be addressed by running each test individually.
Also want to mention that if you're testing component that's using RxJava schedulers (io scheduler for example) to run some tasks in a background thread, the flakiness could happen because Espresso will not be able to synchronize with the background threads.
A solution can be injecting a the ObservableTransformer to do the subscribeOn and observeOn operations. And for Espresso tests substitute the ObservableTransformer instance with another one that uses Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR) for the io scheduler.
Something like that:
public <T> ObservableTransformer<T, T> ioTransformer() {
return observable -> observable.subscribeOn(AsyncTask.THREAD_POOL_EXECUTOR).observeOn(AndroidSchedulers.mainThread());
}
This way Espresso can synchronize with background threads and avoid flakiness.
More info:
https://blog.danlew.net/2015/03/02/dont-break-the-chain/
https://developer.android.com/training/testing/espresso/#sync

How to unit test Log.e in android?

I need to perform an unit test where I need to check if an error message is logged when a certain condition occurs in my app.
try {
//do something
} catch (ClassCastException | IndexOutOfBoundsException e) {
Log.e(INFOTAG, "Exception "+e.getMessage());
}
How can I test this? I am getting the below error while unit testing.
Caused by: java.lang.RuntimeException: Method e in android.util.Log not mocked.
There are two ways to do this:
You turn to Powermock or Powermokito; as those mocking frameworks will allow you to mock/check that static call to Log.e().
You could consider replacing the static call.
Example:
interface LogWrapper {
public void e( whatever Log.e needs);
}
class LogImpl implements LogWrapper {
#Override
e ( whatever ) {
Log.e (whatever) ;
}
And then, you have to use dependency injection to make a LogWrapper object available within the classes you want to log. For normal "production" usage, that object is simply an instance of LogImpl; for testing, you can either use a self-written impl (that keeps track of the logs send to it); or you can use any of the non-power mocking frameworks (like EasyMock or Mokito) to mock it. And then you use the checking/verification aspect of the mocking framework to check "log was called with the expected parametes".
Please note: depending on your setup, option 2 might be overkill. But me, personally, I avoid any usage of Powermock; simply because I have wasted too many hours of my life hunting down bizarre problems with Powermock. And I like to do coverage measurements; and sometimes Powermock gives you problems there, too.
But as you are asking about Powermock, you basically want to look here (powermockito) or here (powermock). And for the record: try using your favorite search engine the next time. It is really not like you are the first person asking this.

Rising error in Robolectric test when you have try-catch in your application code

In my android application I have written try-catch in every event method. So when an exception occurs, the catch gets the exception and a method shows a message box containing the exception details and I can handle and find my application's bugs.
For example:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
}
catch (Exception e) {
MessageBox.showException(this, e);
}
}
Now in Robolectric which there is no device to show the ui results, I cannot find out if an exception occurred. Now I want to do something when my code went to catch part or when MessageBox.showException is called, the test fails.
How can I do that?
The only way I can think of solving this is for you to inject the component that handles the errors into the classes that use it and after that, load a customized one for your tests.
There are several ways to achieve this and probably some better than what I will suggest, but I will try and present the option that requires minimum changes to what I think is your current architecture.
1 - Whatever you use for showing exceptions, instantiate this in your Application class and keep it there. Or at least provide it from your application class, so now whenever you need to use MessageBox, instead of a static method, you fetch it from the Application first. For example:
((MyApplication)getApplication()).getMessageBox().showException(this,e)
2 - Create a TestMessageBox and a TestApplication (that extends your normal Application class). In your TestApplication, override getMessageBox() to return the TestMessageBox instead of the normal MessageBox. In your TestMessageBox do whatever you want to be able to observe the errors in your tests.
3 - In your tests, use the TestApplication. When you run tests, Robolectric will load this instead of the normal application so your tests will now use your TestMessageBox and you can capture the info you need.
#Config(application = TestApplication.class)

Android - Testing a simple Activity method

i'm writing you today because i have a real and concrete question about how testing an activity method. Let me explain the situation.
I have an activity (A) which use a method save(param) from a service (S). This method throws a specific exception if the parameter is invalid.
Unit tests are written for this part, and now, i would like to test the Activity part :
In my Activty, i use the following code to call the save() method
public void OnSaveClicked()
{
try{
if ( S.save(my_object) > 0 ) // Object Saved
{
ShowToast(this, "Your object has been saved successfully !");
}
else { // Error occured with the database
ShowToast(this, "An error occured with the database");
}
catch (MyException ex)
{
ShowToast(this, "The object you are trying to save is not valid... Please check information you entered");
}
}
The test that i'm trying to write has to check if the save() method raised the exception or not. To do that, i simulate a click on the UI Button, but, i don't really know what do i have to check. I read that's not possible to write an assert on a toast message. I'm currently thinking about using a dialog but i am not sure that the way i'm thinking is the right one. Is it normal to test that or not ?
Would you give me your feedback about that, and discuss about the right way to test activity ?
Thanks,
t00f
You might want to look at Robolectric. They have support for assertions like this http://groups.google.com/group/robolectric/browse_thread/thread/87952e620ce1bb37?pli=1
Thanks,
Ian

Thread handling problem in Android Junit Test Case

I am implementing a testcase in Android Juint. I am facing problem in
handling threads. After the successful running of a test case, it will
not wait for child thread to be finished. e.g. If one testcase call
some services in server. testcase will successfully send request to a
server, but it will not wait for a response. Because testcase will
start this request in a different Thread. Currently I am using
following code,
currentThread = Thread.currentThread();
synchronized (Thread.currentThread()) {
try {
Thread.currentThread().wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
After getting response I am using the following code to start the
current thread again.
currentThread.interrupt();
I think this is not the good way to do it. There must be a some other
technique to handle this problem properly. Please let me know as soon
as possible if any one knows solution for this.
Thanks,
Vashishta
In your code the synchronized block never blocks (wait for another thread), because you synchronize on Thread.currentThread() which is a different object in different threads.
You have so synchronize on an object common to all threads: typically an object that contains shared data. Then you synchronize{..} a block od code that manipulates this data.

Categories

Resources