I am a robotium user now switching to Espresso can anyone tell me how to write tests using apk in espresso, as we do in robotium without having acccess to the code but using app apk.
And how to access views without R.id.viewid in espresso? as we do in robotium
solo.getview("viewidText")
In robotium this is how we do
public class CoreTest extends ActivityInstrumentationTestCase2 {
private Solo solo;
//class name of the app launcher activity
private static final String LAUNCHER_ACTIVITY_FULL_CLASSNAME = "com.rex.binderapps.RecorderActivity";
private static Class<?> launcherActivityClass;
static {
try {
launcherActivityClass = Class.forName(LAUNCHER_ACTIVITY_FULL_CLASSNAME);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
#SuppressWarnings("unchecked")
public CoreRecordingTest() throws ClassNotFoundException {
super(launcherActivityClass);
}
public void setUp() throws Exception {
super.setUp();
solo = new Solo(getInstrumentation());
Test.setup(this);
getActivity();
}
#Override
public void tearDown() throws Exception {
solo.finishOpenedActivities();
super.tearDown();
}
...
In espresso
#RunWith(AndroidJUnit4.class)
public class MainActivityTest {
// RecorderActivity is not accessible
#Rule public final ActivityRule<RecorderActivity> main = new ActivityRule<>(RecorderActivity.class);
#Test
public void launchMain(){
}
}
How to specify the class name?
You can use the same reflection technique to specify the class in ActivityTestRule:
#RunWith(AndroidJUnit4.class)
public class MainActivityTest {
private static final String CLASSNAME = "com.rex.binderapps.RecorderActivity";
private static Class<? extends Activity> activityClass;
static {
try {
activityClass = (Class<? extends Activity>) Class.forName(CLASSNAME);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
#Rule
public final ActivityTestRule<?> activityRule
= new ActivityTestRule<>(activityClass);
#Test
public void launchMain() {
}
}
Related
the class i want to test is posted below in the code section. I am trying to test the "setSubscriberName" method.
the test I coded is posted below in the testing section. but at run time the test fails
please let me know how to test that setter method correctly
code
public class ListViewModel {
private String mSubscriberName = null;
public ListViewModel(String subscriberName) {
mSubscriberName = subscriberName;
}
public void setSubscriberName(String name) {
mSubscriberName = name;
}
}
testing:
public class ListViewModelTest {
#Mock
private ListViewModel mListViewModel = null;
#Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
#Before
public void setUp() throws Exception {
mListViewModel = new ListViewModel("");
}
public void setSubscriberName(String str) {
String mSubscriberName = null;
mSubscriberName = str;
}
#Test
public void setSubscriberNameTest() throws Exception {
ListViewModel spyListView = spy(mListViewModel);
verify(spyListView).setSubscriberName("abc");
}
}
In our current framework we have a base class that extends ActivityInstrumentationTestCase2 | Android Developers. Typically when we write our test case classes we inherit this base class ( lets call it FooBase) and write our methods. As you can imagine this is getting really big and I would like to refactor it so that for each area of the feature we are testing it is in its own class so that we can reuse it. Hopefully my vague classes are accurate enough The goal is just being able to split the methods into different classes and call them from my testcase
public class FooBase extends ActivityInstrumentionTestCase2 {
#Override
public void runTestOnUiThread(Runnable runnable) {
try {
super.runTestOnUiThread(runnable);
} catch (InterruptedException e) {
throw RuntimeInterruptedException.rethrow(e);
} catch (RuntimeException e) {
throw e;
} catch (Error e) {
throw e;
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
and our test would be eg
public class TestFooBase extends FooBase{
public void testfeature(){
//execute a method that uses super.runTestOnUiThread()
}
}
How I attempted to refactor it
public class FooHelper extends FooBase{
public FooHelper(Activity activity){
setActivity(activity)
}
public void sameMethod(){
//moved the method in FooBase to this class that uses the runTestOnUiThread
}
}
My new testcase would look something like this
public class TestFooBase extends FooBase{
FooHelper fooHelper;
public void setup(){
fooHelper = new FooHelper(getActivity);
}
public void testfeature(){
//execute a method that uses super.runTestOnUiThread()
fooHelper.callthemethod()
}
}
When I execute this I get a null pointer on the super.runTestOnUIThread.
You can pass in the entire test class and set up a constructor for it.
public class BaseTestCase {
private Instrumentation instrumentation;
private InstrumentationTestCase instrumentationTestCase;
public BaseTestCase(InstrumentationTestCase testClass, Instrumentation instrumentation){
this.instrumentationTestCase = testClass;
this.instrumentation = instrumentation;
}
public Activity getCurrentActivity() {
try {
instrumentationTestCase.runTestOnUiThread(new Runnable() {
#Override
public void run() {
//Code
}
});
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return activity;
}
To use, you want to instantiate the BaseTestCase class on the setUp method
public class ActivityTest extends ActivityInstrumentationTestCase2<TestActivity.class>{
private BaseTestCase baseTestCase;
#Override
public void setUp() throws Exception {
super.setUp();
getActivity();
baseTestCase = new BaseTestCase(this, getInstrumentation());
}
}
And to access the public methods in your BaseTestCase
public void testRun(){
baseTestCase.getCurrentActivity();
}
I want to use RoboGuice in a standard Android JUnit instrumentation test case and override one piece of my app's actual wiring with a mock for testing. I can't find anything online that explains how to do this as all of my search results go to Robolectric with RoboGuoice. I am not using Robolectric nor can I use it in my app for various reasons. Has anyone wired an app with RoboGuice and injected mocks for standard Android Intrumentation test cases?
I'm using the Roboguice 3 and I solved this problem with the following setup and teardown methods within the standard ActivityInstrumentationTestCase2.
Obviously you would need to replace new TestModule() in the snippet below with your own test module class.
#Override
protected void setUp() throws Exception {
super.setUp();
Application app = (Application)getInstrumentation().getTargetContext()
.getApplicationContext();
RoboGuice.getOrCreateBaseApplicationInjector(app, RoboGuice.DEFAULT_STAGE,
Modules.override(RoboGuice.newDefaultRoboModule(app))
.with(new TestModule()));
getActivity();
}
#Override
protected void tearDown() throws Exception {
RoboGuice.Util.reset();
super.tearDown();
}
I've managed to get it work in a simple usage way, you just bind dependencies inside rule using builder and may forget about them later, it will do everything by itself. You may think it's over engineered, but it's realy good for reusing if tyou have a many test classes with robo guice dependencies inside.
Usage in test classes looks like:
#Rule
public InjectWithMocksRule injectWithMocksRule = new InjectWithMocksRule(
this,
() -> new InjectRule
.BindingBuilder()
.add(MyClass.class, mockedClassImpl)
.add(SomeInterface.class, mockedInterfaceImpl));
I wrote helper class TestBindingModule:
public class TestBindingModule extends AbstractModule {
private HashMap<Class<?>, Object> bindings = new HashMap<Class<?>, Object>();
#Override
#SuppressWarnings("unchecked")
protected void configure() {
Set<Entry<Class<?>, Object>> entries = bindings.entrySet();
for (Entry<Class<?>, Object> entry : entries) {
bind((Class<Object>) entry.getKey()).toInstance(entry.getValue());
}
}
public void addBinding(Class<?> type, Object object) {
bindings.put(type, object);
}
public void addBindings(HashMap<Class<?>, Object> bindings) {
this.bindings.putAll(bindings);
}
public static void setUp(Object testObject, TestBindingModule module) {
Module roboGuiceModule = RoboGuice.newDefaultRoboModule(RuntimeEnvironment.application);
Module testModule = Modules.override(roboGuiceModule).with(module);
RoboGuice.getOrCreateBaseApplicationInjector(RuntimeEnvironment.application, RoboGuice.DEFAULT_STAGE, testModule);
RoboInjector injector = RoboGuice.getInjector(RuntimeEnvironment.application);
injector.injectMembers(testObject);
}
public static void tearDown() {
Application app = RuntimeEnvironment.application;
DefaultRoboModule defaultModule = RoboGuice.newDefaultRoboModule(app);
RoboGuice.getOrCreateBaseApplicationInjector(app, RoboGuice.DEFAULT_STAGE, defaultModule);
}
}
Than I use custom Rule to make it work easy:
public class InjectRule implements TestRule {
public interface BindingBuilderFactory {
BindingBuilder create();
}
public static class BindingBuilder {
private HashMap<Class<?>, Object> bindings = new HashMap<>();
public BindingBuilder add(Class<?> dependencyClass, Object implementation) {
bindings.put(dependencyClass, implementation);
return this;
}
HashMap<Class<?>, Object> buildBindings() {
return this.bindings;
}
}
private Object target;
private BindingBuilderFactory bindingBuilderFactory;
public InjectRule(Object target, BindingBuilderFactory bindingBuilderFactory) {
this.target = target;
this.bindingBuilderFactory = bindingBuilderFactory;
}
private void overrideTestInjections(Object target) {
TestBindingModule module = new TestBindingModule();
module.addBindings(this.bindingBuilderFactory.create().buildBindings());
TestBindingModule.setUp(target, module);
}
#Override
public Statement apply(Statement base, Description description) {
return new StatementDecorator(base);
}
private class StatementDecorator extends Statement {
private Statement baseStatement;
StatementDecorator(Statement b) {
baseStatement = b;
}
#Override
public void evaluate() throws Throwable {
before();
try {
baseStatement.evaluate();
} catch (Error e) {
throw e;
} finally {
after();
}
}
void after() {
TestBindingModule.tearDown();
}
void before() {
overrideTestInjections(target);
}
}
}
Also you may want to init mocks with #Mock annotation inside of your test classes, so you need another custom rule:
public class MockitoInitializerRule implements TestRule {
private Object target;
public MockitoInitializerRule(Object target) {
this.target = target;
}
#Override
public Statement apply(Statement base, Description description) {
return new MockitoInitializationStatement(base, target);
}
private class MockitoInitializationStatement extends Statement {
private final Statement base;
private Object test;
MockitoInitializationStatement(Statement base, Object test) {
this.base = base;
this.test = test;
}
#Override
public void evaluate() throws Throwable {
MockitoAnnotations.initMocks(test);
base.evaluate();
}
}
}
And, finaly, you want to combine them to mock mocks first and then set them as dependencies:
public class InjectWithMocksRule implements TestRule {
private final RuleChain delegate;
public InjectWithMocksRule(Object target, InjectRule.BindingBuilderFactory bindingBuilderFactory) {
delegate = RuleChain
.outerRule(new MockitoInitializerRule(target))
.around(new InjectRule(target, bindingBuilderFactory));
}
#Override
public Statement apply(Statement base, Description description) {
return delegate.apply(base, description);
}
}
I have been able to run an android junit test with one test method successfully, but when more than one test method are involved, it just runs the first test and after tearDown, the activity does not relaunch for the subsequent tests. As a result, all my test methods fail, save the first one.
On debugging, I noticed that setUp method launches the MainActivity successfully before running the first testMethod, but on being revisited before the start of second testMethod, the same activity does not get relaunched. The code is as below:
package PACKAGE.test;
import com.jayway.android.robotium.solo.Solo;
import android.test.ActivityInstrumentationTestCase2;
public class Login extends ActivityInstrumentationTestCase2 {
private static final String LAUNCHER_ACTIVITY_FULL_CLASSNAME = "*.*.MainActivity";
private static Class<?> launcherActivityClass;
static {
try {
launcherActivityClass = Class.forName(LAUNCHER_ACTIVITY_FULL_CLASSNAME);
}
catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
#SuppressWarnings("unchecked")
public Login() throws ClassNotFoundException {
super(launcherActivityClass);
}
private Solo solo;
public void setUp() throws Exception {
super.setUp();
solo = new Solo(getInstrumentation(), getActivity());
}
#Test
public void testLoginScreen() {
solo.enterText(0, "user-name");
solo.enterText(1, "pwd");
solo.clickOnButton("Login");
solo.waitForActivity("*.*.*.nextActivity");
solo.clickOnRadioButton(2);
}
#Test
public void testSearch(){
solo.enterText(0, "user-name");
solo.enterText(1, "pwd");
solo.clickOnButton("Login");
solo.waitForActivity("*.*.*.nextActivity");
solo.clickOnRadioButton(1);
}
public void tearDown() throws Exception {
solo.finishOpenedActivities();
super.tearDown();
}
}
You may need to #Override your teardown method
#Override
public void tearDown() throws Exception {
solo.finishOpenedActivities();
super.tearDown();
}
I have an activity A that launch an activity B.
I'd like to have a robotium project to test my app so I'v created a first test class for activity A and all goes well.
I'd like now to create another test class for testing Activity B but it require some init from activity A.
I tried this:
BTestClass extends ActivityInstrumentationTestCase2 {
private Solo solo;
private ATestClass testA;
#Override
protected void setUp() throws Exception {
Log.i(TAG, "setUp");
solo = new Solo(getInstrumentation(), getActivity());
testA = new ATestClass();
testA.setUp();
testA.testAddAccount();
solo.clickInList(0);
}
[… more test method]
}
I got a NullPointerException when testA is doing getActivity()
I do it this way:
public class BTest extends ActivityInstrumentationTestCase2<SplashScreenActivity> {
protected static final String TARGET_PACKAGE_ID = "app.under.test";
protected Solo solo;
public BTest() {
super(TARGET_PACKAGE_ID, StartingActivity.class);
}
#Override
public void setUp() throws Exception {
super.setUp();
solo = new Solo(getInstrumentation(), getActivity());
// setup stuff
}
#Override
public void tearDown() throws Exception {
// teardown stuff
super.tearDown();
}
}
All testcases just inherit from BTest then
public class OneTest extends BTest {
public void test_OneTest() {
//test stuff
solo.clickOnButton("Ok");
}
}