Robotium with parameter - android

Is there any way from which i can run a single test case multiple times with different data in robotium tesing of an android application.
Just like parameterized juint testing.
public class UserTest extends
ActivityInstrumentationTestCase2<MainActivity> {
public UserTest() {
super(TestActivity.class);
}
#Override
public void setUp() throws Exception {
// setUp() is run before a test case is started.
// This is where the solo object is created.
solo = new Solo(getInstrumentation(), getActivity());
}
public void testUserData1() throws Exception {
// UserBean
Bean bean = setUp.get(0);
dataTest(bean);
}
public void testUserData2() throws Exception {
// UserBean
Bean bean = setUp.get(1);
dataTest(bean);
}
public void dataTest(Bean bean) {
Log.e("testAddNote userbean", bean.toString());
// Login
solo.enterText(0, bean.getUserName());
solo.enterText(1, bean.getPassWord());
solo.clickOnButton(0);
}
this the way currently i am running test cases is there a way by which dataTest(Bean) can be executed multiple times with setUp elements as parameters.Means i have to call single method multiple times with different parameters.

I just notice that this only works if you are using https://code.google.com/p/zohhak/
In that case you can do:
#TestWith({
“2, true”,
“6, false”,
“19, true”
})
public void testPrimeNumberValidator(int number, boolean isPrime) {
assertThat(…
}

Related

How to test element of custom sdk android unit test

I've started learning android unit tests, but it looks very hard to find some good guides or information. Every example have a stupid example about 2+2 = 4
Say I write a little SDK which has few functions
MySdk.Init(Context context)
MySdk.CallTask()
I create an androidTest file
How should I call my SDK functions to check how they work? Somewhere required parameters like int/string/context. I just really don't understand, please help me.
This is what I've tried
public class AndroidTest {
private Activity context;
//default test
#Test
public void addition_correct() throws Exception {
assertEquals(4, 2 + 2);
}
#Test
public void checkContext() {
context = getActivity();
assertNotNull(context);
}
#Test
public void testInitPhase() {
MySdk.Init(context, new SdkInitializationListener() {
#Override
public void onInitializationSuccessful(String adv_id) {
assert (adv_id != null);
}
#Override
public void onInitializationError() {
}
});
}
}
For context i was tried context = new mockContext();. It's passed as context = null and my SDK failed with initialization.
Unit tests are mainly about testing an individual class in isolation, so that you can check if individual public methods of a class behave as you intend them to, and continue to do so if you change that class' code in the future. Let's say you have a class like this:
public class UtilityFunctions {
public int double(int value) {
return value * 2;
}
public String mirror(String value) {
if (value == null) return "";
return value + new StringBuilder(value).reverse().toString();
}
}
You want to test these two methods with:
valid input values, and check the output is as expected
invalid values, and check that errors are handled accordingly (and the correct exceptions thrown if necessary)
So a test class for the above class may look like this
#RunWith(JUnit4.class)
public class UtilityFunctionsTest {
private UtilityFunctions utility;
#Before
public void setUp() {
// Initialises any conditions before each test
utility = new UtilityFunctions();
}
#Test
public void testDoubleFunction() {
assertEquals(2, utility.double(1));
assertEquals(8, utility.double(4));
assertEquals(-12, utility.double(-6));
assertEquals(0, utility.double(0));
}
#Test
public void testMirror() {
assertEquals("", utility.mirror(null));
assertEquals("", utility.mirror(""));
assertEquals("aa", utility.mirror("a"));
assertEquals("MirrorrorriM", utility.mirror("Mirror"));
}
}
These standard Java unit tests are run from the test directory. However, you'll need to run tests in the androidTest directory whenever you're using Android-specific classes such as Context. If you're creating a MockContext, you're simply creating an empty Context whose methods don't do anything.
Without me knowing anything about what your MySDK does, I think you may need to pass a fully-functioning Context into your class for your tests. The Android JUnit runner does provide this with InstrumentationRegistry.getTargetContext(), so for your example, you may need to add this #Before method:
#Before
public void setUp() {
context = InstrumentationRegistry.getTargetContext();
}
You'll also need to remove the context = getActivity(); line from your first test.

how to test private Observable inside public method?

I am new with tests.
I have something like next code and wish to cover it with unitTests using the Mockito:
public void doSomeJob(){
//some code before
getMvpView().execute(getObservable());
//some code after
}
private Observable<Boolean> getObservable(){
return Observable.create(new ObservableOnSubscribe<Boolean>() {
#Override
public void subscribe(#NonNull ObservableEmitter<Boolean> e) throws Exception {
Thread.sleep(5000);
e.onNext(true);
e.onComplete();
}
});
}
so questions:
how correct write test for getMvpView().execute(getObservable()); using Mokito?
how can i verify result of getObservable()?
If your private method is not a part of the interface, i.e. cannot be reached from outside the class, it's not something you should test (presumably it's not, since it's private). Mockito in turn doesn't provide mocking of private methods. Thereby you either need to change your interface (make this data available outside) or leave it without testing.
What you should test is the effect of calling the public methods of your class under test. If you do so you will be able to freely refactor the implementation details later, and your tests will still verify that your class works as expected.
I suppose that your code is part of a presenter implementation and the getMvpView() method returns a view interface:
public class MvpPresenterImpl {
private MvpView view;
public void doSomeJob(){
//some code before
getMvpView().execute(getObservable());
//some code after
}
public void attachView(MvpView view) {
this.view = view;
}
private MvpView getMvpView() {
return view;
}
private Observable<Boolean> getObservable(){
return Observable.create(new ObservableOnSubscribe<Boolean>() {
#Override
public void subscribe(#NonNull ObservableEmitter<Boolean> e) throws Exception {
Thread.sleep(5000);
e.onNext(true);
e.onComplete();
}
});
}
}
You can test the effect of doSomeJob() like so:
public class MvpPresenterImplTest {
private MvpPresenterImpl presenter;
private MvpView mockView;
#Before
public void setUp() throws Exception {
// Create a mock view instance so that we can verify method calls on it
mockView = mock(MvpView.class);
// Create our object under test, and set it up with the mock view
presenter = new MvpPresenterImpl();
presenter.attachView(mockView);
}
#Test
public void doSomeJob_callsExecuteOnViewWithCorrectObserver() throws Exception {
// What we want to test is the effect of invoking a public method.
presenter.doSomeJob();
// Verify that the execute method has been called by your class
// under test, and save the parameter for later.
ArgumentCaptor<Observable<Boolean>> paramCaptor =
ArgumentCaptor.<Observable<Boolean>>forClass((Class)Observable.class);
verify(mockView).execute(paramCaptor.capture());
// Get the actual observable that the execute method was called with.
Observable<Boolean> param = paramCaptor.getValue();
// Get a test observer so that we can check what our Observable emits
// (TestObserver is a built-in feature of RxJava, not Mockito.)
TestObserver<Boolean> test = param.test();
// Assert that the Observable behaves as expected
test.assertComplete();
test.assertResult(true);
}
}

How to run unit test + Espresso repeatedly?

I need to collect some data on my current app in order to analyse performance speed by checking the average ellapsed time during Activity start up. I would like to run a test battery where the activity is started 10, 100, 1000 and 5000 times. For each test, it should remain open for at least 10 seconds (time needed to collect all data that happens asynchronously). What I want is exactly this behaviour without having to write these many methods:
#RunWith(AndroidJUnit4.class)
#LargeTest
public class TestStreamLoadingPerformance {
private static final long TIME_OUT = 2;
private static final long WAITING_TIME = 10000;
#Rule
public ActivityTestRule mActivityRule = new ActivityTestRule(HomepageActivity.class);
private ElapsedTimeIdlingResource mIdleRes = new ElapsedTimeIdlingResource(WAITING_TIME);
#Before
public void setUp() {
IdlingPolicies.setMasterPolicyTimeout(TIME_OUT, TimeUnit.HOURS);
IdlingPolicies.setIdlingResourceTimeout(TIME_OUT, TimeUnit.HOURS);
Espresso.registerIdlingResources(mIdleRes);
}
#After
public void tearDown() {
Espresso.unregisterIdlingResources(mIdleRes);
}
#Test
public void test01() {
}
#Test
public void test02() {
}
#Test
public void test03() {
}
#Test
public void test04() {
}
#Test
public void test05() {
}
#Test
public void test06() {
}
#Test
public void test07() {
}
#Test
public void test08() {
}
#Test
public void test09() {
}
}
With the help of #Be_negative comments, this blog post and this answer, I was able to solve the problem with the code below:
#RunWith(AndroidJUnit4.class)
#LargeTest
public class TestStreamLoadingPerformance {
#Rule
public ActivityTestRule mActivityRule = new ActivityTestRule(HomepageActivity.class, false, false);
#Rule
public RepeatRule mRepeatRule = new RepeatRule();
#After
public void tearDown() {
closeActivity();
}
private void closeActivity() {
final int N = 10;
try {
for (int i = 0; i < N; i++) {
Espresso.pressBack();
}
} catch (NoActivityResumedException e) {
Log.e(TestStreamLoadingPerformance.class.getSimpleName(), "Unable to close activities", e);
}
}
#Test
#RepeatRule.Repeat(times = 10)
public void collectData() {
mActivityRule.launchActivity(null);
}
}
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public class RepeatRule implements TestRule {
#Retention(RetentionPolicy.RUNTIME)
#Target({
java.lang.annotation.ElementType.METHOD
})
public #interface Repeat {
public abstract int times();
}
private static class RepeatStatement extends Statement {
private final int times;
private final Statement statement;
private RepeatStatement(int times, Statement statement) {
this.times = times;
this.statement = statement;
}
#Override
public void evaluate() throws Throwable {
for (int i = 0; i < times; i++) {
statement.evaluate();
}
}
}
#Override
public Statement apply(Statement statement, Description description) {
Statement result = statement;
Repeat repeat = description.getAnnotation(Repeat.class);
if (repeat != null) {
int times = repeat.times();
result = new RepeatStatement(times, statement);
}
return result;
}
}
The easiest (as in least amount of new code required) way to do this is to run the test as a parametrized test (annotate with an #RunWith(Parameterized.class) and add a method to provide 10 empty parameters). That way the framework will run the test 10 times.
This test would need to be the only test in the class, or better put all test methods should need to be run 10 times in the class.
Here is an example:
#RunWith(Parameterized.class)
public class RunTenTimes {
#Parameterized.Parameters
public static List<Object[]> data() {
return Arrays.asList(new Object[10][0]);
}
public RunTenTimes() {
}
#Test
public void runsTenTimes() {
System.out.println("run");
}
}
With the above, it is possible to even do it with a parameter-less constructor, but I'm not sure if the framework authors intended that, or if that will break in the future.
If you are implementing your own runner, then you could have the runner run the test 10 times. If you are using a third party runner, then with 4.7, you can use the new #Rule annotation and implement the MethodRule interface so that it takes the statement and executes it 10 times in a for loop. The current disadvantage of this approach is that #Before and #After get run only once. This will likely change in the next version of JUnit (the #Before will run after the #Rule), but regardless you will be acting on the same instance of the object (something that isn't true of the Parameterized runner). This assumes that whatever runner you are running the class with correctly recognizes the #Rule annotations. That is only the case if it is delegating to the JUnit runners.
If you are running with a custom runner that does not recognize the #Rule annotation, then you are really stuck with having to write your own runner that delegates appropriately to that Runner and runs it 10 times.
Note that there are other ways to potentially solve this (such as the Theories runner) but they all require a runner. Unfortunately JUnit does not currently support layers of runners. That is a runner that chains other runners.
I had a very similar issue and as a result I've created a library to run Android UI tests multiple times. Might be useful in your case: https://github.com/stepstone-tech/AndroidTestXRunner

Testing Android Activity with Robolectric, duplicated Otto provider

I have a little problem figuring out how to test my Activity using Robolectric 2.2. I am probably not correctly setting up the lifecycle or the entire test...
In my Activity, I have a Otto producer like this:
#Produce public GetAlarmList produceAlarmList() {
Log.v(this, "Producing GetAlarmList event.");
return new GetAlarmList(mAlarmList);
}
The following is my test.
#RunWith(RobolectricTestRunner.class)
public class GLarmListFragmentTests {
//GLarmMain mActivity;
ActivityController<GLarmMain> mController;
#Before
public void setUp() throws Exception {
mController = Robolectric.buildActivity(GLarmMain.class);
}
#After
public void tearDown() throws Exception {
mController = mController.destroy();
}
#Test
public void shouldHaveListFragment() {
GLarmMain activity = mController.create().start().resume().visible().get();
GLarmListFragment listFragment = (GLarmListFragment) activity.getSupportFragmentManager().findFragmentById(R.id.main_list_frag);
assertNotNull(listFragment);
}
#Test
public void shouldHaveListAdapter() {
GLarmMain activity = mController.create().start().resume().visible().get();
GLarmListFragment listFragment = (GLarmListFragment) activity.getSupportFragmentManager().findFragmentById(R.id.main_list_frag);
FuncAlarmListAdapter listAdapter = (FuncAlarmListAdapter)listFragment.getListAdapter();
assertNotNull(listAdapter);
}
}
Every time I launch it, I receive:
java.lang.IllegalArgumentException: Producer method for type class ar.android.app.glarm.events.GetAlarmList found on type class ar.android.app.glarm.ui.GLarmMain, but already registered by type class ar.android.app.glarm.ui.GLarmMain.
at com.squareup.otto.Bus.register(Bus.java:198)
at ar.android.app.glarm.ui.GLarmMain.onResume(GLarmMain.java:461)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1184)
at android.app.Activity.performResume(Activity.java:5082)
at org.fest.reflect.method.Invoker.invoke(Invoker.java:112)
at org.robolectric.util.ActivityController$6.run(ActivityController.java:216)
at org.robolectric.shadows.ShadowLooper.runPaused(ShadowLooper.java:256)
at org.robolectric.util.ActivityController.invokeWhilePaused(ActivityController.java:214)
at org.robolectric.util.ActivityController.resume(ActivityController.java:152)
at ar.android.app.glarm.test.GLarmListFragmentTests.shouldHaveListAdapter(GLarmListFragmentTests.java:51)
Does someone have the same issue? How can I solve it?
Found the problem, leaving it here for reference.
I was not handling the pause()/onPause() life-cycle step and therefore never calling:
#Override
protected void onPause() {
super.onPause();
Log.v(this, ".onPause()");
mBus.unregister(this); // unregisters.
}
Changing the above code as following solved:
#After
public void tearDown() throws Exception {
mController = mController.pause().stop().destroy();
}

