Android Testing

111
Android Testing Evan Lin at [email protected]

Transcript of Android Testing

Android TestingEvan Lin

at

[email protected]

Tools• Mock -> Mockito

• http://mockito.org/

• UI Testing -> Espresso

• https://developer.android.com/training/testing/ui-testing/espresso-testing.html

• Dependency Injection -> Dagger2

• http://google.github.io/dagger/

Mockitodependencies {

... // Mockito debugCompile 'org.mockito:mockito-core:1.10.19' debugCompile 'com.google.dexmaker:dexmaker:1.2' debugCompile ‘com.google.dexmaker:dexmaker-mockito:1.2'}

Espressoandroid { defaultConfig { ... // Espresso2 testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } }dependencies { ... // Espresso2 androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2' androidTestCompile ‘com.android.support.test:runner:0.3'}

Dagger2// dagger2 apply plugin: 'com.neenbedankt.android-apt' buildscript { repositories { jcenter() } dependencies { // dagger2 classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4' } } dependencies { ... // dagger2 compile 'junit:junit:4.12' compile 'com.google.dagger:dagger:2.0' apt 'com.google.dagger:dagger-compiler:2.0' provided 'org.glassfish:javax.annotation:10.0-b28' }

Start

public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } } EditText mEmailEditText; EditText mPasswordEditText; mEmailEditText = (EditText) findViewById(R.id.email); mPasswordEditText = (EditText) findViewById(R.id.password); public void onEnterButtonClick() { String email = mEmailEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); if (checkEmailAndPassword(email, password)) goToSecondPage(); } private boolean checkEmailAndPassword(String email, String password) { return email.equals("admin") && password.equals("admin"); } private void goToSecondPage() { Intent intent = new Intent(this, SecondActivity.class); startActivity(intent); }

public class MainActivity extends Activity { EditText mEmailEditText; EditText mPasswordEditText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mEmailEditText = (EditText) findViewById(R.id.email); mPasswordEditText = (EditText) findViewById(R.id.password); } public void onEnterButtonClick() { String email = mEmailEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); if (checkEmailAndPassword(email, password)) goToSecondPage(); } private boolean checkEmailAndPassword(String email, String password) { return email.equals("admin") && password.equals("admin"); } private void goToSecondPage() { Intent intent = new Intent(this, SecondActivity.class); startActivity(intent); } }

public class MainActivity extends Activity { EditText mEmailEditText; EditText mPasswordEditText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mEmailEditText = (EditText) findViewById(R.id.email); mPasswordEditText = (EditText) findViewById(R.id.password); } public void onEnterButtonClick(View view) { String email = mEmailEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); if (checkEmailAndPassword(email, password)) goToSecondPage(); } private boolean checkEmailAndPassword(String email, String password) { return email.equals("admin") && password.equals("admin"); } private void goToSecondPage() { Intent intent = new Intent(this, SecondActivity.class); startActivity(intent); } }

public class MainActivity extends Activity { EditText mEmailEditText; EditText mPasswordEditText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mEmailEditText = (EditText) findViewById(R.id.email); mPasswordEditText = (EditText) findViewById(R.id.password); } public void onEnterButtonClick(View view) { String email = mEmailEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); if (checkEmailAndPassword(email, password)) goToSecondPage(); } private boolean checkEmailAndPassword(String email, String password) { return email.equals("admin") && password.equals("admin"); } private void goToSecondPage() { Intent intent = new Intent(this, SecondActivity.class); startActivity(intent); } }

public class MainActivity extends Activity { EditText mEmailEditText; EditText mPasswordEditText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mEmailEditText = (EditText) findViewById(R.id.email); mPasswordEditText = (EditText) findViewById(R.id.password); } public void onEnterButtonClick(View view) { String email = mEmailEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); if (checkEmailAndPassword(email, password)) goToSecondPage(); } private boolean checkEmailAndPassword(String email, String password) { return email.equals("admin") && password.equals("admin"); } private void goToSecondPage() { Intent intent = new Intent(this, SecondActivity.class); startActivity(intent); } }

Keep Signin

public class UserService { ... public boolean isLogin() { return loadLoginStatus(); } public boolean login(String email, String password) { if (checkEmailAndPassword(email, password)) { saveLoginStatus(true); return true; } else { return false; } } private boolean checkEmailAndPassword(String email, String password) { return email.equals("admin") && password.equals("admin"); } ... }

public class UserService { ... public boolean isLogin() { return loadLoginStatus(); } public boolean login(String email, String password) { if (checkEmailAndPassword(email, password)) { saveLoginStatus(true); return true; } else { return false; } } private boolean checkEmailAndPassword(String email, String password) { return email.equals("admin") && password.equals("admin"); } ... }

