Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Android Testing 2.0

Android Testing 2.0

Build a toolset to write rock solid apps.

Avatar for Prateek Srivastava

Prateek Srivastava

April 10, 2015
Tweet

More Decks by Prateek Srivastava

Other Decks in Technology

Transcript

  1. public class UtilsTest extends TestCase { public void testIsNullOrEmpty() {

    assertEquals(isNullOrEmpty(null), true); assertEquals(isNullOrEmpty(""), true); assertEquals(isNullOrEmpty(" "), true); assertEquals(isNullOrEmpty("foo"), false); } }
  2. public class UtilsTest { @Test public void isNullOrEmpty() { assertEquals(isNullOrEmpty(null),

    true); assertEquals(isNullOrEmpty(""), true); assertEquals(isNullOrEmpty(" "), true); assertEquals(isNullOrEmpty("foo"), false); } }
  3. public class TextUtils { ... public static boolean isEmpty(CharSequence cs)

    { throw new RuntimeException("Stub!"); } public static int getTrimmedLength(CharSequence cs) { throw new RuntimeException("Stub!"); } }
  4. public class UtilsTest extends TestCase { public void testIsNullOrEmpty() {

    assertEquals(isNullOrEmpty(null), true); assertEquals(isNullOrEmpty(""), true); assertEquals(isNullOrEmpty(" "), true); assertEquals(isNullOrEmpty("foo"), false); } } http://developer.android.com/reference/junit/framework/ TestCase.html
  5. @RunWith(RobolectricTestRunner.class) public class UtilsTest { @Test public void isNullOrEmpty() {

    assertEquals(isNullOrEmpty(null), true); assertEquals(isNullOrEmpty(""), true); assertEquals(isNullOrEmpty(" "), true); assertEquals(isNullOrEmpty("foo"), false); } }
  6. @RunWith(RobolectricTestRunner.class) public class UtilsTest { @Test public void isNullOrEmpty() {

    assertEquals(isNullOrEmpty(null), true); assertEquals(isNullOrEmpty(""), true); assertEquals(isNullOrEmpty(" "), true); assertEquals(isNullOrEmpty("foo"), false); } }
  7. Instrumentation Tests larger scoped, black box testing Espresso, Spoon, Wiremock,

    Oh my! - Michael Bailey https://www.youtube.com/watch?v=-xQCNf_5NNM
  8. public class LoginActivity extends Activity { @InjectView(R.id.username) EditText username; @InjectView(R.id.password)

    EditText password; @OnClick(R.id.login) void onLoginClicked() { boolean hasError = false; if (TextUtils.isEmpty(username.getText())) { username.setError(getString(R.string.required)); hasError = true; } else { username.setError(null); } if (TextUtils.isEmpty(password.getText())) { password.setError(getString(R.string.required)); hasError = true; } else { password.setError(null); } if (!hasError) { Intent intent = new Intent(LoginActivity.this, OrderActivity.class); intent.setFlags(FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); finish(); } } }
  9. public void testEmptyPassword_ShowsError() { // Make sure the initial state

    does not show any errors. assertEquals(username.getError(), null); assertEquals(password.getError(), null); instrumentation.runOnMainSync(new Runnable() { @Override public void run() { // Type a value into the username and password fields. username.setText("elvis"); password.setText(""); // Click the "login" button. login.performClick(); } }); instrumentation.waitForIdleSync(); // Verify error was shown only for password field. assertEquals(username.getError(), null); assertEquals(password.getError(), getString(R.string.required)); }
  10. public void testEmptyPassword_ShowsError() { // Make sure the initial state

    does not show any errors. assertEquals(username.getError(), null); assertEquals(password.getError(), null); instrumentation.runOnMainSync(new Runnable() { @Override public void run() { // Type a value into the username and password fields. username.setText("elvis"); password.setText(""); // Click the "login" button. login.performClick(); } }); instrumentation.waitForIdleSync(); // Verify error was shown only for password field. assertEquals(username.getError(), null); assertEquals(password.getError(), getString(R.string.required)); }
  11. public void testEmptyPassword_ShowsError() { // Make sure the initial state

    does not show any errors. assertThat(username).hasNoError(); assertThat(password).hasNoError(); // Type a value into the username and password fields. solo.typeText(username, "elvis"); solo.typeText(password, ""); // Click the "login" button. solo.clickOnView(login); // Verify error was shown only for username field. assertThat(username).hasNoError(); assertThat(password).hasError(R.string.required); }
  12. public void testEmptyPassword_ShowsError() { // Make sure the initial state

    does not show any errors. onView(withId(R.id.username)).check(matches(hasNoError())); onView(withId(R.id.password)).check(matches(hasNoError())); // Type a value into the username and password fields. onView(withId(R.id.username)).perform(typeText("elvis")); onView(withId(R.id.password)).perform(typeText("")); // Click the "login" button. onView(withId(R.id.login)).perform(click()); // Verify error was shown only for username field. onView(withId(R.id.password)).check(matches(hasNoError())); onView(withId(R.id.password)) .check(matches(hasError(R.string.required))); } https://code.google.com/p/android-test-kit/wiki/ EspressoV2CheatSheet
  13. public void testEmptyPassword_ShowsError() { Spoon.screenshot(activity, "initial_state"); // Make sure the

    initial state does not show any errors. onView(withId(R.id.username)).check(matches(hasNoError())); onView(withId(R.id.password)).check(matches(hasNoError())); // Type a value into the username and password fields. onView(withId(R.id.username)).perform(typeText("elvis")); onView(withId(R.id.password)).perform(typeText("")); Spoon.screenshot(activity, "typed_text"); // Click the "login" button. onView(withId(R.id.login)).perform(click()); Spoon.screenshot(activity, "login_clicked"); // Verify error was shown only for username field. onView(withId(R.id.password)).check(matches(hasNoError())); onView(withId(R.id.password)) .check(matches(hasError(R.string.required))); }
  14. public void testEmptyPassword_ShowsError() { Spoon.screenshot(activity, "initial_state"); // Make sure the

    initial state does not show any errors. onView(withId(R.id.username)).check(matches(hasNoError())); onView(withId(R.id.password)).check(matches(hasNoError())); // Type a value into the username and password fields. onView(withId(R.id.username)).perform(typeText("elvis")); onView(withId(R.id.password)).perform(typeText("")); Spoon.screenshot(activity, "typed_text"); // Click the "login" button. onView(withId(R.id.login)).perform(click()); Spoon.screenshot(activity, "login_clicked"); // Verify error was shown only for username field. onView(withId(R.id.password)).check(matches(hasNoError())); onView(withId(R.id.password)) .check(matches(hasError(R.string.required))); }
  15. class MixpanelAdapter implements Adapter { final MixpanelAPI.People people; … void

    identify(IdentifyMessage message) { JSONObject json = new JSONObject(); json.put("$email", message.email()); json.put("$first_name", message.firstName()); json.put("$last_name", message.lastName()); people.identify(message.userId()); people.set(json); } }
  16. @Test public void identify() throws JSONException { // 1. Prepare

    our mocks MixpanelAPI.People people = Mockito.mock(MixpanelAPI.People.class); MixpanelAdapter adapter = mockAdapter(people); Analytics analytics = createAnalyticsWithMock(adapter); // 2. Exercise the test analytics.identify("elvis", new Traits() .putFirstName("Elvis") .putLastName("Presley") .putEmail("[email protected]")); JSONObject expected = new JSONObject(); expected.put("userId", "elvis"); expected.put("$email", "[email protected]"); expected.put("$first_name", "Elvis"); expected.put("$last_name", "Presley"); // 3. Verify that we saw what we expected Mockito.verify(people).identify("elvis"); Mockito.verify(people).set(eq(expected)); }
  17. class LocalyticsAdapter implements Adapter { void identify(IdentifyMessage message) { Localytics.setCustomerId(message.userId());

    Localytics.setIdentifier("email", message.email()); Localytics.setIdentifier("customer_name", message.name()); } }
  18. @Test public void identify() { // 1. Prepare mocks. PowerMockito.mockStatic(Localytics.class);

    Analytics analytics = createAnalytics(); // 2. Test the code of interest. analytics.identify("elvis", new Traits() .putFirstName("Elvis") .putLastName("Presley") .putEmail("[email protected]")); // 3. Validate that we saw exactly what we wanted. PowerMockito.verifyStatic(); Localytics.setCustomerId("elvis"); PowerMockito.verifyStatic(); Localytics.setIdentifier("email", "[email protected]"); PowerMockito.verifyStatic(); Localytics.setIdentifier("customer_name", "Elvis Presley"); }
  19. public void test() throws Exception { // Create a MockWebServer.

    MockWebServer server = new MockWebServer(); // Schedule some responses. server.enqueue(new MockResponse().setBody("hello, world!")); // Start the server. server.start(); // Ask the server for its URL. You'll need this to make HTTP requests. URL baseUrl = server.getUrl(“/v1/chat/“); // Exercise your application code, which makes those HTTP requests. // Responses are returned in the same order that they are enqueued. Chat chat = new Chat(baseUrl); chat.loadMore(); assertThat(chat.messages()).containsExactly("hello, world!"); // Confirm that your app made the HTTP requests you were expecting. RecordedRequest request1 = server.takeRequest(); assertEquals("/v1/chat/messages/", request1.getPath()); assertThat(request1.getHeader("Authorization")).isNotNull(); // Shut down the server. server.shutdown(); }
  20. public class MyBenchmark extends Benchmark { public void timeMyOperation(int reps)

    { for (int i = 0; i < reps; i++) { MyClass.myOperation(); } } }