Android JUNIT testing stuck

I'm new at JUnit tests, I'm trying to test database access through this code:
public class SeuticketTest extends ActivityInstrumentationTestCase2<Seuticket> {
private Seuticket mActivity;
public SeuticketTest(String name) {
super("br.com.code.seuticket.android.view",Seuticket.class);
setName(name);
}
#Override
protected void setUp() throws Exception {
super.setUp();
mActivity = this.getActivity();
}
public void testTicketInsertion() {
Ticket ticket = new Ticket("123453", "Vip", new Date(), "Vila Country");
PersistenceTicket persistence = new PersistenceTicket(mActivity);
persistence.addTicket(ticket);
assertEquals(persistence.fetchTicket(ticket.getTicketCode()).getTicketCode(),ticket.getTicketCode());
}
public void testUserInsertion() {
User user = new User();
user.setPin("1234");
user.setPhone("9241173");
PersistenceUser persistence = new PersistenceUser(mActivity);
persistence.addUser(user);
assertEquals(persistence.fetchUser().getPin(), user.getPin());
}
}
But my tests get stuck after complete the testTicketInsertion, the second test keep running forever, and sometimes before it run the tests this message shows at the console:
Test run failed: Process crashed.
Any ideas?
Hope to find an answer here.
Thanks people!
I am brand new to JUnit testing in Android and ran into the same problem. Make sure you have the tearDown method overridden and are making the call to super.
protected void tearDown() throws Exception {
super.tearDown();
}

Categories

Resources