public class UserService { ... public boolean isLogin() { return loadLoginStatus(); } public boolean login(String email, String password) { if (checkEmailAndPassword(email, password)) { saveLoginStatus(true); return true; } else { return false; } } private boolean checkEmailAndPassword(String email, String password) { return email.equals("admin") && password.equals("admin"); } ... }

public class UserService { private PasswordValidator mPasswordValidator; ... public boolean isLogin() { return loadLoginStatus(); } public boolean login(String email, String password) { if (mPasswordValidator.checkEmailAndPassword(email, password)) { saveLoginStatus(true); return true; } else { return false; } } private boolean checkEmailAndPassword(String email, String password) { return email.equals("admin") && password.equals("admin"); } ...}

public class PasswordValidator { public boolean checkEmailAndPassword(String email, String password) { return email.equals("admin") && password.equals("admin"); } }

public class UserService { public static final String SHARED_PREF_NAME = "MY_SHARED_PREF"; private static final String SHARED_PREF_KEY_IS_LOGIN = “SHARED_PREF_KEY_IS_LOGIN"; private PasswordValidator mPasswordValidator; private SharedPreferences mSharedPreferences; public UserService(Context appContext, PasswordValidator validator) { mPasswordValidator = validator; mSharedPreferences = appContext.getSharedPreferences(SHARED_PREF_NAME, 0); } ... private boolean loadLoginStatus() { return mSharedPreferences.getBoolean(SHARED_PREF_KEY_IS_LOGIN, false); } private void saveLoginStatus(boolean isLogin) { SharedPreferences.Editor editor = mSharedPreferences.edit(); editor.putBoolean(SHARED_PREF_KEY_IS_LOGIN, isLogin); editor.commit(); } }

public class MainActivity extends Activity { EditText mEmailEditText; EditText mPasswordEditText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mEmailEditText = (EditText) findViewById(R.id.email); mPasswordEditText = (EditText) findViewById(R.id.password); } public void onEnterButtonClick(View view) { String email = mEmailEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); if (checkEmailAndPassword(email, password)) goToSecondPage(); } private boolean checkEmailAndPassword(String email, String password) { return email.equals("admin") && password.equals("admin"); } private void goToSecondPage() { Intent intent = new Intent(this, SecondActivity.class); startActivity(intent); } }

public class MainActivity extends Activity { EditText mEmailEditText; EditText mPasswordEditText; UserService mUserService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mEmailEditText = (EditText) findViewById(R.id.email); mPasswordEditText = (EditText) findViewById(R.id.password); mUserService = new UserService(getApplicationContext(), new PasswordValidator()); } public void onEnterButtonClick(View view) { String email = mEmailEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); if (checkEmailAndPassword(email, password)) goToSecondPage(); } private boolean checkEmailAndPassword(String email, String password) { return email.equals("admin") && password.equals("admin"); } private void goToSecondPage() { Intent intent = new Intent(this, SecondActivity.class); startActivity(intent); } }

public class MainActivity extends Activity { EditText mEmailEditText; EditText mPasswordEditText; UserService mUserService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mEmailEditText = (EditText) findViewById(R.id.email); mPasswordEditText = (EditText) findViewById(R.id.password); mUserService = new UserService(getApplicationContext(), new PasswordValidator()); } public void onEnterButtonClick(View view) { String email = mEmailEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); if (checkEmailAndPassword(email, password)) goToSecondPage(); } private boolean checkEmailAndPassword(String email, String password) { return email.equals("admin") && password.equals("admin"); } private void goToSecondPage() { Intent intent = new Intent(this, SecondActivity.class); startActivity(intent); } }

public class MainActivity extends Activity { EditText mEmailEditText; EditText mPasswordEditText; UserService mUserService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mEmailEditText = (EditText) findViewById(R.id.email); mPasswordEditText = (EditText) findViewById(R.id.password); mUserService = new UserService(getApplicationContext(), new PasswordValidator()); } public void onEnterButtonClick(View view) { String email = mEmailEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); boolean isLoginSuccess = mUserService.login(email, password); if (isLoginSuccess) goToSecondPage(); } private void goToSecondPage() { Intent intent = new Intent(this, SecondActivity.class); startActivity(intent); } }

public class MainActivity extends Activity { EditText mEmailEditText; EditText mPasswordEditText; UserService mUserService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mEmailEditText = (EditText) findViewById(R.id.email); mPasswordEditText = (EditText) findViewById(R.id.password); mUserService = new UserService(getApplicationContext(), new PasswordValidator()); if (checkAutoLogin()) { goToSecondPage(); finish(); } } private boolean checkAutoLogin() { return mUserService.isLogin(); } public void onEnterButtonClick(View view) { String email = mEmailEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); boolean isLoginSuccess = mUserService.login(email, password); if (isLoginSuccess) goToSecondPage(); } ...

First Time Open App

Second Time Open App

Time to Test

Unit Test

1.

2.

3.

public class UserServiceTest extends TestCase { }

public class UserServiceTest extends TestCase { public void testLoginSuccess() throws Exception { // arrange // act // assert } }

public class UserServiceTest extends TestCase { public void testLoginSuccess() throws Exception { // arrange // act // assert } }

test method prefix

public class UserServiceTest extends TestCase { public void testLoginSuccess() throws Exception { // arrange // act // assert } }

public class UserServiceTest extends AndroidTestCase { public void testLoginSuccess() throws Exception { // arrange PasswordValidator validator = new PasswordValidator(); UserService userService = new UserService(getContext(), validator); // act // assert } }

public class UserServiceTest extends AndroidTestCase { public void testLoginSuccess() throws Exception { // arrange PasswordValidator validator = new PasswordValidator(); UserService userService = new UserService(getContext(), validator); // act userService.login("admin", "admin"); // assert assertTrue(userService.isLogin()); } }

public class UserServiceTest extends AndroidTestCase { public void testLoginSuccess() throws Exception { // arrange PasswordValidator validator = Mockito.mock(PasswordValidator.class); UserService userService = new UserService(getContext(), validator); // act userService.login("admin", "admin"); // assert assertTrue(userService.isLogin()); } }

public class UserServiceTest extends AndroidTestCase { public void testLoginSuccess() throws Exception { // arrange PasswordValidator validator = Mockito.mock(PasswordValidator.class); Mockito.when(validator.checkEmailAndPassword(Matchers.anyString(), Matchers.anyString())).thenReturn(true); UserService userService = new UserService(getContext(), validator); // act userService.login("admin", "admin"); // assert assertTrue(userService.isLogin()); } }

public class UserServiceTest extends AndroidTestCase { public void testLoginSuccess() throws Exception { // arrange PasswordValidator validator = Mockito.mock(PasswordValidator.class); Mockito.when(validator.checkEmailAndPassword(Matchers.anyString(), Matchers.anyString())).thenReturn(true); UserService userService = new UserService(getContext(), validator); // act userService.login("whateverEmail", "whateverPassword"); // assert assertTrue(userService.isLogin()); } }

public class UserServiceTest extends AndroidTestCase { public void testLoginSuccess() throws Exception { // arrange PasswordValidator validator = Mockito.mock(PasswordValidator.class); Mockito.when(validator.checkEmailAndPassword(Matchers.anyString(), Matchers.anyString())).thenReturn(true); UserService userService = new UserService(getContext(), validator); // act userService.login("whateverEmail", "whateverPassword"); // assert assertTrue(userService.isLogin()); } }

public class UserServiceTest extends AndroidTestCase { public void testLoginSuccess() throws Exception { // arrange PasswordValidator validator = mock(PasswordValidator.class); when(validator.checkEmailAndPassword(anyString(), anyString())).thenReturn(true); UserService userService = new UserService(getContext(), validator); // act userService.login("whateverEmail", "whateverPassword"); // assert assertTrue(userService.isLogin()); } public void testLoginFailure() throws Exception { // arrange PasswordValidator validator = mock(PasswordValidator.class); when(validator.checkEmailAndPassword(anyString(), anyString())).thenReturn(false); UserService userService = new UserService(getContext(), validator); // act userService.login("whateverEmail", "whateverPassword"); // assert assertFalse(userService.isLogin()); } }

public class UserServiceTest extends AndroidTestCase { public void testLoginSuccess() throws Exception { // arrange PasswordValidator validator = mock(PasswordValidator.class); when(validator.checkEmailAndPassword(anyString(), anyString())).thenReturn(true); UserService userService = new UserService(getContext(), validator); // act userService.login("whateverEmail", "whateverPassword"); // assert assertTrue(userService.isLogin()); } public void testLoginFailure() throws Exception { // arrange PasswordValidator validator = mock(PasswordValidator.class); when(validator.checkEmailAndPassword(anyString(), anyString())).thenReturn(false); UserService userService = new UserService(getContext(), validator); // act userService.login("whateverEmail", "whateverPassword"); // assert assertFalse(userService.isLogin()); } }

• passed when running separately(sometimes?)

• passed when running separately(sometimes?)

• but failed running the whole tests

• passed when running separately(sometimes?)

• but failed running the whole tests

• WHY?

public boolean isLogin() { return loadLoginStatus(); } public boolean login(String email, String password) { if (mPasswordValidator.checkEmailAndPassword(email, password)) { saveLoginStatus(true); return true; } else { return false; } } private boolean loadLoginStatus() { return mSharedPreferences.getBoolean(SHARED_PREF_KEY_IS_LOGIN, false); } private void saveLoginStatus(boolean isLogin) { SharedPreferences.Editor editor = mSharedPreferences.edit(); editor.putBoolean(SHARED_PREF_KEY_IS_LOGIN, isLogin); editor.commit(); }

public class UserServiceTest extends AndroidTestCase { public void setUp() throws Exception { super.setUp(); clearSharedPref(); } private void clearSharedPref() { getContext().getSharedPreferences(UserService.SHARED_PREF_NAME, 0) .edit().clear().commit(); }

...

Works!!

Async Tasks

public class PasswordValidator { public boolean checkEmailAndPassword(String email, String password) { return email.equals("admin") && password.equals("admin"); } }

public class PasswordValidator { public boolean checkEmailAndPassword(String email, String password) { return email.equals("admin") && password.equals("admin"); } }

public class UserApiService { public void login(String email, String password, Callback callback) { // todo: send login request to server... } public interface Callback { void onSuccess(); void onFailure(); } }

public class UserApiService { public void login(String email, String password, Callback callback) { // todo: send login request to server... } public interface Callback { void onSuccess(); void onFailure(); } }

public class UserApiService { public void login(String email, String password, Callback callback) { if (checkEmailAndPassword(email, password)) wait2SecondsAndRespondSuccess(callback); } private boolean checkEmailAndPassword(String email, String password) { return email.equals("admin") && password.equals("admin"); } private void wait2SecondsAndRespondSuccess(final Callback callback) { new Handler().postDelayed(new Runnable() { @Override public void run() { callback.onSuccess(); } }, 2000); } public interface Callback { void onSuccess(); void onFailure(); } }

public class UserService { private PasswordValidator mPasswordValidator; ...

public UserService(Context appContext, PasswordValidator validator) { mPasswordValidator = validator; ... } public boolean login(String email, String password) { if (mPasswordValidator.checkEmailAndPassword(email, password)) { saveLoginStatus(true); return true; } else { return false; } } ...

}

public class UserService { private UserApiService mUserApiService; ...

public UserService(Context appContext, UserApiService userApiService) { mUserApiService = userApiService; ... } public void login(String email, String password, final Callback callback) { mUserApiService.login(email, password, new Callback() { @Override public void onSuccess() { saveLoginStatus(true); callback.onSuccess(); } @Override public void onFailure() { callback.onFailure(); } }); } ...

public class MainActivity extends Activity { ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mEmailEditText = (EditText) findViewById(R.id.email); mPasswordEditText = (EditText) findViewById(R.id.password); mUserService = new UserService(getApplicationContext(), new PasswordValidator()); } public void onEnterButtonClick(View view) { String email = mEmailEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); boolean isLoginSuccess = mUserService.login(email, password); if (isLoginSuccess) goToSecondPage(); } ...

public class MainActivity extends Activity { ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mEmailEditText = (EditText) findViewById(R.id.email); mPasswordEditText = (EditText) findViewById(R.id.password); mUserService = new UserService(getApplicationContext(), new UserApiService()); } public void onEnterButtonClick(View view) { String email = mEmailEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); mUserService.login(email, password, new UserApiService.Callback() { @Override public void onSuccess() { goToSecondPage(); } @Override public void onFailure() { } }); } ...

Unit Test

public void testLoginSuccess() throws Exception { // arrange PasswordValidator validator = mock(PasswordValidator.class); when(validator.checkEmailAndPassword(anyString(), anyString())).thenReturn(true); UserService userService = new UserService(getContext(), validator); // act userService.login("whateverEmail", "whateverPassword"); // assert assertTrue(userService.isLogin()); }

public void testLoginSuccess() throws Exception { // arrange UserApiService userApiService = mock(UserApiService.class); doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Callback callback = (Callback) invocation.getArguments()[2]; callback.onSuccess(); return null; } }).when(userApiService).login(anyString(), anyString(), any(Callback.class)); UserService userService = new UserService(getContext(), userApiService); // act userService.login("whateverEmail", "whateverPassword", mock(Callback.class)); // assert assertTrue(userService.isLogin()); }

public void testLoginSuccess() throws Exception { // arrange UserApiService userApiService = mock(UserApiService.class); doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Callback callback = (Callback) invocation.getArguments()[2]; callback.onSuccess(); return null; } }).when(userApiService).login(anyString(), anyString(), any(Callback.class)); UserService userService = new UserService(getContext(), userApiService); // act userService.login("whateverEmail", "whateverPassword", mock(Callback.class)); // assert assertTrue(userService.isLogin()); }

public void testLoginSuccess() throws Exception { // arrange UserApiService userApiService = mock(UserApiService.class); doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Callback callback = (Callback) invocation.getArguments()[2]; callback.onSuccess(); return null; } }).when(userApiService).login(anyString(), anyString(), any(Callback.class)); UserService userService = new UserService(getContext(), userApiService); // act userService.login("whateverEmail", "whateverPassword", mock(Callback.class)); // assert assertTrue(userService.isLogin()); }

public void testLoginSuccess() throws Exception { // arrange UserApiService userApiService = mock(UserApiService.class); doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Callback callback = (Callback) invocation.getArguments()[2]; callback.onSuccess(); return null; } }).when(userApiService).login(anyString(), anyString(), any(Callback.class)); UserService userService = new UserService(getContext(), userApiService); // act userService.login("whateverEmail", "whateverPassword", mock(Callback.class)); // assert assertTrue(userService.isLogin()); }

public void testLoginSuccess() throws Exception { // arrange UserApiService userApiService = mock(UserApiService.class); doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Callback callback = (Callback) invocation.getArguments()[2]; callback.onSuccess(); return null; } }).when(userApiService).login(anyString(), anyString(), any(Callback.class)); UserService userService = new UserService(getContext(), userApiService); // act userService.login("whateverEmail", "whateverPassword", mock(Callback.class)); // assert assertTrue(userService.isLogin()); }

public void testLoginSuccess() throws Exception { // arrange UserApiService userApiService = mock(UserApiService.class); doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Callback callback = (Callback) invocation.getArguments()[2]; callback.onSuccess(); return null; } }).when(userApiService).login(anyString(), anyString(), any(Callback.class)); UserService userService = new UserService(getContext(), userApiService); // act userService.login("whateverEmail", "whateverPassword", mock(Callback.class)); // assert assertTrue(userService.isLogin()); }

public void testLoginSuccess() throws Exception { // arrange UserApiService userApiService = mock(UserApiService.class); doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Callback callback = (Callback) invocation.getArguments()[2]; callback.onSuccess(); return null; } }).when(userApiService).login(anyString(), anyString(), any(Callback.class)); UserService userService = new UserService(getContext(), userApiService); // act userService.login("whateverEmail", "whateverPassword", mock(Callback.class)); // assert assertTrue(userService.isLogin()); } public void testLoginFailure() throws Exception { // arrange UserApiService userApiService = mock(UserApiService.class); doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Callback callback = (Callback) invocation.getArguments()[2]; callback.onFailure(); return null; } }).when(userApiService).login(anyString(), anyString(), any(Callback.class)); UserService userService = new UserService(getContext(), userApiService); // act userService.login("whateverEmail", "whateverPassword", mock(Callback.class)); // assert assertFalse(userService.isLogin()); }

Works!!

UI Test

1.

2.

3.public class MainActivityTest extends TestCase { }

public class MainActivityTest extends TestCase { }

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> { public MainActivityTest() { super(MainActivity.class); }}

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> { public MainActivityTest() { super(MainActivity.class); } public void setUp() throws Exception { super.setUp(); clearSharedPref(); getActivity(); } private void clearSharedPref() { getInstrumentation().getTargetContext().getSharedPreferences (UserService.SHARED_PREF_NAME, 0).edit().clear().commit(); } }

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {

... public void testLayout() throws Exception { // arrange // act // assert Espresso.onView(ViewMatchers.withId(R.id.email)) .check(ViewAssertions.matches(ViewMatchers.isDisplayed())); Espresso.onView(ViewMatchers.withId(R.id.password)) .check(ViewAssertions.matches(ViewMatchers.isDisplayed())); Espresso.onView(ViewMatchers.withId(R.id.enter_button)) .check(ViewAssertions.matches(ViewMatchers.isDisplayed())); }}

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {

... public void testLayout() throws Exception { // arrange // act // assert Espresso.onView(ViewMatchers.withId(R.id.email)) .check(ViewAssertions.matches(ViewMatchers.isDisplayed())); Espresso.onView(ViewMatchers.withId(R.id.password)) .check(ViewAssertions.matches(ViewMatchers.isDisplayed())); Espresso.onView(ViewMatchers.withId(R.id.enter_button)) .check(ViewAssertions.matches(ViewMatchers.isDisplayed())); }}

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {

... public void testLayout() throws Exception { // arrange // act // assert onView(withId(R.id.email)) .check(matches(isDisplayed())); onView(withId(R.id.password)) .check(matches(isDisplayed())); onView(withId(R.id.enter_button)) .check(matches(isDisplayed())); }}

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {

... public void testLayout() throws Exception { // arrange // act // assert onView(withId(R.id.email)) .check(matches(isDisplayed())); onView(withId(R.id.password)) .check(matches(isDisplayed())); onView(withId(R.id.enter_button)) .check(matches(isDisplayed())); }}

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {

... public void testLayout() throws Exception { // arrange // act // assert onView(withId(R.id.email)) .check(matches(isDisplayed())); onView(withId(R.id.password)) .check(matches(isDisplayed())); onView(withId(R.id.enter_button)) .check(matches(isDisplayed())); }}

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {

... public void testLayout() throws Exception { // arrange // act // assert onView(withId(R.id.email)) .check(matches(isDisplayed())); onView(withId(R.id.password)) .check(matches(isDisplayed())); onView(withId(R.id.enter_button)) .check(matches(isDisplayed())); }}

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {

... public void testLayout() throws Exception { // arrange // act // assert onView(withId(R.id.email)) .check(matches(isDisplayed())); onView(withId(R.id.password)) .check(matches(isDisplayed())); onView(withId(R.id.enter_button)) .check(matches(isDisplayed())); }} Works!!

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {

... public void testLoginSuccess() throws Exception { // arrange // act onView(ViewMatchers.withId(R.id.email)) .perform(typeText("whateverEmail")); onView(ViewMatchers.withId(R.id.password)) .perform(typeText("whateverPassword")); onView(ViewMatchers.withId(R.id.enter_button)) .perform(click()); // assert onView(withText("Second Page")) .check(matches(isDisplayed())); }}

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {

... public void testLoginSuccess() throws Exception { // arrange // act onView(withId(R.id.email)) .perform(typeText("whateverEmail")); onView(ViewMatchers.withId(R.id.password)) .perform(typeText("whateverPassword")); onView(ViewMatchers.withId(R.id.enter_button)) .perform(click()); // assert onView(withText("Second Page")) .check(matches(isDisplayed())); }}

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {

... public void testLoginSuccess() throws Exception { // arrange // act onView(withId(R.id.email)) .perform(typeText("whateverEmail")); onView(withId(R.id.password)) .perform(typeText("whateverPassword")); onView(ViewMatchers.withId(R.id.enter_button)) .perform(click()); // assert onView(withText("Second Page")) .check(matches(isDisplayed())); }}

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {

... public void testLoginSuccess() throws Exception { // arrange // act onView(withId(R.id.email)) .perform(typeText("whateverEmail")); onView(withId(R.id.password)) .perform(typeText("whateverPassword")); onView(withId(R.id.enter_button)) .perform(click()); // assert onView(withText("Second Page")) .check(matches(isDisplayed())); }}

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {

... public void testLoginSuccess() throws Exception { // arrange // act onView(withId(R.id.email)) .perform(typeText("whateverEmail")); onView(withId(R.id.password)) .perform(typeText("whateverPassword")); onView(withId(R.id.enter_button)) .perform(click()); // assert onView(withText("Second Page")) .check(matches(isDisplayed())); }}

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {

... public void testLoginSuccess() throws Exception { // arrange // act onView(withId(R.id.email)) .perform(typeText("whateverEmail")); onView(withId(R.id.password)) .perform(typeText("whateverPassword")); onView(withId(R.id.enter_button)) .perform(click()); // assert onView(withText("Second Page")) .check(matches(isDisplayed())); }}

after doing some research…

use Dagger2 for Dependency Injection

public class MainActivity extends AppCompatActivity {

... @Inject UserService mUserService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); UserServiceComponent.Initializer.init(getApplicationContext()).inject(this); ... } public void onEnterButtonClick(View view) { String email = mEmailEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); mUserService.login(email, password, new UserApiService.Callback() { @Override public void onSuccess() { goToSecondPage(); } @Override public void onFailure() { } }); }

public class MainActivity extends AppCompatActivity {

... @Inject UserService mUserService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); UserServiceComponent.Initializer.init(getApplicationContext()).inject(this); ... }

public void onEnterButtonClick(View view) { String email = mEmailEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); mUserService.login(email, password, new UserApiService.Callback() { @Override public void onSuccess() { goToSecondPage(); } @Override public void onFailure() { } }); }

public class MainActivity extends AppCompatActivity {

... @Inject UserService mUserService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); UserServiceComponent.Initializer.init(getApplicationContext()).inject(this); ... } public void onEnterButtonClick(View view) { String email = mEmailEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); mUserService.login(email, password, new UserApiService.Callback() { @Override public void onSuccess() { goToSecondPage(); } @Override public void onFailure() { } }); }

@Provides @Singleton UserService provideUserService(UserApiService userApiService){ return new UserService(mAppContext, userApiService); }

release

public class MainActivity extends AppCompatActivity {

... @Inject UserService mUserService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); UserServiceComponent.Initializer.init(getApplicationContext()).inject(this); ... } public void onEnterButtonClick(View view) { String email = mEmailEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); mUserService.login(email, password, new UserApiService.Callback() { @Override public void onSuccess() { goToSecondPage(); } @Override public void onFailure() { } }); }

@Provides @Singleton UserService provideUserService(UserApiService userApiService){ return new UserService(mAppContext, userApiService); }

release

public class MainActivity extends AppCompatActivity {

... @Inject UserService mUserService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); UserServiceComponent.Initializer.init(getApplicationContext()).inject(this); ... } public void onEnterButtonClick(View view) { String email = mEmailEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); mUserService.login(email, password, new UserApiService.Callback() { @Override public void onSuccess() { goToSecondPage(); } @Override public void onFailure() { } }); }

@Provides @Singleton UserService provideTestUserService(UserApiService userApiService){ return mMockUserService; }

@Provides @Singleton UserService provideUserService(UserApiService userApiService){ return new UserService(mAppContext, userApiService); }

debug

public class MainActivity extends AppCompatActivity {

... @Inject UserService mUserService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); UserServiceComponent.Initializer.init(getApplicationContext()).inject(this); ... } public void onEnterButtonClick(View view) { String email = mEmailEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); mUserService.login(email, password, new UserApiService.Callback() { @Override public void onSuccess() { goToSecondPage(); } @Override public void onFailure() { } }); }

@Provides @Singleton UserService provideTestUserService(UserApiService userApiService){ return mMockUserService; }

@Provides @Singleton UserService provideUserService(UserApiService userApiService){ return new UserService(mAppContext, userApiService); }

debug

public class MainActivity extends AppCompatActivity {

... @Inject UserService mUserService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); UserServiceComponent.Initializer.init(getApplicationContext()).inject(this); ... } public void onEnterButtonClick(View view) { String email = mEmailEditText.getText().toString(); String password = mPasswordEditText.getText().toString(); mUserService.login(email, password, new UserApiService.Callback() { @Override public void onSuccess() { goToSecondPage(); } @Override public void onFailure() { } }); }

@Provides @Singleton UserService provideTestUserService(UserApiService userApiService){ return mMockUserService; }

@Provides @Singleton UserService provideUserService(UserApiService userApiService){ return new UserService(mAppContext, userApiService); }

debug

Keep Instance

@Provides @Singleton UserService provideTestUserService(UserApiService userApiService){ return mMockUserService; }

@Provides @Singleton UserService provideTestUserService(UserApiService userApiService){ return mMockUserService; }

public class MainActivityTest extends MainActivityTestCase { public void setUp() throws Exception { super.setUp(); getActivity(); UserServiceComponent.Initializer.getInstance().inject(this); }

@Provides @Singleton UserService provideTestUserService(UserApiService userApiService){ return mMockUserService; }

public class MainActivityTest extends MainActivityTestCase { public void setUp() throws Exception { super.setUp(); getActivity(); UserServiceComponent.Initializer.getInstance().inject(this); }

public class MainActivity extends AppCompatActivity {

... @Inject UserService mUserService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); UserServiceComponent.Initializer.init(getApplicationContext()).inject(this); ... } public void onEnterButtonClick(View view) { String email = mEmailEditText.getText().toString();

@Provides @Singleton UserService provideTestUserService(UserApiService userApiService){ return mMockUserService; }

Keep Instance

public class MainActivityTest extends MainActivityTestCase { public void setUp() throws Exception { super.setUp(); getActivity(); UserServiceComponent.Initializer.getInstance().inject(this); }

public class MainActivity extends AppCompatActivity {

... @Inject UserService mUserService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); UserServiceComponent.Initializer.init(getApplicationContext()).inject(this); ... } public void onEnterButtonClick(View view) { String email = mEmailEditText.getText().toString();

@Provides @Singleton UserService provideTestUserService(UserApiService userApiService){ return mMockUserService; }

Keep Instance

public class MainActivityTest extends MainActivityTestCase { public void setUp() throws Exception { super.setUp(); getActivity(); UserServiceComponent.Initializer.getInstance().inject(this); }

public class MainActivity extends AppCompatActivity {

... @Inject UserService mUserService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); UserServiceComponent.Initializer.init(getApplicationContext()).inject(this); ... } public void onEnterButtonClick(View view) { String email = mEmailEditText.getText().toString();

@Provides @Singleton UserService provideTestUserService(UserApiService userApiService){ return mMockUserService; }

Keep Instance

public class MainActivityTest extends MainActivityTestCase { public void setUp() throws Exception { super.setUp(); getActivity(); UserServiceComponent.Initializer.getInstance().inject(this); }

@Provides @Singleton UserService provideTestUserService(UserApiService userApiService){ return mMockUserService; }

Keep Instance

public class MainActivityTest extends MainActivityTestCase { public void setUp() throws Exception { super.setUp(); getActivity(); UserServiceComponent.Initializer.getInstance().inject(this); }

public class MainActivityTestCase extends ActivityInstrumentationTestCase2<MainActivity> { @Inject protected UserService mMockUserService; public MainActivityTestCase() { super(MainActivity.class); } }

@Provides @Singleton UserService provideTestUserService(UserApiService userApiService){ return mMockUserService; }

Keep Instance

public class MainActivityTest extends MainActivityTestCase { public void setUp() throws Exception { super.setUp(); getActivity(); UserServiceComponent.Initializer.getInstance().inject(this); }

public class MainActivityTestCase extends ActivityInstrumentationTestCase2<MainActivity> { @Inject protected UserService mMockUserService; public MainActivityTestCase() { super(MainActivity.class); } }

public class MainActivityTest extends MainActivityTestCase {

... public void testLoginSuccess() throws Exception { // arrange // act onView(ViewMatchers.withId(R.id.email)) .perform(typeText("whateverEmail")); onView(ViewMatchers.withId(R.id.password)) .perform(typeText("whateverPassword")); onView(ViewMatchers.withId(R.id.enter_button)) .perform(click()); // assert onView(withText("Second Page")) .check(matches(isDisplayed())); }}

public class MainActivityTest extends MainActivityTestCase {

... public void testLoginSuccess() throws Exception { // arrange doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { UserApiService.Callback callback = (UserApiService.Callback) invocation.getArguments()[2]; callback.onSuccess(); return null; } }).when(mMockUserService).login(anyString(), anyString(), any(UserApiService.Callback.class)); // act onView(withId(R.id.email)) .perform(ViewActions.typeText("whateverEmail")); onView(withId(R.id.password)) .perform(ViewActions.typeText("whateverPassword")); onView(withId(R.id.enter_button)) .perform(ViewActions.click()); // assert onView(withText("Second Page")) .check(ViewAssertions.matches(isDisplayed())); }

...

public class MainActivityTest extends MainActivityTestCase {

... public void testLoginSuccess() throws Exception { // arrange doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { UserApiService.Callback callback = (UserApiService.Callback) invocation.getArguments()[2]; callback.onSuccess(); return null; } }).when(mMockUserService).login(anyString(), anyString(), any(UserApiService.Callback.class)); // act onView(withId(R.id.email)) .perform(ViewActions.typeText("whateverEmail")); onView(withId(R.id.password)) .perform(ViewActions.typeText("whateverPassword")); onView(withId(R.id.enter_button)) .perform(ViewActions.click()); // assert onView(withText("Second Page")) .check(ViewAssertions.matches(isDisplayed())); }

...

public class MainActivityTest extends MainActivityTestCase {

... public void testLoginSuccess() throws Exception { // arrange doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { UserApiService.Callback callback = (UserApiService.Callback) invocation.getArguments()[2]; callback.onSuccess(); return null; } }).when(mMockUserService).login(anyString(), anyString(), any(UserApiService.Callback.class)); // act onView(withId(R.id.email)) .perform(ViewActions.typeText("whateverEmail")); onView(withId(R.id.password)) .perform(ViewActions.typeText("whateverPassword")); onView(withId(R.id.enter_button)) .perform(ViewActions.click()); // assert onView(withText("Second Page")) .check(ViewAssertions.matches(isDisplayed())); }

...

public class MainActivityTest extends MainActivityTestCase {

... public void testLoginSuccess() throws Exception { // arrange doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { UserApiService.Callback callback = (UserApiService.Callback) invocation.getArguments()[2]; callback.onSuccess(); return null; } }).when(mMockUserService).login(anyString(), anyString(), any(UserApiService.Callback.class)); // act onView(withId(R.id.email)) .perform(ViewActions.typeText("whateverEmail")); onView(withId(R.id.password)) .perform(ViewActions.typeText("whateverPassword")); onView(withId(R.id.enter_button)) .perform(ViewActions.click()); // assert onView(withText("Second Page")) .check(ViewAssertions.matches(isDisplayed())); }

...

Works!!

• sometimes failed

• static variable

• local storage

• not easy to test all stuff

• no a best way you can follow

frequent problems

• Pattern (MVP, DI)

• Structure

• follow up the android geeks

what I learned

• mock object called when activity onCreate

• UI testing for a fragment with interaction with certain activity

• find out the best test sturcture

still need to figure out

• https://github.com/proevan/android-testing-sample