Integrate EndToEnd tests and removed unused tests projects

This commit is contained in:
Plonk42
2016-02-16 23:43:00 +01:00
parent b90c680805
commit aba8cb4090
116 changed files with 3 additions and 11463 deletions
+3
View File
@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
@@ -0,0 +1,65 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest;
import android.os.Bundle;
import android.test.InstrumentationTestRunner;
import android.util.Log;
/**
* End-to-end test test runner.
*
* @author Youtao Liu
*/
public class EndToEndTestRunner extends InstrumentationTestRunner {
private static final String TAG = EndToEndTestRunner.class.getSimpleName();
private static final String PORT_KEY = "port";
private static final String RESOURCE_KEY = "resource";
private static final String SENSOR_KEY = "sensor";
private static final String STRESS_KEY = "stress";
private static final String TRUE_VALUE = "true";
@Override
public void onCreate(Bundle bundle) {
// Get the emulator port parameter for GPS signals
String port = bundle.getString(PORT_KEY);
if (port != null) {
try {
EndToEndTestUtils.emulatorPort = Integer.parseInt(port);
} catch (Exception e) {
Log.e(TAG, "Unable to get emulator port parameter, use the default value.", e);
}
}
Log.d(TAG, "Emulator port: " + EndToEndTestUtils.emulatorPort);
RunConfiguration runConfiguration = RunConfiguration.getInstance();
runConfiguration.setRunResourceTest(
TRUE_VALUE.equalsIgnoreCase(bundle.getString(RESOURCE_KEY)));
Log.d(TAG, "Run resource test: " + runConfiguration.getRunResourceTest());
runConfiguration.setRunSensorTest(TRUE_VALUE.equalsIgnoreCase(bundle.getString(SENSOR_KEY)));
Log.d(TAG, "Run sensor test: " + runConfiguration.getRunSensorTest());
runConfiguration.setRunStressTest(TRUE_VALUE.equalsIgnoreCase(bundle.getString(STRESS_KEY)));
Log.d(TAG, "Run stress test: " + runConfiguration.getRunStressTest());
super.onCreate(bundle);
}
}
@@ -0,0 +1,936 @@
package com.google.android.apps.mytracks.endtoendtest;
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.maps.mytracks.R;
import com.robotium.solo.Solo;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.content.res.Configuration;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import junit.framework.Assert;
/**
* Provides utilities to smoke test.
*
* @author Youtao Liu
*/
public class EndToEndTestUtils {
public static final int TINY_WAIT_TIME = 200;
public static final int VERY_SHORT_WAIT_TIME = 500;
public static final int SHORT_WAIT_TIME = 2000;
public static final int NORMAL_WAIT_TIME = 8000;
public static final int LONG_WAIT_TIME = 15000;
public static final int SUPER_LONG_WAIT_TIME = 100000;
// Pause 200ms between each send.
public static final double START_LONGITUDE = 51;
public static final double START_LATITUDE = -1.3f;
public static final double DELTA_LONGITUDE = 0.0005f;
public static final double DELTA_LADITUDE = 0.0005f;
public static final String WAYPOINT_NAME = "testWaypoint";
public static final String WAYPOINT_TYPE = "testWaypoinType";
public static final String WAYPOINT_DESCRIPTION = "testWaypointDesc";
public static final String DEFAULT_ACTIVITY_TYPE = "TestActivity";
public static final String TRACK_NAME_PREFIX = "testTrackName";
private static final String TAG = EndToEndTestUtils.class.getSimpleName();
private static final String TRACK_DESCRIPTION_PREFIX = "testTrackDesc";
private static final int ORIENTATION_PORTRAIT = 1;
private static final int ORIENTATION_LANDSCAPE = 0;
private static final String ANDROID_LOCAL_IP = "10.0.2.2";
private static final String NO_GPS_MESSAGE_PREFIX = "GPS is not available";
private static final String MORE_OPTION_CLASSNAME = "com.android.internal.view.menu.ActionMenuPresenter$OverflowMenuButton";
private static final String MENUITEM_CLASSNAME = "com.android.internal.view.menu.IconMenuItemView";
// Following is some check strings in English and Chinese
private static final HashMap<String, String>
RELATIVE_START_TIME_SUFFIX_MULTILINGUAL = new HashMap<String, String>();
static {
RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.put("en", "mins ago");
RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.put("de", "Minuten");
RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.put("fr", "minute");
RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.put("ar", "دقيقة");
RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.put("zh", "分钟前");
}
public static int emulatorPort = 5554; // usually 5554.
public static String activityType = DEFAULT_ACTIVITY_TYPE;
public static String trackName;
public static String trackDescription;
public static com.robotium.solo.Solo SOLO;
public static Instrumentation instrumentation;
public static TrackListActivity trackListActivity;
/*
* Check whether the UI has an action bar which is related with the version of
* Android OS.
*/
public static boolean hasActionBar = false;
public static boolean isEmulator = true;
public static boolean hasGpsSignal = true;
private static boolean isCheckedFirstLaunch = false;
private static boolean isGooglePlayServicesLatest = true;
private static String language;
private EndToEndTestUtils() {};
/**
* Checks the language, then sets the fields with right string.
*/
private static void checkLanguage() {
Locale locale = new Locale("en");
Locale.setDefault(locale);
Configuration configuration = trackListActivity.getBaseContext()
.getResources().getConfiguration();
configuration.locale = locale;
language = instrumentation.getContext().getResources().getConfiguration().locale.getLanguage();
}
/**
* Sends Gps data to emulator, and the start value has an offset.
*
* @param number send times
* @param offset is used to compute the start latitude and longitude
* @param pause pause interval between each sending
*/
public static void sendGps(int number, int offset, int pause) {
if (number < 1) {
return;
}
int pauseInterval = TINY_WAIT_TIME;
if (pause != -1) {
pauseInterval = pause;
}
// If it's a real device, does not send simulated GPS signal.
if (!isEmulator) {
return;
}
PrintStream out = null;
Socket socket = null;
try {
socket = new Socket(ANDROID_LOCAL_IP, emulatorPort);
out = new PrintStream(socket.getOutputStream());
double longitude = START_LONGITUDE + offset * DELTA_LONGITUDE;
double latitude = START_LATITUDE + offset * DELTA_LADITUDE;
for (int i = 0; i < number; i++) {
out.println("geo fix " + longitude + " " + latitude);
longitude += DELTA_LONGITUDE;
latitude += DELTA_LADITUDE;
Thread.sleep(pauseInterval);
}
// Wait the GPS signal can be obtained by MyTracks.
Thread.sleep(SHORT_WAIT_TIME);
} catch (UnknownHostException e) {
System.exit(-1);
} catch (IOException e) {
System.exit(-1);
} catch (InterruptedException e) {
System.exit(-1);
} finally {
if (out != null) {
out.close();
}
}
}
/**
* Send Gps data to emulator.
*
* @param number number of signals
* @param offset is used to compute the start latitude and longitude
*/
public static void sendGps(int number, int offset) {
sendGps(number, offset, -1);
}
/**
* Send Gps data to emulator.
*
* @param number number of signals
*/
public static void sendGps(int number) {
sendGps(number, 0, -1);
}
/**
* Sets the status whether the test is run on an emulator or not.
*/
private static void setIsEmulator() {
isEmulator = android.os.Build.MODEL.equals("google_sdk");
}
/**
* Checks whether the Google Play Services need update.
*/
private static boolean isGooglePlayServicesLatest() {
return findTextView("Google Play services") == null;
}
/**
* A setup for debugging end-to-end tests.
*
* @param inst the instrumentation
* @param activity the track list activity
*/
public static void setupForDebug(Instrumentation inst, TrackListActivity activity) {
instrumentation = inst;
trackListActivity = activity;
SOLO = new Solo(instrumentation, trackListActivity);
setIsEmulator();
hasActionBar = setHasActionBar();
checkLanguage();
}
/**
* A setup for all end-to-end tests.
*
* @param inst the instrumentation
* @param activity the track list activity
*/
public static void setupForAllTest(Instrumentation inst, TrackListActivity activity) {
instrumentation = inst;
trackListActivity = activity;
SOLO = new Solo(instrumentation, trackListActivity);
if (!isGooglePlayServicesLatest) {
SOLO.finishOpenedActivities();
Assert.fail();
Log.e(TAG, "Need update Google Play Services");
}
// Check if open MyTracks first time after install. If so, there would be a
// welcome view with accept buttons. And makes sure only check once.
if (!isCheckedFirstLaunch) {
isGooglePlayServicesLatest = isGooglePlayServicesLatest();
if (!isGooglePlayServicesLatest) {
SOLO.finishOpenedActivities();
Assert.fail();
Log.e(TAG, "Need update Google Play Services");
}
setIsEmulator();
verifyFirstLaunch();
hasActionBar = setHasActionBar();
checkLanguage();
isCheckedFirstLaunch = true;
inst.waitForIdleSync();
// Check the status of real phone. For emulator, we would fix GPS signal.
if (!isEmulator) {
findAndClickMyLocation(activity);
hasGpsSignal = !SOLO.waitForText(NO_GPS_MESSAGE_PREFIX, 1, SHORT_WAIT_TIME);
SOLO.goBack();
}
}
int trackNumber = SOLO.getCurrentViews(ListView.class).get(0).getCount();
// Delete all tracks when there are two many tracks which may make some test
// run slowly, such as sync test cases.
if (trackNumber > 3) {
deleteAllTracks();
}
// Check whether is under recording. If previous test failed, the recording
// may not be recording.
if (isUnderRecording()) {
stopRecording(true);
}
resetAllSettings(activity, false);
inst.waitForIdleSync();
}
/**
* Rotates the given activity.
*
* @param activity a given activity
*/
private static void rotateActivity(Activity activity) {
activity
.setRequestedOrientation(activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT ? ORIENTATION_LANDSCAPE
: ORIENTATION_PORTRAIT);
}
/**
* Accepts terms and configures units.
*/
private static void verifyFirstLaunch() {
if ((getButtonOnScreen(trackListActivity.getString(R.string.eula_accept), false, false) != null)) {
getButtonOnScreen(trackListActivity.getString(R.string.eula_accept), true, true);
}
}
/**
* Creates a simple track which can be used by subsequent test. This method
* will save a customized track name.
*
* @param numberOfGpsData number of simulated Gps data
* @param showTrackList whether stay on track list activity or track detail
* activity
*/
public static void createSimpleTrack(int numberOfGpsData, boolean showTrackList) {
startRecording();
sendGps(numberOfGpsData);
instrumentation.waitForIdleSync();
stopRecording(true);
if (showTrackList) {
SOLO.goBack();
instrumentation.waitForIdleSync();
}
}
/**
* Creates a track which contains pause during recording.
*
* @param numberOfGpsData number of simulated Gps data before pause and after
* resume
*/
public static void createTrackWithPause(int numberOfGpsData) {
startRecording();
sendGps(numberOfGpsData);
pauseRecording();
resumeRecording();
sendGps(numberOfGpsData, numberOfGpsData);
stopRecording(true);
}
/**
* Checks if there is no track in track list. For some tests need at least one
* track, the method can save time to create a new track.
*
* @param isClick if not empty, true means click any track
* @return return true if the track list is empty
*/
private static boolean isTrackListEmpty(boolean isClick) {
instrumentation.waitForIdleSync();
int trackNumber = SOLO.getCurrentViews(ListView.class).get(0).getCount();
if (trackNumber <= 0) {
return true;
}
View oneTrack = SOLO.getCurrentViews(ListView.class).get(0).getChildAt(0);
View aa = oneTrack.findViewById(R.id.list_item_name);
if (aa != null) {
trackName = (String) ((TextView) oneTrack.findViewById(R.id.list_item_name)).getText();
}
if (isClick) {
SOLO.scrollUp();
SOLO.clickOnView(oneTrack);
SOLO.waitForText(trackListActivity.getString(R.string.track_detail_chart_tab));
}
return false;
}
/**
* Create a new track if the track is empty.
*
* @param gpsNumber the number of gps signals
* @param showTrackList whether stay on track list activity or track detail
* activity
*/
public static void createTrackIfEmpty(int gpsNumber, boolean showTrackList) {
if (isTrackListEmpty(!showTrackList)) {
// Create a simple track.
createSimpleTrack(gpsNumber, showTrackList);
}
}
/**
* Starts recoding track.
*/
public static void startRecording() {
View startButton = SOLO.getCurrentActivity().findViewById(R.id.track_controller_record);
if (startButton != null && startButton.isShown()) {
SOLO.clickOnView(startButton);
}
instrumentation.waitForIdleSync();
}
/**
* Pauses recoding track.
*/
public static void pauseRecording() {
View pauseButton = SOLO.getCurrentActivity().findViewById(R.id.track_controller_record);
if (pauseButton != null && pauseButton.isShown()) {
SOLO.clickOnView(pauseButton);
}
instrumentation.waitForIdleSync();
}
/**
* Resume recoding track.
*/
public static void resumeRecording() {
View startButton = SOLO.getCurrentActivity().findViewById(R.id.track_controller_record);
if (startButton != null && startButton.isShown()) {
SOLO.clickOnView(startButton);
}
instrumentation.waitForIdleSync();
}
/**
* Checks if the MyTracks is under recording.
*
* @return true if it is under recording.
*/
private static boolean isUnderRecording() {
instrumentation.waitForIdleSync();
View view = SOLO.getCurrentActivity().findViewById(R.id.track_controller_stop);
// TODO: understand why view can be null here
return view != null ? view.isEnabled() : false;
}
/**
* Stops recoding track.
*
* @param isSave true means should save this track
*/
public static void stopRecording(boolean isSave) {
View stopButton = SOLO.getCurrentActivity().findViewById(R.id.track_controller_stop);
if (stopButton != null && stopButton.isShown()) {
SOLO.clickOnView(stopButton);
if (isSave) {
SOLO.waitForText(trackListActivity.getString(R.string.generic_save), 1, 5000);
// Make every track name is unique to make sure every check can be
// trusted.
long currentMillis = System.currentTimeMillis();
trackName = TRACK_NAME_PREFIX + currentMillis;
trackDescription = TRACK_DESCRIPTION_PREFIX + currentMillis;
SOLO.sendKey(KeyEvent.KEYCODE_DEL);
enterTextAvoidSoftKeyBoard(0, trackName);
enterTextAvoidSoftKeyBoard(1, activityType);
enterTextAvoidSoftKeyBoard(2, trackDescription);
SOLO.clickOnText(trackListActivity.getString(R.string.generic_save));
instrumentation.waitForIdleSync();
} else {
instrumentation.waitForIdleSync();
}
}
}
/**
* Deletes all tracks. This method should be call when the TracksListActivity
* is shown.
*/
public static void deleteAllTracks() {
if (!isTrackListEmpty(false)) {
findMenuItem(trackListActivity.getString(R.string.menu_delete_all), true);
getButtonOnScreen(trackListActivity.getString(R.string.generic_yes), true, true);
waitTextToDisappear(trackListActivity.getString(R.string.generic_progress_title));
}
}
/**
* Checks if a button is existed in the screen.
*
* @param buttonName the name string of the button
* @param isWait whether wait the text
* @param isClick whether click the button if find it
* @return the button to search, and null means can not find the button
*/
public static View getButtonOnScreen(String buttonName, boolean isWait, boolean isClick) {
View button = null;
instrumentation.waitForIdleSync();
if (isWait) {
SOLO.waitForText(buttonName);
}
// Find on action bar.
if (hasActionBar) {
ArrayList<View> allViews = SOLO.getViews();
for (View view : allViews) {
String className = view.getClass().getName();
if (className.indexOf("ActionMenuItemView") > 0) {
String menuItemNameString = view.getContentDescription().toString();
if (menuItemNameString.equalsIgnoreCase(buttonName)) {
button = view;
break;
}
}
}
}
// Get all buttons and find.
if (button == null) {
ArrayList<Button> currentButtons = SOLO.getCurrentViews(Button.class);
for (Button oneButton : currentButtons) {
String title = (String) oneButton.getText();
if (title.equalsIgnoreCase(buttonName)) {
button = oneButton;
}
}
}
if (button != null && isClick) {
SOLO.clickOnView(button);
}
if (button == null && isClick) {
Log.d(TAG, "Don't find the button " + buttonName);
}
return button;
}
/**
* Checks whether an action bar is shown.
*
* @return false means can not check failed.
*/
@SuppressLint("NewApi")
private static boolean setHasActionBar() {
try {
return trackListActivity.getActionBar() == null ? false : true;
} catch (Throwable e) {
// For in Android which does not has action bar, here will meet a error.
return false;
}
}
/**
* Rotates all activities.
*/
public static void rotateCurrentActivity() {
rotateActivity(SOLO.getCurrentActivity());
instrumentation.waitForIdleSync();
}
/**
* Finds an item in the menu with the option to click the item.
*
* @param menuName the name of item
* @param click true means need click this menu
* @return true if find this menu
*/
public static boolean findMenuItem(String menuName, boolean click) {
instrumentation.waitForIdleSync();
boolean findResult = false;
boolean isMoreMenuOpened = false;
// ICS phone.
if (hasActionBar) {
// Firstly find in action bar.
View button = getButtonOnScreen(menuName, false, false);
if (button != null) {
findResult = true;
if (click) {
SOLO.clickOnView(button);
instrumentation.waitForIdleSync();
}
return findResult;
}
showMenuItem();
findResult = SOLO.waitForText(menuName, 1, LONG_WAIT_TIME, true);
} else {
// Non-ICS phone.
SOLO.sendKey(KeyEvent.KEYCODE_MENU);
if (SOLO.searchText(menuName, 1, true)) {
findResult = true;
} else if (getMoreOptionView() != null) {
SOLO.clickOnView(getMoreOptionView());
findResult = SOLO.searchText(menuName, 1, true);
isMoreMenuOpened = true;
}
}
if (findResult && click) {
SOLO.clickOnView(SOLO.getText(menuName));
instrumentation.waitForIdleSync();
} else {
// Quit more menu list if opened.
if (isMoreMenuOpened) {
SOLO.goBack();
}
// Quit menu list.
SOLO.goBack();
}
return findResult;
}
/**
* Show menu item list.
*/
private static void showMenuItem() {
showMenuItem(0);
}
/**
* Gets more menu items operation is different for different Android OS. When
* get overflow button view on action, it usually be able to click. But in
* some situation, will meet an error when click it. So catch it and try
* again. In most situation, the second click will be pass.
*
* @param depth control the depth of recursion to prevent dead circulation
*/
private static void showMenuItem(int depth) {
// ICS phone.
if (hasActionBar) {
instrumentation.waitForIdleSync();
View moreButton = getMoreOptionView();
// ICS phone without menu key.
if (moreButton != null) {
try {
SOLO.clickOnView(moreButton);
} catch (Throwable e) {
if (depth < 5 && e.getMessage().indexOf("Click can not be completed") > -1) {
showMenuItem(depth++);
}
}
return;
} else {
// ICS phone with menu key.
SOLO.sendKey(KeyEvent.KEYCODE_MENU);
}
} else {
// Non-ICS phone with menu key.
SOLO.sendKey(KeyEvent.KEYCODE_MENU);
}
}
/**
* Finds the more option menu. It should match following conditions:
* <ul>
* <li>The view extends ImageButton.</li>
* <li>The view name equals {@link #MORE_OPTION_CLASSNAME}.</li>
* </ul>
*
* @return the more option view. Null means can not find it.
*/
private static View getMoreOptionView() {
View viewResult = null;
if (hasActionBar) {
ArrayList<View> allViews = SOLO.getViews();
for (View view : allViews) {
if (view instanceof ImageButton && view.getClass().getName().equals(MORE_OPTION_CLASSNAME)) {
viewResult = view;
break;
}
}
} else {
ArrayList<View> allViews = SOLO.getViews();
for (View view : allViews) {
if (view.getClass().getName().equals(MENUITEM_CLASSNAME)) {
viewResult = view;
// No break here to get the last menu item.
}
}
}
return viewResult;
}
/**
* Finds a displayed text view with specified text in a view.
*
* @param text text to find
* @param parent which text view in in
* @return the text view, null means can not find it
*/
public static TextView findTextViewInView(String text, View parent) {
ArrayList<TextView> textViews = SOLO.getCurrentViews(TextView.class, parent);
for (TextView textView : textViews) {
String textString = (String) textView.getText();
if (textView.isShown() && textString.endsWith(text)) {
return textView;
}
}
return null;
}
/**
* Finds a displayed text view with specified text.
*
* @param text text to find
* @return the text view, null means can not find it
*/
public static TextView findTextView(String text) {
ArrayList<View> allViews = SOLO.getViews();
if (allViews != null) {
for (View view : allViews) {
if (view instanceof TextView) {
TextView textView = (TextView) view;
String textString = (String) textView.getText();
if (textView.isShown() && textString.endsWith(text)) {
return textView;
}
}
}
}
return null;
}
/**
* Finds a displayed text view with specified text and index number.
*
* @param text text to find
* @param index the index to search
* @return the text view, null means can not find it
*/
public static TextView findTextViewByIndex(String text, int index) {
int number = 1;
ArrayList<View> allViews = SOLO.getViews();
for (View view : allViews) {
if (view instanceof TextView) {
TextView textView = (TextView) view;
String textString = (String) textView.getText();
if (textView.isShown() && textString.endsWith(text)) {
if (number == index) {
return textView;
} else {
number++;
}
}
}
}
return null;
}
/**
* Resets all settings of MyTracks.
*
* @param activityMyTracks current activity
* @param keepInSettingList whether keep in setting list or not
*/
public static void resetAllSettings(Activity activityMyTracks, boolean keepInSettingList) {
findMenuItem(activityMyTracks.getString(R.string.menu_settings), true);
SOLO.clickOnText(activityMyTracks.getString(R.string.settings_advanced));
Assert.assertTrue(SOLO.waitForText(activityMyTracks.getString(R.string.settings_reset)));
SOLO.clickOnText(activityMyTracks.getString(R.string.settings_reset));
getButtonOnScreen(trackListActivity.getString(R.string.generic_yes), true, true);
Assert.assertTrue(SOLO.waitForText(activityMyTracks.getString(R.string.settings_reset_done)));
instrumentation.waitForIdleSync();
SOLO.goBack();
instrumentation.waitForIdleSync();
if (!keepInSettingList) {
SOLO.goBack();
}
}
/**
* Finds a edit text and enter text in it. This method can hides soft key
* board when input text.
*
* @param editTextIndex the index of edit text
* @param text to enter
*/
public static void enterTextAvoidSoftKeyBoard(int editTextIndex, String text) {
EditText editText = SOLO.getEditText(editTextIndex);
SOLO.enterText(editText, text);
SOLO.hideSoftKeyboard();
// Above line does not work every time. And it is should be a Robotium
// issue.
InputMethodManager imm = (InputMethodManager) trackListActivity.getApplicationContext()
.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(editText.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
}
/**
* Waits n milliseconds.
*
* @param milliseconds time to sleep
*/
public static void sleep(long milliseconds) {
try {
Thread.sleep(milliseconds);
} catch (InterruptedException e) {
Log.e(TAG, "Unable to sleep " + milliseconds, e);
}
}
/**
* Checks whether the recording is not started.
*/
public static void checkNotRecording() {
instrumentation.waitForIdleSync();
Assert.assertEquals(trackListActivity.getString(R.string.image_record),
(String) SOLO.getCurrentActivity()
.findViewById(R.id.track_controller_record).getContentDescription());
Assert.assertFalse(
SOLO.getCurrentActivity().findViewById(R.id.track_controller_stop).isEnabled());
Assert.assertNull(findTextView(trackListActivity.getString(R.string.generic_recording)));
Assert.assertNull(findTextView(trackListActivity.getString(R.string.generic_paused)));
Assert.assertFalse(
SOLO.getCurrentActivity().findViewById(R.id.track_controller_total_time).isShown());
}
/**
* Checks whether the MyTracks is under recording.
*/
public static void checkUnderRecording() {
instrumentation.waitForIdleSync();
Assert.assertEquals(trackListActivity.getString(R.string.image_pause), (String) SOLO
.getCurrentActivity().findViewById(R.id.track_controller_record).getContentDescription());
Assert.assertTrue(SOLO.getCurrentActivity().findViewById(R.id.track_controller_stop)
.isEnabled());
Assert.assertNotNull(findTextView(trackListActivity.getString(R.string.generic_recording)));
Assert.assertNull(findTextView(trackListActivity.getString(R.string.generic_paused)));
String totalTimeOld = ((TextView) SOLO.getCurrentActivity().findViewById(
R.id.track_controller_total_time)).getText().toString();
sleep(2000);
String totalTimeNew = ((TextView) SOLO.getCurrentActivity().findViewById(
R.id.track_controller_total_time)).getText().toString();
Assert.assertFalse(totalTimeOld.equalsIgnoreCase(totalTimeNew));
}
/**
* Checks whether the recording is paused.
*/
public static void checkUnderPaused() {
instrumentation.waitForIdleSync();
Assert.assertEquals(trackListActivity.getString(R.string.image_record), (String) SOLO
.getCurrentActivity().findViewById(R.id.track_controller_record).getContentDescription());
Assert.assertTrue(SOLO.getCurrentActivity().findViewById(R.id.track_controller_stop)
.isEnabled());
Assert.assertNull(findTextView(trackListActivity.getString(R.string.generic_recording)));
Assert.assertNotNull(findTextView(trackListActivity.getString(R.string.generic_paused)));
String totalTimeOld = ((TextView) SOLO.getCurrentActivity().findViewById(
R.id.track_controller_total_time)).getText().toString();
sleep(2000);
String totalTimeNew = ((TextView) SOLO.getCurrentActivity().findViewById(
R.id.track_controller_total_time)).getText().toString();
Assert.assertTrue(totalTimeOld.equalsIgnoreCase(totalTimeNew));
}
/**
* Creates a way point during track recording.
*
* @param markerNumber of number of previous markers
*/
public static void createWaypoint(int markerNumber) {
findMenuItem(trackListActivity.getString(R.string.menu_markers), true);
instrumentation.waitForIdleSync();
if (markerNumber > 0 && hasGpsSignal) {
SOLO.waitForText(WAYPOINT_NAME);
int actualMarkerNumber = SOLO.getCurrentViews(ListView.class).get(0).getCount();
Assert.assertEquals(markerNumber, actualMarkerNumber);
} else {
Log.d(TAG, "marker number, hasGpsSignal: " + markerNumber + ", " + hasGpsSignal);
Assert.assertTrue(SOLO.waitForText(trackListActivity
.getString(R.string.marker_list_empty_message)));
}
findMenuItem(trackListActivity.getString(R.string.menu_insert_marker), true);
enterTextAvoidSoftKeyBoard(0, WAYPOINT_NAME + (markerNumber + 1));
enterTextAvoidSoftKeyBoard(1, WAYPOINT_TYPE + (markerNumber + 1));
enterTextAvoidSoftKeyBoard(2, WAYPOINT_DESCRIPTION + (markerNumber + 1));
SOLO.clickOnButton(trackListActivity.getString(R.string.generic_add));
instrumentation.waitForIdleSync();
if (hasGpsSignal) {
Assert.assertTrue(SOLO.waitForText(WAYPOINT_NAME, 1, LONG_WAIT_TIME, true));
} else {
Assert.assertFalse(SOLO.searchText(WAYPOINT_NAME));
}
SOLO.goBack();
}
/**
* Waits a text to disappear.
*/
public static void waitTextToDisappear(String text) {
instrumentation.waitForIdleSync();
SOLO.waitForText(text, 1, VERY_SHORT_WAIT_TIME);
while (SOLO.waitForText(text, 1, VERY_SHORT_WAIT_TIME)) {}
return;
}
/**
* Finds the My Location view and click it.
*
* @param activity
*/
private static void findAndClickMyLocation(Activity activity) {
createTrackIfEmpty(1, false);
sendGps(30);
View myLocation = SOLO.getCurrentActivity().findViewById(R.id.map_my_location);
instrumentation.waitForIdleSync();
// Find the My Location button in another if null.
if (myLocation == null) {
ArrayList<ImageButton> aa = SOLO.getCurrentViews(ImageButton.class);
for (ImageButton imageButton : aa) {
if (imageButton.getContentDescription() != null
&& imageButton.getContentDescription().equals(
activity.getString(R.string.image_my_location))) {
myLocation = imageButton;
break;
}
}
}
SOLO.clickOnView(myLocation);
}
/**
* Gets the relative start time suffix.
*/
public static String getRelativeStartTimeSuffix() {
String value = RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.get(language);
return value != null ? value : RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.get("en");
}
/**
* Changes to metric units.
*/
public static void changeToMetricUnits() {
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
EndToEndTestUtils.SOLO.clickOnText(
trackListActivity.getString(R.string.track_detail_stats_tab));
Assert.assertTrue(EndToEndTestUtils.SOLO.waitForText(
trackListActivity.getString(R.string.settings_stats_units_title)));
// Change the preferred units
EndToEndTestUtils.SOLO.clickOnText(
trackListActivity.getString(R.string.settings_stats_units_title));
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.unit_kilometer));
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.SOLO.goBack();
}
}
@@ -0,0 +1,398 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.io.gdata.GDataClientFactory;
import com.google.android.apps.mytracks.io.gdata.maps.MapFeatureEntry;
import com.google.android.apps.mytracks.io.gdata.maps.MapsClient;
import com.google.android.apps.mytracks.io.gdata.maps.MapsConstants;
import com.google.android.apps.mytracks.io.gdata.maps.MapsGDataConverter;
import com.google.android.apps.mytracks.io.gdata.maps.MapsMapMetadata;
import com.google.android.apps.mytracks.io.gdata.maps.XmlMapsGDataParserFactory;
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
import com.google.android.apps.mytracks.io.spreadsheets.SendSpreadsheetsAsyncTask;
import com.google.android.apps.mytracks.io.sync.SyncUtils;
import com.google.android.apps.mytracks.util.SystemUtils;
import com.google.android.common.gdata.AndroidXmlParserFactory;
import com.google.android.maps.mytracks.R;
import com.google.api.client.auth.oauth2.BearerToken;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.model.File;
import com.google.api.services.fusiontables.Fusiontables;
import com.google.api.services.fusiontables.model.Table;
import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.data.spreadsheet.ListEntry;
import com.google.gdata.data.spreadsheet.ListFeed;
import com.google.gdata.data.spreadsheet.WorksheetEntry;
import com.google.gdata.data.spreadsheet.WorksheetFeed;
import com.google.wireless.gdata.parser.GDataParser;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.Context;
import android.util.Log;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
/**
* Utilities for accessing Google Drive, Google Maps, Google Fusion Tables, and
* Google Spreadsheets.
*
* @author Youtao Liu
*/
public class GoogleUtils {
public static final String ACCOUNT_1 = "mytrackstest@gmail.com";
public static final String ACCOUNT_2 = "mytrackstest2@gmail.com";
private static final String TAG = GoogleUtils.class.getSimpleName();
private static final String MY_TRACKS_PREFIX = "My Tracks";
private static final String SPREADSHEETS_NAME = MY_TRACKS_PREFIX + "-"
+ EndToEndTestUtils.activityType;
private static final String SPREADSHEETS_WORKSHEET_NAME = "Log";
private static final String SPREADSHEETS_TRANCK_NAME_COLUMN = "Name";
private static final String DRIVE_TEST_FILES_QUERY = "'root' in parents and title contains '"
+ EndToEndTestUtils.TRACK_NAME_PREFIX + "' and trashed = false";
/**
* Deletes Google Drive test files.
*
* @param context the context
* @param accountName the account name
*/
public static void deleteDriveTestFiles(Context context, String accountName) {
try {
GoogleAccountCredential googleAccountCredential = SendToGoogleUtils
.getGoogleAccountCredential(context, accountName, SendToGoogleUtils.DRIVE_SCOPE);
if (googleAccountCredential == null) {
return;
}
Drive drive = SyncUtils.getDriveService(googleAccountCredential);
com.google.api.services.drive.Drive.Files.List list = drive.files()
.list().setQ(DRIVE_TEST_FILES_QUERY);
List<File> files = list.execute().getItems();
Iterator<File> iterator = files.iterator();
while (iterator.hasNext()) {
File file = (File) iterator.next();
drive.files().delete(file.getId()).execute();
}
} catch (Exception e) {
Log.e(TAG, "Unable to delete Google Drive test files.", e);
}
}
/**
* Deletes Google Maps of the first Google account.
*
* @param context the context
* @param accountName the account name
* @param mapTitle the map title
* @return true if deletion is success.
*/
public static boolean deleteMaps(Context context, String accountName, String mapTitle) {
Account account = getGoogleAccount(context, accountName);
if (account == null) {
return false;
}
MapsClient mapsClient = new MapsClient(GDataClientFactory.getGDataClient(context),
new XmlMapsGDataParserFactory(new AndroidXmlParserFactory()));
ArrayList<MapsMapMetadata> mapMetadata = getMaps(context, account, mapsClient);
for (MapsMapMetadata data : mapMetadata) {
if (data.getDescription().indexOf(MY_TRACKS_PREFIX) > -1
&& data.getTitle().equals(mapTitle)) {
try {
mapsClient.deleteEntry(data.getGDataEditUri(), AccountManager.get(context)
.blockingGetAuthToken(account, MapsConstants.SERVICE_NAME, false));
return true;
} catch (Exception e) {
Log.e(TAG, "Unable to delete maps.", e);
return false;
}
}
}
return false;
}
/**
* Deletes all Google Maps of the first Google account
*
* @param context the context
* @param accountName the account name
*/
public static void deleteAllMaps(Context context, String accountName) {
Account account = getGoogleAccount(context, accountName);
if (account == null) {
Log.e(TAG, "Unable to get account.");
return;
}
MapsClient mapsClient = new MapsClient(GDataClientFactory.getGDataClient(context),
new XmlMapsGDataParserFactory(new AndroidXmlParserFactory()));
ArrayList<MapsMapMetadata> mapMetadata = getMaps(context, account, mapsClient);
for (MapsMapMetadata oneData : mapMetadata) {
try {
mapsClient.deleteEntry(oneData.getGDataEditUri(), AccountManager.get(context)
.blockingGetAuthToken(account, MapsConstants.SERVICE_NAME, false));
} catch (Exception e) {
Log.e(TAG, "Unable to delete maps.", e);
}
}
}
/**
* Deletes Google Fusion Tables.
*
* @param context the context
* @param accountName the account name
* @param tableName the table name
* @return true if deletion is success.
*/
public static boolean deleteFusionTables(Context context, String accountName, String tableName) {
try {
GoogleAccountCredential googleAccountCredential = SendToGoogleUtils
.getGoogleAccountCredential(context, accountName, SendToGoogleUtils.FUSION_TABLES_SCOPE);
if (googleAccountCredential == null) {
return false;
}
Fusiontables fusiontables = new Fusiontables.Builder(
AndroidHttp.newCompatibleTransport(), new GsonFactory(), googleAccountCredential).build();
List<Table> tables = fusiontables.table().list().execute().getItems();
Iterator<Table> iterator = tables.iterator();
while (iterator.hasNext()) {
Table table = (Table) iterator.next();
String name = table.getName();
if (name != null && name.equals(tableName)) {
fusiontables.table().delete(table.getTableId()).execute();
return true;
}
}
} catch (Exception e) {
Log.e(TAG, "Unable to search fusion tables.", e);
}
return false;
}
/**
* Searches Google Spreadsheets.
*
* @param context the context
* @param accountName the account name
* @return the list of spreadsheets matching the title. Null if unable to
* search.
*/
public static List<File> searchSpreadsheets(Context context, String accountName) {
try {
GoogleAccountCredential googleAccountCredential = SendToGoogleUtils
.getGoogleAccountCredential(context, accountName, SendToGoogleUtils.DRIVE_SCOPE);
if (googleAccountCredential == null) {
return null;
}
Drive drive = SyncUtils.getDriveService(googleAccountCredential);
com.google.api.services.drive.Drive.Files.List list = drive.files().list().setQ(String.format(
Locale.US, SendSpreadsheetsAsyncTask.GET_SPREADSHEET_QUERY, SPREADSHEETS_NAME));
return list.execute().getItems();
} catch (Exception e) {
Log.e(TAG, "Unable to search spreadsheets.", e);
}
return null;
}
/**
* Deletes Google Spreadsheets.
*
* @param context the context
* @param accountName the account name
* @return true if deletion is success.
*/
public static boolean deleteSpreadsheets(Context context, String accountName) {
try {
GoogleAccountCredential googleAccountCredential = SendToGoogleUtils
.getGoogleAccountCredential(context, accountName, SendToGoogleUtils.DRIVE_SCOPE);
if (googleAccountCredential == null) {
return false;
}
Drive drive = SyncUtils.getDriveService(googleAccountCredential);
com.google.api.services.drive.Drive.Files.List list = drive.files().list().setQ(String.format(
Locale.US, SendSpreadsheetsAsyncTask.GET_SPREADSHEET_QUERY, SPREADSHEETS_NAME));
List<File> files = list.execute().getItems();
Iterator<File> iterator = files.iterator();
while (iterator.hasNext()) {
File file = (File) iterator.next();
drive.files().delete(file.getId()).execute();
}
return true;
} catch (Exception e) {
Log.e(TAG, "Unable to delete spreadsheets.", e);
}
return false;
}
/**
* Deletes Google Spreadsheets row.
*
* @param context the context
* @param accountName the account name
* @param trackName the track name
* @return true if deletion is success.
*/
public static boolean deleteSpreadsheetsRow(
Context context, String accountName, String trackName) {
try {
// Get spreadsheet Id
List<File> files = searchSpreadsheets(context, accountName);
if (files == null || files.size() == 0) {
return false;
}
String spreadsheetId = files.get(0).getId();
// Get spreadsheet service
SpreadsheetService spreadsheetService = new SpreadsheetService(
"MyTracks-" + SystemUtils.getMyTracksVersion(context));
Credential credential = new Credential(BearerToken.authorizationHeaderAccessMethod());
credential.setAccessToken(
SendToGoogleUtils.getToken(context, accountName, SendToGoogleUtils.SPREADSHEETS_SCOPE));
spreadsheetService.setOAuth2Credentials(credential);
// Get work sheet
WorksheetFeed worksheetFeed = spreadsheetService.getFeed(new URL(
String.format(Locale.US, SendSpreadsheetsAsyncTask.GET_WORKSHEETS_URI, spreadsheetId)),
WorksheetFeed.class);
Iterator<WorksheetEntry> worksheetEntryIterator = worksheetFeed.getEntries().iterator();
while (worksheetEntryIterator.hasNext()) {
WorksheetEntry worksheetEntry = (WorksheetEntry) worksheetEntryIterator.next();
String worksheetTitle = worksheetEntry.getTitle().getPlainText();
if (worksheetTitle.equals(SPREADSHEETS_WORKSHEET_NAME)) {
URL url = worksheetEntry.getListFeedUrl();
Iterator<ListEntry> listEntryIterator = spreadsheetService.getFeed(url, ListFeed.class)
.getEntries().iterator();
while (listEntryIterator.hasNext()) {
ListEntry listEntry = (ListEntry) listEntryIterator.next();
String name = listEntry.getCustomElements().getValue(SPREADSHEETS_TRANCK_NAME_COLUMN);
if (name.equals(trackName)) {
listEntry.delete();
return true;
}
}
}
}
} catch (Exception e) {
Log.e(TAG, "Unable to delete spreadsheets row.", e);
}
return false;
}
/**
* Returns true if an account is available.
*/
public static boolean isAccountAvailable() {
// Check the no account dialog
if (EndToEndTestUtils.SOLO.waitForText(
EndToEndTestUtils.trackListActivity.getString(R.string.send_google_no_account_title), 1,
EndToEndTestUtils.SHORT_WAIT_TIME)) {
EndToEndTestUtils.getButtonOnScreen(
EndToEndTestUtils.trackListActivity.getString(R.string.generic_ok), false, true);
return false;
}
// Check the choose account dialog
if (EndToEndTestUtils.SOLO.waitForText(
EndToEndTestUtils.trackListActivity.getString(R.string.send_google_choose_account_title), 1,
EndToEndTestUtils.SHORT_WAIT_TIME)) {
EndToEndTestUtils.SOLO.clickOnText(ACCOUNT_1);
EndToEndTestUtils.getButtonOnScreen(
EndToEndTestUtils.trackListActivity.getString(R.string.generic_ok), false, true);
}
// Check the no account permission dialog
if (EndToEndTestUtils.SOLO.waitForText(
EndToEndTestUtils.trackListActivity.getString(R.string.send_google_no_account_permission), 1,
EndToEndTestUtils.SHORT_WAIT_TIME)) {
return false;
}
return true;
}
/**
* Gets the google account.
*
* @param context the context
* @param accountName the account name
*/
private static Account getGoogleAccount(Context context, String accountName) {
Account[] accounts = AccountManager.get(context).getAccountsByType(Constants.ACCOUNT_TYPE);
for (Account account : accounts) {
if (account.name.equals(accountName)) {
return account;
}
}
return null;
}
/**
* Gets Google Maps.
*
* @param context the context
* @param account the account
* @param mapsClient the map client
* @return a list of maps.
*/
private static ArrayList<MapsMapMetadata> getMaps(
Context context, Account account, MapsClient mapsClient) {
String authToken = null;
ArrayList<String> mapIds = new ArrayList<String>();
ArrayList<MapsMapMetadata> mapMetadata = new ArrayList<MapsMapMetadata>();
try {
authToken = AccountManager.get(context)
.blockingGetAuthToken(account, MapsConstants.SERVICE_NAME, false);
} catch (Exception e) {
Log.e(TAG, "Unable to get auth token.", e);
return mapMetadata;
}
GDataParser gDataParser = null;
try {
gDataParser = mapsClient.getParserForFeed(
MapFeatureEntry.class, MapsClient.getMapsFeed(), authToken);
gDataParser.init();
while (gDataParser.hasMoreData()) {
MapFeatureEntry entry = (MapFeatureEntry) gDataParser.readNextEntry(null);
mapIds.add(MapsGDataConverter.getMapidForEntry(entry));
mapMetadata.add(MapsGDataConverter.getMapMetadataForEntry(entry));
}
} catch (Exception e) {
Log.e(TAG, "Unable to get maps.", e);
} finally {
if (gDataParser != null) {
gDataParser.close();
}
}
return mapMetadata;
}
}
@@ -0,0 +1,133 @@
/*
* Copyright 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest;
import com.google.android.maps.mytracks.R;
/**
* Run configuration for various tests.
*
* @author Youtao Liu
*/
public class RunConfiguration {
private static RunConfiguration instance;
/**
* Gets an instance of {@link RunConfiguration}.
*/
public static RunConfiguration getInstance() {
if (instance == null) {
instance = new RunConfiguration();
}
return instance;
}
/*
* Set to false as default. True to run the test. Default to false since these
* tests can take a long time.
*/
private boolean runResourceTest = false;
private boolean runSensorTest = false;
private boolean runStressTest = false;
private boolean runSyncTest = false;
private RunConfiguration() {
// Sets run sync test in run-time
setRunSyncTest(canRunSyncTest());
}
/**
* Returns true to run the resource test.
*/
public boolean getRunResourceTest() {
return runResourceTest;
}
/**
* Sets run resource test.
*
* @param run true to run
*/
public void setRunResourceTest(boolean run) {
runResourceTest = run;
}
/**
* Returns true to run the sensor test.
*/
public boolean getRunSensorTest() {
return runSensorTest;
}
/**
* Sets run sensor test.
*
* @param run true to run
*/
public void setRunSensorTest(boolean run) {
runSensorTest = run;
}
/**
* Returns true to run the stress test.
*/
public boolean getRunStressTest() {
return runStressTest;
}
/**
* Sets run stress test.
*
* @param run true to run
*/
public void setRunStressTest(boolean run) {
runStressTest = run;
}
/**
* Returns true to run the sync test.
*/
public boolean getRunSyncTest() {
return runSyncTest;
}
/**
* Sets run sync test.
*
* @param run true to run
*/
public void setRunSyncTest(boolean run) {
runSyncTest = run;
}
/**
* Returns true if can run the sync test. Needs two specific test accounts on
* the device.
*/
private boolean canRunSyncTest() {
EndToEndTestUtils.findMenuItem(
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_drive), true);
boolean canRun = EndToEndTestUtils.SOLO.waitForText(
GoogleUtils.ACCOUNT_1, 1, EndToEndTestUtils.SHORT_WAIT_TIME)
&& EndToEndTestUtils.SOLO.waitForText(
GoogleUtils.ACCOUNT_2, 1, EndToEndTestUtils.TINY_WAIT_TIME);
EndToEndTestUtils.SOLO.clickOnText(
EndToEndTestUtils.trackListActivity.getString(R.string.generic_cancel));
return canRun;
}
}
@@ -0,0 +1,172 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest.common;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
import com.google.android.maps.mytracks.R;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.ListView;
/**
* Tests creating new tracks.
*
* @author Youtao Liu
*/
public class CreateTrackTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private Instrumentation instrumentation;
private TrackListActivity trackListActivity;
public CreateTrackTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
trackListActivity = getActivity();
EndToEndTestUtils.setupForAllTest(instrumentation, trackListActivity);
EndToEndTestUtils.deleteAllTracks();
}
@Override
protected void tearDown() throws Exception {
EndToEndTestUtils.SOLO.finishOpenedActivities();
super.tearDown();
}
/**
* Tests creating a new track and checks the relative time in
* {@link TrackListActivity}.
*/
public void testNewTrack() {
// Start a recording
EndToEndTestUtils.startRecording();
checkRecording();
// Stop the recording
EndToEndTestUtils.stopRecording(false);
// Save the track
EndToEndTestUtils.getButtonOnScreen(
trackListActivity.getString(R.string.generic_save), true, true);
instrumentation.waitForIdleSync();
// Go back to the TrackListActivity
EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync();
// Make sure "mins ago" is displayed
assertTrue(EndToEndTestUtils.SOLO.searchText(
EndToEndTestUtils.getRelativeStartTimeSuffix(), 1, false, true));
}
/**
* Tests creating a new track with two markers.
*/
public void testNewTrackWithMarker() {
// Start a recording
EndToEndTestUtils.startRecording();
checkRecording();
// Create a marker
EndToEndTestUtils.sendGps(2);
EndToEndTestUtils.createWaypoint(0);
// Send more gps points
EndToEndTestUtils.sendGps(2, 2);
EndToEndTestUtils.createWaypoint(1);
// Go back to the TrackListActivity
EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync();
// Rotate the phone
EndToEndTestUtils.rotateCurrentActivity();
// Stop the recording
EndToEndTestUtils.stopRecording(false);
// Update edit page and save
String trackName = EndToEndTestUtils.TRACK_NAME_PREFIX + System.currentTimeMillis();
EndToEndTestUtils.SOLO.enterText(0, trackName);
EndToEndTestUtils.SOLO.enterText(1, EndToEndTestUtils.activityType);
EndToEndTestUtils.SOLO.clickOnButton(trackListActivity.getString(R.string.generic_save));
instrumentation.waitForIdleSync();
// Check the track name in the TrackListActivity
EndToEndTestUtils.SOLO.scrollUp();
assertTrue(EndToEndTestUtils.SOLO.waitForText(
trackName, 1, EndToEndTestUtils.NORMAL_WAIT_TIME, true, false));
// Go to the TrackDetailActivity
EndToEndTestUtils.SOLO.clickOnText(trackName);
instrumentation.waitForIdleSync();
// Go to Markers
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_markers), true);
instrumentation.waitForIdleSync();
// Make sure there are two markers
assertTrue(EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount() == 2);
}
/**
* Tests creating a new track with split markers.
*/
public void testNewTrackWithSplit() {
EndToEndTestUtils.changeToMetricUnits();
EndToEndTestUtils.startRecording();
checkRecording();
EndToEndTestUtils.findMenuItem(
trackListActivity.getString(R.string.menu_split_frequency), true);
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.unit_kilometer), 0);
EndToEndTestUtils.getButtonOnScreen(
trackListActivity.getString(R.string.generic_ok), true, true);
// Send gps to give a distance more than one kilometer
EndToEndTestUtils.sendGps(50);
assertTrue(
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_markers), true));
instrumentation.waitForIdleSync();
if (EndToEndTestUtils.isEmulator) {
assertTrue(EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount() > 0);
}
EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync();
EndToEndTestUtils.stopRecording(true);
}
/**
* Checks recording.
*/
private void checkRecording() {
if (EndToEndTestUtils.hasActionBar) {
// Check the title is Recording...
assertTrue(EndToEndTestUtils.SOLO.searchText(
trackListActivity.getString(R.string.generic_recording)));
}
}
}
@@ -0,0 +1,144 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest.common;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
import com.google.android.maps.mytracks.R;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.ListView;
/**
* Tests delete tracks.
*
* @author Youtao Liu
*/
public class DeleteTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private Instrumentation instrumentation;
private TrackListActivity trackListActivity;
public DeleteTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
trackListActivity = getActivity();
EndToEndTestUtils.setupForAllTest(instrumentation, trackListActivity);
}
@Override
protected void tearDown() throws Exception {
EndToEndTestUtils.SOLO.finishOpenedActivities();
super.tearDown();
}
/**
* Deletes all tracks.
*/
public void testDeleteAllTracks() {
EndToEndTestUtils.createSimpleTrack(1, true);
assertTrue(EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount() > 0);
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_delete_all), true);
instrumentation.waitForIdleSync();
EndToEndTestUtils.rotateCurrentActivity();
EndToEndTestUtils.getButtonOnScreen(
trackListActivity.getString(R.string.generic_yes), true, true);
EndToEndTestUtils.waitTextToDisappear(
trackListActivity.getString(R.string.generic_progress_title));
instrumentation.waitForIdleSync();
assertTrue(EndToEndTestUtils.SOLO.waitForText(
trackListActivity.getString(R.string.track_list_empty_message)));
assertEquals(0, EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount());
}
/**
* Deletes one track.
*/
public void testDeleteOneTrack() {
EndToEndTestUtils.createSimpleTrack(1, true);
ListView listView = EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0);
int trackCount = listView.getCount();
assertTrue(trackCount > 0);
EndToEndTestUtils.SOLO.clickOnView(listView.getChildAt(0));
EndToEndTestUtils.SOLO.waitForText(
trackListActivity.getString(R.string.track_detail_chart_tab));
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_delete), true);
EndToEndTestUtils.getButtonOnScreen(
trackListActivity.getString(R.string.generic_yes), true, true);
EndToEndTestUtils.waitTextToDisappear(
trackListActivity.getString(R.string.generic_progress_title));
assertEquals(
trackCount - 1, EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount());
}
/**
* Deletes multiple tracks in {@link TrackListActivity}.
*/
public void testDeleteMultiple() {
if (!EndToEndTestUtils.hasActionBar) {
return;
}
// Create 3 tracks
for (int i = 0; i < 3; i++) {
EndToEndTestUtils.createSimpleTrack(0, true);
}
ListView listView = EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0);
int trackCount = listView.getCount();
assertTrue(trackCount > 2);
// Select 3 tracks
EndToEndTestUtils.SOLO.clickLongOnView(listView.getChildAt(0));
EndToEndTestUtils.SOLO.clickOnView(listView.getChildAt(1));
EndToEndTestUtils.SOLO.clickOnView(listView.getChildAt(2));
// Deselect the first one
EndToEndTestUtils.SOLO.clickOnView(listView.getChildAt(0));
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_delete), true);
EndToEndTestUtils.getButtonOnScreen(
trackListActivity.getString(R.string.generic_yes), true, true);
EndToEndTestUtils.waitTextToDisappear(
trackListActivity.getString(R.string.generic_progress_title));
assertEquals(
trackCount - 2, EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount());
}
/**
* Deletes a recording track.
*/
public void testDeleteRecordingTrack() {
EndToEndTestUtils.startRecording();
EndToEndTestUtils.checkUnderRecording();
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_delete), true);
EndToEndTestUtils.getButtonOnScreen(
trackListActivity.getString(R.string.generic_yes), true, true);
EndToEndTestUtils.waitTextToDisappear(
trackListActivity.getString(R.string.generic_progress_title));
EndToEndTestUtils.checkNotRecording();
}
}
@@ -0,0 +1,112 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest.common;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
import com.google.android.maps.mytracks.R;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.view.KeyEvent;
/**
* Tests editing a track.
*
* @author Youtao Liu
*/
public class EditTrackTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private Instrumentation instrumentation;
private TrackListActivity trackListActivity;
public EditTrackTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
trackListActivity = getActivity();
EndToEndTestUtils.setupForAllTest(instrumentation, trackListActivity);
}
@Override
protected void tearDown() throws Exception {
EndToEndTestUtils.SOLO.finishOpenedActivities();
super.tearDown();
}
/**
* Tests editing a track.
*/
public void testEditTrack() {
EndToEndTestUtils.deleteAllTracks();
EndToEndTestUtils.createSimpleTrack(1, false);
// Click on the Edit menu item
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_edit), true);
// Rotate phone
EndToEndTestUtils.rotateCurrentActivity();
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.generic_save));
String newName = EndToEndTestUtils.TRACK_NAME_PREFIX + "_new" + System.currentTimeMillis();
String newActivityType = EndToEndTestUtils.activityType;
String newDescription = "new_description_" + newName;
// Clear name field
sendKeys(KeyEvent.KEYCODE_DEL);
// Enter new name
EndToEndTestUtils.enterTextAvoidSoftKeyBoard(0, newName);
// Enter new activity type
EndToEndTestUtils.SOLO.clearEditText(1);
EndToEndTestUtils.enterTextAvoidSoftKeyBoard(1, newActivityType);
// Enter new description
EndToEndTestUtils.SOLO.clearEditText(2);
EndToEndTestUtils.enterTextAvoidSoftKeyBoard(2, newDescription);
// Change activity type using the activity picker
assertTrue(EndToEndTestUtils.SOLO.searchText(newActivityType));
EndToEndTestUtils.SOLO.clickOnView(EndToEndTestUtils.SOLO.getCurrentActivity()
.findViewById(R.id.track_edit_activity_type_icon));
EndToEndTestUtils.SOLO.waitForText(
trackListActivity.getString(R.string.track_edit_activity_type_hint));
int walkingActivityTypeIndex = 1;
EndToEndTestUtils.SOLO.clickOnView(EndToEndTestUtils.SOLO.getImage(walkingActivityTypeIndex));
EndToEndTestUtils.SOLO.clickOnButton(trackListActivity.getString(R.string.generic_ok));
// The activity type should be replaced by the walking activity type
assertFalse(EndToEndTestUtils.SOLO.searchText(newActivityType));
assertTrue(EndToEndTestUtils.SOLO.searchText(
trackListActivity.getString(R.string.activity_type_walking)));
// Save
EndToEndTestUtils.SOLO.clickOnButton(trackListActivity.getString(R.string.generic_save));
instrumentation.waitForIdleSync();
// Go back to the TrackListActivity
EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync();
assertTrue(EndToEndTestUtils.SOLO.searchText(newName));
assertTrue(EndToEndTestUtils.SOLO.searchText(newDescription));
}
}
@@ -0,0 +1,637 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest.common;
import com.google.android.apps.mytracks.TrackDetailActivity;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
import com.google.android.apps.mytracks.io.file.TrackFileFormat;
import com.google.android.apps.mytracks.util.FileUtils;
import com.google.android.apps.mytracks.util.UnitConversions;
import com.google.android.maps.mytracks.R;
import android.app.Activity;
import android.app.Instrumentation;
import android.location.Location;
import android.location.LocationManager;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
import android.widget.ListView;
import android.widget.TextView;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* Tests export all and import all.
*
* @author Youtao Liu
*/
public class ExportAllAndImportAllTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private static final String TAG = ExportAllAndImportAllTest.class.getSimpleName();
private static final String GPX_FILE_TRACK_NAME = "TestTrackName1373523959524";
private static final int GPX_FILE_TIME_INTERVAL = 9; // seconds
private static final double GPX_FILE_INIT_LATITUDE = 39.30;
private static final double GPX_FILE_INIT_LONGITUDE = 116.0;
private static final String GPX_FILE_ELEVATION_MAX = "33.3";
private static final String GPX_FILE_ELEVATION_MIN = "22.2";
private Instrumentation instrumentation;
private TrackListActivity trackListActivity;
public ExportAllAndImportAllTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
trackListActivity = getActivity();
EndToEndTestUtils.setupForAllTest(instrumentation, trackListActivity);
}
@Override
protected void tearDown() throws Exception {
EndToEndTestUtils.SOLO.finishOpenedActivities();
super.tearDown();
}
/**
* Tests export all as KML.
*/
public void testExport_kml() {
testExport(TrackFileFormat.KML);
}
/**
* Tests export all as GPX.
*/
public void testExport_gpx() {
testExport(TrackFileFormat.GPX);
}
/**
* Tests export all as CSV.
*/
public void testExport_csv() {
testExport(TrackFileFormat.CSV);
}
/**
* Tests export all as TCX.
*/
public void testExport_tcx() {
testExport(TrackFileFormat.TCX);
}
/**
* Test import all KML when there is no file.
*/
public void testImportNoFile_kml() {
testImportNoFile(TrackFileFormat.KML);
}
/**
* Test import all GPX when there is no file.
*/
public void testImportNoFile_gpx() {
testImportNoFile(TrackFileFormat.GPX);
}
/**
* Tests export all as KML and import all KML when there is only one track.
*/
public void testExportImportOne_kml() {
testExportImportOne(TrackFileFormat.KML);
}
/**
* Tests export all as GPX and import all GPX when there is only one track.
*/
public void testExportImportOne_gpx() {
testExportImportOne(TrackFileFormat.GPX);
}
/**
* Tests export all as KML and import all KML when there is only one track and
* the track contains markers.
*/
public void testExportImportOneWithMarker_kml() {
testExportImportOneWithMarker(TrackFileFormat.KML);
}
/**
* Tests export all as GPX and import all GPX when there is only one track and
* the track contains markers.
*/
public void testExportImportOneWithMarker_gpx() {
testExportImportOneWithMarker(TrackFileFormat.GPX);
}
/**
* Tests export all as KML and import all KML when there are multiple tracks.
*/
public void testExportImportMultiple_kml() {
testExportImportMultiple(TrackFileFormat.KML);
}
/**
* Tests export all as GPX and import all GPX when there are multiple tracks.
*/
public void testExportImportMultiple_gpx() {
testExportImportMultiple(TrackFileFormat.GPX);
}
/**
* Tests export all as KML and import all KML when there are multiple tracks
* and the tracks contain pauses.
*/
public void testExportImportMultipleWithPause_kml() {
testExportImportMultipleWithPause(TrackFileFormat.KML);
}
/**
* Tests export all as GPX and import all GPX when there are multiple tracks
* and the tracks contain pauses.
*/
public void testExportImportMultipleWithPause_gpx() {
testExportImportMultipleWithPause(TrackFileFormat.GPX);
}
/**
* Tests export all.
*
* @param trackFileFormat the track file format
*/
private void testExport(TrackFileFormat trackFileFormat) {
deleteExternalStorageFiles(trackFileFormat);
EndToEndTestUtils.deleteAllTracks();
// Create a new track with 1 gps point
EndToEndTestUtils.createTrackIfEmpty(1, true);
assertEquals(1, EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount());
exportTracks(trackFileFormat, 1);
assertEquals(1, getExternalStorageFiles(trackFileFormat).length);
}
/**
* Tests import all when there is no file.
*
* @param trackFileFormat the track file format
*/
private void testImportNoFile(TrackFileFormat trackFileFormat) {
deleteExternalStorageFiles(trackFileFormat);
importTracks(trackFileFormat);
EndToEndTestUtils.SOLO.waitForText(getImportErrorMessage(trackFileFormat));
EndToEndTestUtils.getButtonOnScreen(
trackListActivity.getString(R.string.generic_ok), true, true);
}
/**
* Tests export all and import all with one track.
*
* @param trackFileFormat the track file format
*/
private void testExportImportOne(TrackFileFormat trackFileFormat) {
EndToEndTestUtils.changeToMetricUnits();
showGradeElevation();
addTrackFromGpxFile();
exportImport(trackFileFormat);
checkTrackFromGpxFile();
}
/**
* Tests export all and import all with one track containing markers.
*
* @param trackFileFormat the track file format
*/
private void testExportImportOneWithMarker(TrackFileFormat trackFileFormat) {
addTrackWithMarker();
exportImport(trackFileFormat);
// Check name, activity type, and description
assertTrue(EndToEndTestUtils.SOLO.waitForText(EndToEndTestUtils.trackName));
EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.trackName);
EndToEndTestUtils.SOLO.waitForText(
trackListActivity.getString(R.string.track_detail_chart_tab));
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_edit), true);
instrumentation.waitForIdleSync();
assertTrue(EndToEndTestUtils.SOLO.searchText(EndToEndTestUtils.trackName));
assertTrue(EndToEndTestUtils.SOLO.searchText(EndToEndTestUtils.activityType));
assertTrue(EndToEndTestUtils.SOLO.searchText(EndToEndTestUtils.trackDescription));
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.generic_cancel));
// Check markers
if (EndToEndTestUtils.hasGpsSignal) {
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_markers), true);
// The first marker
assertTrue(EndToEndTestUtils.SOLO.searchText(EndToEndTestUtils.WAYPOINT_NAME + 1));
assertTrue(EndToEndTestUtils.SOLO.searchText(EndToEndTestUtils.WAYPOINT_TYPE + 1));
assertTrue(EndToEndTestUtils.SOLO.searchText(EndToEndTestUtils.WAYPOINT_DESCRIPTION + 1));
// The second marker
assertTrue(EndToEndTestUtils.SOLO.searchText(EndToEndTestUtils.WAYPOINT_NAME + 2));
assertTrue(EndToEndTestUtils.SOLO.searchText(EndToEndTestUtils.WAYPOINT_TYPE + 2));
assertTrue(EndToEndTestUtils.SOLO.searchText(EndToEndTestUtils.WAYPOINT_DESCRIPTION + 2));
}
}
/**
* Tests export all and import all with multiple tracks.
*
* @param trackFileFormat the track file format
*/
private void testExportImportMultiple(TrackFileFormat trackFileFormat) {
addTracks();
exportImport(trackFileFormat);
}
/**
* Tests export all and import all with multiple tracks containing pauses.
*
* @param trackFileFormat the track file format
*/
private void testExportImportMultipleWithPause(TrackFileFormat trackFileFormat) {
addTracksWithPause();
exportImport(trackFileFormat);
}
/**
* Adds one track by importing it from a GPX file.
*/
private void addTrackFromGpxFile() {
EndToEndTestUtils.deleteAllTracks();
deleteExternalStorageFiles(TrackFileFormat.GPX);
createOneGpxFile();
importTracks(TrackFileFormat.GPX);
checkImportSuccess();
checkTrackFromGpxFile();
}
/**
* Adds one track with markers.
*/
private void addTrackWithMarker() {
EndToEndTestUtils.deleteAllTracks();
// Create a new track with two markers
EndToEndTestUtils.startRecording();
instrumentation.waitForIdleSync();
// Send gps before creating the first marker
EndToEndTestUtils.sendGps(2);
EndToEndTestUtils.createWaypoint(0);
EndToEndTestUtils.sendGps(2, 2);
EndToEndTestUtils.createWaypoint(1);
EndToEndTestUtils.sendGps(2, 4);
// Back to the tracks list
EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync();
EndToEndTestUtils.stopRecording(true);
}
/**
* Adds multiple tracks.
*/
private void addTracks() {
EndToEndTestUtils.deleteAllTracks();
// Create a new track with 3 gps points
EndToEndTestUtils.createTrackIfEmpty(3, true);
instrumentation.waitForIdleSync();
// Create an empty track
EndToEndTestUtils.createSimpleTrack(0, true);
instrumentation.waitForIdleSync();
assertEquals(2, EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount());
}
/**
* Adds multiple tracks with pauses.
*/
private void addTracksWithPause() {
EndToEndTestUtils.deleteAllTracks();
// Create a new track with 3 gps points
EndToEndTestUtils.createTrackWithPause(3);
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync();
// Create an empty track
EndToEndTestUtils.createTrackWithPause(0);
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync();
assertEquals(2, EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount());
}
/**
* Export all and import all.
*
* @param trackFileFormat the track file format
*/
private void exportImport(TrackFileFormat trackFileFormat) {
deleteExternalStorageFiles(trackFileFormat);
assertEquals(0, getExternalStorageFiles(trackFileFormat).length);
int trackCount = EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount();
// Export all
exportTracks(trackFileFormat, trackCount);
assertEquals(trackCount, getExternalStorageFiles(trackFileFormat).length);
if (trackCount == 1) {
EndToEndTestUtils.deleteAllTracks();
}
// Import all
importTracks(trackFileFormat);
EndToEndTestUtils.rotateCurrentActivity();
checkImportSuccess();
EndToEndTestUtils.SOLO.waitForActivity(TrackListActivity.class);
assertEquals(trackCount == 1 ? 1 : trackCount * 2,
EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount());
}
/**
* Exports all tracks.
*
* @param trackFileFormat the track file format
* @param trackCount the track count
*/
private void exportTracks(TrackFileFormat trackFileFormat, int trackCount) {
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_export_all), true);
EndToEndTestUtils.instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.clickOnText(trackFileFormat.name());
EndToEndTestUtils.getButtonOnScreen(
EndToEndTestUtils.trackListActivity.getString(R.string.generic_ok), true, true);
EndToEndTestUtils.SOLO.waitForText(getExportSuccessMessage(trackCount, trackFileFormat));
EndToEndTestUtils.getButtonOnScreen(
trackListActivity.getString(R.string.generic_ok), true, true);
instrumentation.waitForIdleSync();
}
/**
* Imports all tracks.
*
* @param trackFileFormat the track file format
*/
private void importTracks(TrackFileFormat trackFileFormat) {
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_import_all), true);
EndToEndTestUtils.SOLO.clickOnText(trackFileFormat.name());
EndToEndTestUtils.getButtonOnScreen(
EndToEndTestUtils.trackListActivity.getString(R.string.generic_ok), true, true);
}
/**
* Gets the export all success message.
*
* @param count the count of successfully exported tracks
* @param trackFileFormat the track file format
*/
private String getExportSuccessMessage(int count, TrackFileFormat trackFileFormat) {
String trackCount = trackListActivity.getResources()
.getQuantityString(R.plurals.tracks, count, count);
String path = FileUtils.getPathDisplayName(trackFileFormat.getExtension());
return trackListActivity.getString(R.string.export_external_storage_success, trackCount, path);
}
/**
* Gets the import all error message.
*
* @param trackFileFormat the track file format
*/
private String getImportErrorMessage(TrackFileFormat trackFileFormat) {
String fileCount = trackListActivity.getResources().getQuantityString(R.plurals.files, 0, 0);
String path = FileUtils.getPathDisplayName(trackFileFormat.getExtension());
return trackListActivity.getString(R.string.import_error, 0, fileCount, path);
}
/**
* Checks that import all is success.
*/
private void checkImportSuccess() {
// Waiting for the prefix is much faster than waiting for the whole string
EndToEndTestUtils.waitTextToDisappear(
trackListActivity.getString(R.string.generic_progress_title));
EndToEndTestUtils.SOLO.waitForText(
trackListActivity.getString(R.string.import_success).split("%")[0]);
EndToEndTestUtils.getButtonOnScreen(
trackListActivity.getString(R.string.generic_ok), true, true);
instrumentation.waitForIdleSync();
}
/**
* Creates one GPX file in the MyTracks folder.
*/
private void createOneGpxFile() {
String fileName = GPX_FILE_TRACK_NAME + "." + TrackFileFormat.GPX.getExtension();
String fileContent = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> " + "<gpx "
+ "version=\"1.1\" " + "creator=\"Created by Google My Tracks on Android.\" "
+ "xmlns=\"http://www.topografix.com/GPX/1/1\" "
+ "xmlns:topografix=\"http://www.topografix.com/GPX/Private/TopoGrafix/0/1\" "
+ "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
+ "xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1"
+ " http://www.topografix.com/GPX/1/1/gpx.xsd"
+ " http://www.topografix.com/GPX/Private/TopoGrafix/0/1"
+ " http://www.topografix.com/GPX/Private/TopoGrafix/0/1/topografix.xsd\"> " + "<metadata> "
+ "<name><![CDATA[" + GPX_FILE_TRACK_NAME + "]]></name> "
+ "<desc><![CDATA[testTrackDescription1373523959524]]></desc> " + "</metadata> " + "<trk> "
+ "<name><![CDATA[" + GPX_FILE_TRACK_NAME + "]]></name> "
+ "<desc><![CDATA[testTrackDescription1373523959524]]></desc> "
+ "<type><![CDATA[TestActivityType]]></type> "
+ "<extensions><topografix:color>c0c0c0</topografix:color></extensions> " + "<trkseg> "
+ "<trkpt lat=\"" + GPX_FILE_INIT_LATITUDE + "\" lon=\"" + GPX_FILE_INIT_LONGITUDE + "\"> "
+ "<time>2013-07-10T08:00:00.000Z</time> <ele>" + GPX_FILE_ELEVATION_MIN + "</ele>"
+ "</trkpt> " + "<trkpt lat=\"39.2995\" lon=\"116.0005\"> "
+ "<time>2013-07-10T08:00:01.000Z</time> " + "</trkpt> "
+ "<trkpt lat=\"39.299\" lon=\"116.001\"> " + "<time>2013-07-10T08:00:02.000Z</time> "
+ "</trkpt> " + "<trkpt lat=\"39.2985\" lon=\"116.0015\"> "
+ "<time>2013-07-10T08:00:03.000Z</time> " + "</trkpt> "
+ "<trkpt lat=\"39.298\" lon=\"116.002\"> " + "<time>2013-07-10T08:00:04.000Z</time> "
+ "</trkpt> " + "<trkpt lat=\"39.2975\" lon=\"116.0025\"> "
+ "<time>2013-07-10T08:00:05.000Z</time> " + "</trkpt> "
+ "<trkpt lat=\"39.297\" lon=\"116.003\"> " + "<time>2013-07-10T08:00:06.000Z</time> "
+ "</trkpt> " + "<trkpt lat=\"39.2965\" lon=\"116.0035\"> "
+ "<time>2013-07-10T08:00:07.000Z</time> " + "</trkpt> "
+ "<trkpt lat=\"39.296\" lon=\"116.004\"> " + "<time>2013-07-10T08:00:08.000Z</time> "
+ "</trkpt> " + "<trkpt lat=\"39.2955\" lon=\"116.0045\"> "
+ "<time>2013-07-10T08:00:09.000Z</time> <ele>" + GPX_FILE_ELEVATION_MAX + "</ele>"
+ "</trkpt> " + "</trkseg> " + "</trk> " + "</gpx>";
FileOutputStream fileOutputStream = null;
try {
File file = new File(
FileUtils.getPath(TrackFileFormat.GPX.getExtension()) + File.separator + fileName);
if (!file.exists()) {
file.createNewFile();
}
fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(fileContent.getBytes());
fileOutputStream.flush();
} catch (IOException e) {
Log.e(TAG, "Unable to write GPX file", e);
fail();
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
Log.e(TAG, "Unable to close GPX file", e);
fail();
}
}
}
}
/**
* Checks track imported from a GPX file.
*/
private void checkTrackFromGpxFile() {
EndToEndTestUtils.SOLO.clickOnText(GPX_FILE_TRACK_NAME);
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.waitForActivity(
TrackDetailActivity.class, EndToEndTestUtils.LONG_WAIT_TIME);
EndToEndTestUtils.SOLO.clickOnText(
trackListActivity.getString(R.string.track_detail_stats_tab));
instrumentation.waitForIdleSync();
double acceptDeviation = 0.1f;
Activity activity = EndToEndTestUtils.SOLO.getCurrentActivity();
double elevationMin = Double.parseDouble(((TextView) activity.findViewById(
R.id.stats_elevation_min).findViewById(R.id.stats_value)).getText().toString());
double elevationMax = Double.parseDouble(((TextView) activity.findViewById(
R.id.stats_elevation_max).findViewById(R.id.stats_value)).getText().toString());
double distance = Double.parseDouble(((TextView) activity.findViewById(R.id.stats_distance)
.findViewById(R.id.stats_value)).getText().toString());
double averageSpeed = Double.parseDouble(((TextView) activity.findViewById(
R.id.stats_average_speed).findViewById(R.id.stats_value)).getText().toString());
assertEquals(Double.parseDouble(GPX_FILE_ELEVATION_MIN), elevationMin);
assertEquals(getGpxFileElevationMax(), elevationMax);
// in km
double calculateDistance = getGpxFileDistance();
// in km/h
double calculateAverageSpeed = calculateDistance
/ (GPX_FILE_TIME_INTERVAL + UnitConversions.S_TO_MIN * UnitConversions.MIN_TO_HR);
assertTrue((calculateDistance - distance) / calculateDistance < acceptDeviation);
assertTrue((calculateAverageSpeed - averageSpeed) / calculateAverageSpeed < acceptDeviation);
EndToEndTestUtils.SOLO.goBack();
}
/**
* Gets the GPX file distance in km.
*/
private double getGpxFileDistance() {
double distance = 0.0;
double latitude = GPX_FILE_INIT_LATITUDE;
double longitude = GPX_FILE_INIT_LONGITUDE;
Location current = new Location(LocationManager.GPS_PROVIDER);
current.setLatitude(latitude);
current.setLongitude(longitude);
for (int i = 1; i < 10; i++) {
Location next = new Location(LocationManager.GPS_PROVIDER);
next.setLatitude(latitude - 0.0005 * i);
next.setLongitude(longitude + 0.0005 * i);
distance = distance + next.distanceTo(current) * UnitConversions.M_TO_KM;
current = next;
}
return distance;
}
/**
* Gets the GPX file elevation max.
*/
private double getGpxFileElevationMax() {
/*
* Returns the highest value of all the weighted averages. Since there are
* only two elevation data points, the highest value is the weighted average
* of both points.
*/
return (Double.parseDouble(GPX_FILE_ELEVATION_MIN) + Double.parseDouble(GPX_FILE_ELEVATION_MAX))
/ 2.0;
}
/**
* Gets the external storage files.
*
* @param trackFileFormat the track file format
*/
private File[] getExternalStorageFiles(final TrackFileFormat trackFileFormat) {
FileFilter filter = new FileFilter() {
@Override
public boolean accept(File file) {
String suffix = trackFileFormat == TrackFileFormat.KML ? ".kmz"
: "." + trackFileFormat.getExtension();
return file.getName().endsWith(suffix);
}
};
File dir = new File(FileUtils.getPath(trackFileFormat.getExtension()));
File[] files = dir.listFiles(filter);
return files == null ? new File[0] : files;
}
/**
* Deletes the external storage files.
*
* @param trackFileFormat the track file format
*/
private void deleteExternalStorageFiles(TrackFileFormat trackFileFormat) {
File dir = new File(FileUtils.getPath(trackFileFormat.getExtension()));
File[] files = dir.listFiles();
if (files == null) {
return;
}
for (File file : files) {
file.delete();
}
}
/**
* Shows grade elevation.
*/
private void showGradeElevation() {
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
EndToEndTestUtils.SOLO.clickOnText(
trackListActivity.getString(R.string.track_detail_stats_tab));
String gradeElevation = trackListActivity.getString(R.string.settings_stats_grade_elevation);
if (!EndToEndTestUtils.SOLO.isCheckBoxChecked(gradeElevation)) {
EndToEndTestUtils.SOLO.clickOnText(gradeElevation);
}
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.SOLO.goBack();
}
}
@@ -0,0 +1,196 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest.common;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
import com.google.android.apps.mytracks.endtoendtest.GoogleUtils;
import com.google.android.maps.mytracks.R;
import com.google.api.services.drive.model.File;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import java.util.List;
/**
* Tests export single track to Google. Each test would export one track to
* Google Maps, Google Fusion Tables and Google Spreadsheets.
*
* @author youtaol
*/
public class ExportSingleTrackTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private Instrumentation instrumentation;
private TrackListActivity activityMyTracks;
public ExportSingleTrackTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
activityMyTracks = getActivity();
GoogleUtils.deleteAllMaps(activityMyTracks.getApplicationContext(), GoogleUtils.ACCOUNT_1);
GoogleUtils.deleteDriveTestFiles(
activityMyTracks.getApplicationContext(), GoogleUtils.ACCOUNT_1);
EndToEndTestUtils.setupForAllTest(instrumentation, activityMyTracks);
}
/**
* Checks all services and send to google.
*/
public void testCreateAndSendTrack_send() {
// Create a new track.
EndToEndTestUtils.createSimpleTrack(1, false);
instrumentation.waitForIdleSync();
checkSendTrackToGoogle();
}
/**
* Checks all services and send to google.
*/
public void testCreateAndSendTrack_sendPausedTrack() {
EndToEndTestUtils.deleteAllTracks();
EndToEndTestUtils.createTrackWithPause(3);
instrumentation.waitForIdleSync();
checkSendTrackToGoogle();
}
/**
* Sends two tracks with same activity. Two tracks should be in the same
* spreadsheet.
*/
public void testSendTwoTracksWithSameActivity() {
String testActivity = "(TestActivity)";
EndToEndTestUtils.activityType = testActivity;
GoogleUtils.deleteSpreadsheets(
EndToEndTestUtils.trackListActivity.getApplicationContext(), GoogleUtils.ACCOUNT_1);
EndToEndTestUtils.createSimpleTrack(1, false);
boolean result = sendToGoogle(activityMyTracks.getString(R.string.export_google_maps))
&& sendToGoogle(activityMyTracks.getString(R.string.export_google_fusion_tables))
&& sendToGoogle(activityMyTracks.getString(R.string.export_google_spreadsheets));
result = result && sendToGoogle(activityMyTracks.getString(R.string.export_google_maps))
&& sendToGoogle(activityMyTracks.getString(R.string.export_google_fusion_tables))
&& sendToGoogle(activityMyTracks.getString(R.string.export_google_spreadsheets));
// Result is true mean has account bound with this device and send
// successful.
if (result) {
List<File> fileList = GoogleUtils.searchSpreadsheets(
activityMyTracks.getApplicationContext(), GoogleUtils.ACCOUNT_1);
assertEquals(1, fileList.size());
}
}
/**
* Checks the process of sending track to google.
*/
private void checkSendTrackToGoogle() {
if (!sendToGoogle(activityMyTracks.getString(R.string.export_google_maps))
|| !sendToGoogle(activityMyTracks.getString(R.string.export_google_fusion_tables))
|| !sendToGoogle(activityMyTracks.getString(R.string.export_google_spreadsheets))) {
return;
}
// Check whether all data is correct on Google Drive, Maps, Documents, and
// Spreadsheet.
// assertTrue(SyncTestUtils.checkFile(EndToEndTestUtils.trackName, true,
// SyncTestUtils.getGoogleDrive(activityMyTracks.getApplicationContext())));
assertTrue(GoogleUtils.deleteMaps(
activityMyTracks.getApplicationContext(), GoogleUtils.ACCOUNT_1,
EndToEndTestUtils.trackName));
assertTrue(GoogleUtils.deleteFusionTables(
activityMyTracks.getApplicationContext(), GoogleUtils.ACCOUNT_1,
EndToEndTestUtils.trackName));
assertTrue(GoogleUtils.deleteSpreadsheetsRow(
activityMyTracks.getApplicationContext(), GoogleUtils.ACCOUNT_1,
EndToEndTestUtils.trackName));
}
/**
* Sends a track to Google.
*
* @param exportDestination destination to export
* @return true means send successfully
*/
private boolean sendToGoogle(String exportDestination) {
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_export), true);
EndToEndTestUtils.SOLO.waitForText(activityMyTracks.getString(R.string.export_title));
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.clickOnText(exportDestination);
instrumentation.waitForIdleSync();
EndToEndTestUtils.getButtonOnScreen(activityMyTracks.getString(R.string.menu_export), true,
true);
instrumentation.waitForIdleSync();
if (!GoogleUtils.isAccountAvailable()) {
return false;
}
// Following check the process of "Send to Google", the second condition is
// in case the export has done.
assertTrue(EndToEndTestUtils.SOLO.waitForText(activityMyTracks
.getString(R.string.generic_progress_title))
|| EndToEndTestUtils.SOLO.waitForText(activityMyTracks
.getString(R.string.generic_success_title)));
// Waiting the send is finish. Should double check it for the progress
// dialog may disappear and display again while switch to next send(There
// are four sends currently, there are send to drive, maps, fusion table and
// spreadsheet).
while (EndToEndTestUtils.SOLO.waitForText(
activityMyTracks.getString(R.string.generic_progress_title), 1,
EndToEndTestUtils.SHORT_WAIT_TIME)
|| EndToEndTestUtils.SOLO.waitForText(
activityMyTracks.getString(R.string.generic_progress_title), 1,
EndToEndTestUtils.SHORT_WAIT_TIME)) {}
if (exportDestination.endsWith(activityMyTracks.getString(R.string.export_google_maps))) {
// Check whether the result dialog is display.
assertTrue(EndToEndTestUtils.SOLO.waitForText(activityMyTracks
.getString(R.string.share_track_share_url)));
} else {
assertTrue(EndToEndTestUtils.SOLO.waitForText(activityMyTracks
.getString(R.string.generic_success_title)));
}
EndToEndTestUtils
.getButtonOnScreen(activityMyTracks.getString(R.string.generic_ok), true, true);
return true;
}
/**
* Sends a large track to Google.
*/
public void testSendLargeTrackToGoogle() {
EndToEndTestUtils.deleteAllTracks();
EndToEndTestUtils.createSimpleTrack(200, false);
instrumentation.waitForIdleSync();
checkSendTrackToGoogle();
}
@Override
protected void tearDown() throws Exception {
EndToEndTestUtils.activityType = EndToEndTestUtils.DEFAULT_ACTIVITY_TYPE;
EndToEndTestUtils.SOLO.finishOpenedActivities();
super.tearDown();
}
}
@@ -0,0 +1,189 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest.common;
import com.google.android.apps.mytracks.TrackDetailActivity;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
import com.google.android.maps.mytracks.R;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.view.KeyEvent;
import android.widget.ListView;
import java.util.Locale;
/**
* Tests menu items.
*
* @author Youtao Liu
*/
public class MenuItemsTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private Instrumentation instrumentation;
private TrackListActivity trackListActivity;
public MenuItemsTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
trackListActivity = getActivity();
EndToEndTestUtils.setupForAllTest(instrumentation, trackListActivity);
}
@Override
protected void tearDown() throws Exception {
EndToEndTestUtils.SOLO.finishOpenedActivities();
super.tearDown();
}
/**
* Tests following More menu items.
* <ul>
* <li>Aggregated statistics in {@link TrackListActivity}</li>
* <li>Help & feedback in {@link TrackListActivity}</li>
* <li>Help & feedback in {@link TrackDetailActivity}</li>
* <li>Export in {@link TrackDetailActivity}</li>
* </ul>
*/
public void testMoreMenuItems() {
// Aggregated statistics in TrackListActivity
EndToEndTestUtils.findMenuItem(
trackListActivity.getString(R.string.menu_aggregated_statistics), true);
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.stats_distance));
EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync();
// Help & feedback in TrackListActivity
checkHelpFeedbackPage();
EndToEndTestUtils.createSimpleTrack(1, false);
instrumentation.waitForIdleSync();
// Help & feedback in TrackDetailActivity
checkHelpFeedbackPage();
// Export in TrackDetailActivity
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_export), true);
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.export_title));
}
/**
* Tests the search menu. When search is displayed, the track controller
* should be hidden.
*/
public void testSearchMenu() {
EndToEndTestUtils.deleteAllTracks();
EndToEndTestUtils.createSimpleTrack(0, true);
assertTrue(isTrackControllerShown());
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_search), true);
assertFalse(isTrackControllerShown());
EndToEndTestUtils.enterTextAvoidSoftKeyBoard(0, EndToEndTestUtils.trackName);
sendKeys(KeyEvent.KEYCODE_ENTER);
instrumentation.waitForIdleSync();
assertEquals(1, EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount());
// TODO: not sure why the following fails. It passes in debug mode.
// assertFalse(isTrackControllerShown());
EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync();
assertTrue(isTrackControllerShown());
}
/**
* Checks the voice frequency and the split frequency menu. When recording,
* they should be in both the {@link TrackDetailActivity} menu and the
* recording settings. When not recording, they should only be in the
* recording settings.
*/
public void testFrequencyMenu() {
EndToEndTestUtils.startRecording();
assertTrue(EndToEndTestUtils.findMenuItem(
trackListActivity.getString(R.string.menu_voice_frequency), false));
assertTrue(EndToEndTestUtils.findMenuItem(
trackListActivity.getString(R.string.menu_split_frequency), false));
checkFrequencyInSettings();
EndToEndTestUtils.stopRecording(true);
assertFalse(EndToEndTestUtils.findMenuItem(
trackListActivity.getString(R.string.menu_voice_frequency), false));
assertFalse(EndToEndTestUtils.findMenuItem(
trackListActivity.getString(R.string.menu_split_frequency), false));
checkFrequencyInSettings();
}
/**
* Tests start and stop gps.
*/
public void testGpsMenu() {
// Start gps
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_start_gps), true);
EndToEndTestUtils.waitTextToDisappear(trackListActivity.getString(R.string.menu_start_gps));
assertTrue(
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_stop_gps), false));
// Stop gps
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_stop_gps), true);
EndToEndTestUtils.waitTextToDisappear(trackListActivity.getString(R.string.menu_stop_gps));
assertTrue(EndToEndTestUtils.findMenuItem(
trackListActivity.getString(R.string.menu_start_gps), false));
}
/**
* Checks the help & feedback page.
*/
private void checkHelpFeedbackPage() {
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_help_feedback), true);
assertNotNull(EndToEndTestUtils.getButtonOnScreen(
trackListActivity.getString(R.string.menu_feedback).toUpperCase(Locale.getDefault()), true,
false));
EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync();
}
/**
* Returns true if the track controller is shown.
*/
private boolean isTrackControllerShown() {
return trackListActivity.findViewById(R.id.track_controler_container).isShown();
}
/**
* Checks that the frequency options exists in settings.
*/
private void checkFrequencyInSettings() {
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.settings_recording));
assertTrue(EndToEndTestUtils.SOLO.searchText(
trackListActivity.getString(R.string.menu_voice_frequency), 1, true, true));
assertTrue(EndToEndTestUtils.SOLO.searchText(
trackListActivity.getString(R.string.menu_split_frequency), 1, true, true));
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.SOLO.goBack();
}
}
@@ -0,0 +1,75 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest.common;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
import com.google.android.apps.mytracks.util.GoogleLocationUtils;
import com.google.android.maps.mytracks.R;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.view.View;
/**
* Tests the my location button.
*
* @author Youtao Liu
*/
public class MyLocationTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private Instrumentation instrumentation;
private TrackListActivity trackListActivity;
public MyLocationTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
trackListActivity = getActivity();
EndToEndTestUtils.setupForAllTest(instrumentation, trackListActivity);
}
@Override
protected void tearDown() throws Exception {
EndToEndTestUtils.SOLO.finishOpenedActivities();
super.tearDown();
}
/**
* Tests the my location button.
*/
public void testMyLocation() {
EndToEndTestUtils.deleteAllTracks();
EndToEndTestUtils.createSimpleTrack(1, false);
View myLocation = EndToEndTestUtils.SOLO.getCurrentActivity()
.findViewById(R.id.map_my_location);
EndToEndTestUtils.SOLO.clickOnView(myLocation);
instrumentation.waitForIdleSync();
if (EndToEndTestUtils.isEmulator) {
EndToEndTestUtils.SOLO.waitForText(
GoogleLocationUtils.getGpsDisabledMyLocationMessage(trackListActivity), 1,
EndToEndTestUtils.SHORT_WAIT_TIME);
} else {
// TODO How to verify my location is shown on the map?
}
}
}
@@ -0,0 +1,152 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest.common;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
import com.google.android.apps.mytracks.services.TrackRecordingService;
import android.app.Instrumentation;
import android.location.Location;
import android.test.ActivityInstrumentationTestCase2;
/**
* Tests pause and resume during a recording.
*
* @author Youtao Liu
*/
public class PauseResumeTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private static final int SEND_INTERVAL = 100; // ms
private Instrumentation instrumentation;
private TrackListActivity trackListActivity;
public PauseResumeTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
trackListActivity = getActivity();
EndToEndTestUtils.setupForAllTest(instrumentation, trackListActivity);
}
@Override
protected void tearDown() throws Exception {
EndToEndTestUtils.SOLO.finishOpenedActivities();
super.tearDown();
}
/**
* Tests stop after a pause.
*/
public void testStopAfterPause() {
int firstBatch = 3;
int secondBatch = 10;
EndToEndTestUtils.checkNotRecording();
// Start a recording
EndToEndTestUtils.startRecording();
EndToEndTestUtils.checkUnderRecording();
EndToEndTestUtils.sendGps(firstBatch);
// Pause the recording
EndToEndTestUtils.pauseRecording();
EndToEndTestUtils.checkUnderPaused();
EndToEndTestUtils.sendGps(secondBatch, firstBatch);
// Stop the recording
EndToEndTestUtils.stopRecording(true);
checkTrackLocation(firstBatch, 1, 0);
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.checkNotRecording();
}
/**
* Tests stop after a resume.
*/
public void testStopAfterResume() {
int firstBatch = 3;
int secondBatch = 5;
int thirdBatch = 7;
EndToEndTestUtils.checkNotRecording();
// Start a recording
EndToEndTestUtils.startRecording();
EndToEndTestUtils.checkUnderRecording();
EndToEndTestUtils.sendGps(firstBatch);
// Pause the recording
EndToEndTestUtils.pauseRecording();
EndToEndTestUtils.checkUnderPaused();
// Send gps signal after pause
EndToEndTestUtils.sendGps(secondBatch, firstBatch, SEND_INTERVAL);
// Resume the recording
EndToEndTestUtils.resumeRecording();
EndToEndTestUtils.checkUnderRecording();
EndToEndTestUtils.sendGps(thirdBatch, firstBatch + secondBatch);
// Stop the recordinga
EndToEndTestUtils.stopRecording(true);
checkTrackLocation(firstBatch + secondBatch, 1, 1);
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.checkNotRecording();
}
/**
* Check the last track's location.
*
* @param expectedPoint the number of expected points
* @param expectedPause the number of expected pauses
* @param expectedResume the number of expected resumes
*/
private void checkTrackLocation(int expectedPoint, int expectedPause, int expectedResume) {
if (EndToEndTestUtils.isEmulator) {
int point = 0;
int pause = 0;
int resume = 0;
MyTracksProviderUtils myTracksProviderUtils = MyTracksProviderUtils.Factory.get(
trackListActivity.getApplicationContext());
long trackId = myTracksProviderUtils.getLastTrack().getId();
LocationIterator locationIterator = myTracksProviderUtils.getTrackPointLocationIterator(
trackId, 0, false, MyTracksProviderUtils.DEFAULT_LOCATION_FACTORY);
while (locationIterator.hasNext()) {
Location location = locationIterator.next();
double latitude = location.getLatitude();
if (latitude == TrackRecordingService.PAUSE_LATITUDE) {
pause++;
} else if (latitude == TrackRecordingService.RESUME_LATITUDE) {
resume++;
} else {
point++;
}
}
assertEquals(expectedPoint, point);
assertEquals(expectedPause, pause);
assertEquals(expectedResume, resume);
}
}
}
@@ -0,0 +1,296 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest.common;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
import com.google.android.maps.mytracks.R;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.CheckBox;
import junit.framework.Assert;
/**
* Tests the settings.
*
* @author Youtao Liu
*/
public class SettingsTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private static final String GMAIL_COM = "gmail.com";
private static final String NEW_ACTIVITY_TYPE = "NewActivityType";
private Instrumentation instrumentation;
private TrackListActivity trackListActivity;
public SettingsTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
trackListActivity = getActivity();
EndToEndTestUtils.setupForAllTest(instrumentation, trackListActivity);
}
@Override
protected void tearDown() throws Exception {
EndToEndTestUtils.SOLO.finishOpenedActivities();
super.tearDown();
}
/**
* Tests changing preferred units to imperial.
*/
public void testPreferredUnits_imperial() {
testPreferredUnits(R.string.unit_mile);
}
/**
* Tests changing preferred units to metric.
*/
public void testPreferredUnits_metric() {
testPreferredUnits(R.string.unit_kilometer);
}
/**
* Tests changing preferred units while recording and viewing the chart tab.
*/
public void testPreferredUnitsRecording_chart() {
testPreferredUnitsRecording(R.string.track_detail_chart_tab);
}
/**
* Tests changing preferred units while recording and viewing the stats tab.
*/
public void testPreferredUnitsRecording_stats() {
testPreferredUnitsRecording(R.string.track_detail_stats_tab);
}
/**
* Tests changing preferred units while recording and viewing the map tab.
*/
public void testPreferredUnitsRecording_map() {
testPreferredUnitsRecording(R.string.track_detail_map_tab);
}
/**
* Tests grade/elevation and latitude/longitude..
*/
public void testGradeElevationAndLatitudeLongitude() {
// Ennable grade/elevation and latitude/longitude
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
EndToEndTestUtils.SOLO.clickOnText(
trackListActivity.getString(R.string.track_detail_stats_tab));
assertTrue(EndToEndTestUtils.SOLO.waitForText(
trackListActivity.getString(R.string.settings_stats_units_title)));
EndToEndTestUtils.SOLO.clickOnText(
trackListActivity.getString(R.string.settings_stats_grade_elevation));
EndToEndTestUtils.SOLO.clickOnText(
trackListActivity.getString(R.string.settings_stats_coordinate));
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.SOLO.goBack();
// Start recording and check stats tab
EndToEndTestUtils.startRecording();
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.clickOnText(
trackListActivity.getString(R.string.track_detail_stats_tab));
assertTrue(EndToEndTestUtils.SOLO.waitForText(
trackListActivity.getString(R.string.stats_elevation), 1,
EndToEndTestUtils.NORMAL_WAIT_TIME, true));
assertTrue(
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.stats_grade)));
assertTrue(
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.stats_latitude)));
assertTrue(
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.stats_longitude)));
// Stop recording and check stats tab
EndToEndTestUtils.stopRecording(true);
assertTrue(EndToEndTestUtils.SOLO.waitForText(
trackListActivity.getString(R.string.stats_elevation), 1,
EndToEndTestUtils.NORMAL_WAIT_TIME, true));
assertTrue(
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.stats_grade)));
assertNull(
EndToEndTestUtils.findTextView(trackListActivity.getString(R.string.stats_latitude)));
assertNull(
EndToEndTestUtils.findTextView(trackListActivity.getString(R.string.stats_longitude)));
}
/**
* Tests default track name and default activity type.
*/
public void testDefaultTrackNameAndDefaultActivityType() {
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.settings_recording));
// Change the default track name to number
EndToEndTestUtils.SOLO.clickOnText(
trackListActivity.getString(R.string.settings_recording_track_name_title));
EndToEndTestUtils.SOLO.clickOnText(
trackListActivity.getString(R.string.settings_recording_track_name_number_option));
// Change the default activity type to NEW_ACTIVITY_TYPE
EndToEndTestUtils.SOLO.clickOnText(
trackListActivity.getString(R.string.settings_recording_default_activity_title));
EndToEndTestUtils.enterTextAvoidSoftKeyBoard(0, NEW_ACTIVITY_TYPE);
EndToEndTestUtils.getButtonOnScreen(
trackListActivity.getString(R.string.generic_ok), true, true);
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.startRecording();
instrumentation.waitForIdleSync();
EndToEndTestUtils.stopRecording(false);
assertTrue(EndToEndTestUtils.SOLO.searchText(
trackListActivity.getString(R.string.track_name_format).split(" ")[0]));
assertTrue(EndToEndTestUtils.SOLO.searchText(NEW_ACTIVITY_TYPE));
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.generic_save));
}
/**
* Tests track color setting for fixed thresholds.
*/
public void testTrackColor_fixed() {
testTrackColor(R.string.settings_map_track_color_mode_fixed,
R.string.settings_map_track_color_mode_fixed_summary);
}
/**
* Tests track color setting for dynamic thresholds.
*/
public void testTrackColorSettings_dynamic() {
testTrackColor(R.string.settings_map_track_color_mode_dynamic,
R.string.settings_map_track_color_mode_dynamic_summary);
}
/**
* Tests track color setting for single color.
*/
public void testTrackColorSettings_single() {
testTrackColor(R.string.settings_map_track_color_mode_single,
R.string.settings_map_track_color_mode_single);
}
/**
* Tests allow access.
*/
public void testAllowAccess() {
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.settings_advanced));
assertTrue(EndToEndTestUtils.SOLO.waitForText(
trackListActivity.getString(R.string.settings_sharing_allow_access), 1,
EndToEndTestUtils.NORMAL_WAIT_TIME));
EndToEndTestUtils.SOLO.clickOnCheckBox(0);
assertTrue(EndToEndTestUtils.SOLO.waitForText(
trackListActivity.getString(R.string.settings_sharing_allow_access_confirm_message), 1,
EndToEndTestUtils.NORMAL_WAIT_TIME));
EndToEndTestUtils.SOLO.clickOnButton(trackListActivity.getString(R.string.generic_yes));
instrumentation.waitForIdleSync();
assertEquals(true, EndToEndTestUtils.SOLO.getCurrentViews(CheckBox.class).get(0).isChecked());
EndToEndTestUtils.SOLO.goBack();
}
/**
* Tests sync.
*/
public void testSync() {
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.menu_sync_drive));
// Whether there is a gmail.com account
if (!EndToEndTestUtils.SOLO.waitForText(GMAIL_COM, 1, EndToEndTestUtils.TINY_WAIT_TIME)) {
return;
}
// Click the first gmail.com account
EndToEndTestUtils.SOLO.clickOnText(GMAIL_COM, 0);
instrumentation.waitForIdleSync();
EndToEndTestUtils.getButtonOnScreen(
trackListActivity.getString(R.string.generic_ok), true, true);
EndToEndTestUtils.SOLO.waitForText(
trackListActivity.getString(R.string.sync_drive_confirm_message).split("%")[0], 1,
EndToEndTestUtils.SHORT_WAIT_TIME);
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.generic_no));
EndToEndTestUtils.SOLO.goBack();
assertEquals(false,
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_sync_now), false));
}
/**
* Tests preferred units.
*
* @param unitId the unit id
*/
private void testPreferredUnits(int unitId) {
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
EndToEndTestUtils.SOLO.clickOnText(
trackListActivity.getString(R.string.track_detail_stats_tab));
Assert.assertTrue(EndToEndTestUtils.SOLO.waitForText(
trackListActivity.getString(R.string.settings_stats_units_title)));
EndToEndTestUtils.SOLO.clickOnText(
trackListActivity.getString(R.string.settings_stats_units_title));
instrumentation.waitForIdleSync();
String unit = trackListActivity.getString(unitId);
EndToEndTestUtils.SOLO.clickOnText(unit);
EndToEndTestUtils.SOLO.searchText(unit);
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.SOLO.goBack();
}
/**
* Tests preferred units while recording.
*
* @param tabId the tab id
*/
private void testPreferredUnitsRecording(int tabId) {
testPreferredUnits(R.string.unit_kilometer);
EndToEndTestUtils.startRecording();
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(tabId));
EndToEndTestUtils.sendGps(3);
testPreferredUnits(R.string.unit_mile);
EndToEndTestUtils.sendGps(3, 3);
EndToEndTestUtils.stopRecording(true);
}
/**
* Tests track color setting.
*
* @param modeId the mode id
* @param summaryId the summary id
*/
private void testTrackColor(int modeId, int summaryId) {
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.menu_map));
EndToEndTestUtils.SOLO.clickOnText(
trackListActivity.getString(R.string.settings_map_track_color_mode));
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(modeId));
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(summaryId));
}
}
@@ -0,0 +1,125 @@
/*
* Copyright 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest.common;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
import com.google.android.apps.mytracks.endtoendtest.GoogleUtils;
import com.google.android.apps.mytracks.endtoendtest.sync.SyncTestUtils;
import com.google.android.maps.mytracks.R;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.CheckBox;
import java.util.ArrayList;
/**
* Tests the share feature.
*
* @author youtaol
*/
public class ShareTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private Instrumentation instrumentation;
private TrackListActivity activityMyTracks;
public ShareTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
activityMyTracks = getActivity();
EndToEndTestUtils.setupForAllTest(instrumentation, activityMyTracks);
}
/**
* Tests the share one track.
*/
public void testShare() {
EndToEndTestUtils.resetAllSettings(activityMyTracks, false);
EndToEndTestUtils.createTrackIfEmpty(0, false);
// Click share again and confirm the share.
EndToEndTestUtils.findMenuItem(activityMyTracks.getString(R.string.menu_share), true);
// Whether can found any account.
if (EndToEndTestUtils.SOLO.waitForText(
activityMyTracks.getString(R.string.send_google_no_account_title), 1,
EndToEndTestUtils.VERY_SHORT_WAIT_TIME)) {
EndToEndTestUtils.SOLO.clickOnText(activityMyTracks.getString(R.string.generic_ok));
return;
}
boolean isAccount2Bound = false;
// If Choose account dialog prompt, choose the first account.
if (EndToEndTestUtils.SOLO.waitForText(
activityMyTracks.getString(R.string.send_google_choose_account_title), 1,
EndToEndTestUtils.SHORT_WAIT_TIME)) {
// Whether can found account2.
if (EndToEndTestUtils.SOLO.waitForText(
GoogleUtils.ACCOUNT_2, 1, EndToEndTestUtils.VERY_SHORT_WAIT_TIME)) {
isAccount2Bound = true;
}
EndToEndTestUtils.SOLO.clickOnText(GoogleUtils.ACCOUNT_1);
EndToEndTestUtils.getButtonOnScreen(
activityMyTracks.getString(R.string.generic_ok), true, true);
}
// Check all check boxes.
assertTrue(EndToEndTestUtils.SOLO.waitForText(activityMyTracks
.getString(R.string.share_track_title)));
ArrayList<CheckBox> checkBoxs = EndToEndTestUtils.SOLO.getCurrentViews(CheckBox.class);
for (int i = 0; i < checkBoxs.size(); i++) {
if (!checkBoxs.get(i).isChecked()) {
EndToEndTestUtils.SOLO.clickOnView(checkBoxs.get(i));
instrumentation.waitForIdleSync();
}
}
// Input account to share and click OK button.
assertTrue(EndToEndTestUtils.SOLO.waitForText(activityMyTracks
.getString(R.string.share_track_emails_hint)));
EndToEndTestUtils.enterTextAvoidSoftKeyBoard(0, GoogleUtils.ACCOUNT_2);
EndToEndTestUtils
.getButtonOnScreen(activityMyTracks.getString(R.string.generic_ok), true, true);
// Waiting the send is finish.
while (EndToEndTestUtils.SOLO.waitForText(
activityMyTracks.getString(R.string.generic_progress_title), 1,
EndToEndTestUtils.SHORT_WAIT_TIME)) {}
assertTrue(EndToEndTestUtils.SOLO.waitForText(EndToEndTestUtils.SOLO
.getString(R.string.share_track_share_url_title)));
EndToEndTestUtils.SOLO.goBack();
// Make more checks if the second account is also bound with this device.
if (isAccount2Bound) {
EndToEndTestUtils.SOLO.goBack();
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_2);
EndToEndTestUtils.findMenuItem(
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
assertTrue(EndToEndTestUtils.SOLO.waitForText(
activityMyTracks.getString(R.string.track_list_shared_with_me), 1,
EndToEndTestUtils.SUPER_LONG_WAIT_TIME));
assertTrue(EndToEndTestUtils.SOLO.waitForText(EndToEndTestUtils.trackName, 1,
EndToEndTestUtils.SUPER_LONG_WAIT_TIME));
}
}
}
@@ -0,0 +1,181 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest.common;
import com.google.android.apps.mytracks.TrackDetailActivity;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
import com.google.android.apps.mytracks.fragments.ChartFragment;
import com.google.android.apps.mytracks.fragments.MyTracksMapFragment;
import com.google.android.apps.mytracks.fragments.StatsFragment;
import com.google.android.maps.mytracks.R;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.view.Display;
import android.view.View;
import junit.framework.Assert;
/**
* Tests switching views and the menu list of each view.
*
* @author Youtao Liu
*/
public class ViewsTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private Instrumentation instrumentation;
private TrackListActivity trackListActivity;
public ViewsTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
trackListActivity = getActivity();
EndToEndTestUtils.setupForAllTest(instrumentation, trackListActivity);
}
@Override
protected void tearDown() throws Exception {
EndToEndTestUtils.SOLO.finishOpenedActivities();
super.tearDown();
}
/**
* Switches tab from {@link MyTracksMapFragment} to {@link ChartFragment},
* then to {@link StatsFragment}, and then to {@link MyTracksMapFragment}. In
* each tab, checks menu items like settings and map layer.
*/
public void testSwitchTabAndViewMenu() {
EndToEndTestUtils.createTrackIfEmpty(3, true);
EndToEndTestUtils.SOLO.scrollUp();
EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.trackName, 1, true);
// Switch to chart view
EndToEndTestUtils.SOLO.clickOnText(
trackListActivity.getString(R.string.track_detail_chart_tab));
EndToEndTestUtils.rotateCurrentActivity();
assertTrue(
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), false));
assertFalse(EndToEndTestUtils.findMenuItem(
trackListActivity.getString(R.string.menu_map_layer), false));
// Switch to stats view
EndToEndTestUtils.SOLO.clickOnText(
trackListActivity.getString(R.string.track_detail_stats_tab));
assertTrue(
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), false));
assertFalse(EndToEndTestUtils.findMenuItem(
trackListActivity.getString(R.string.menu_map_layer), false));
// Switch to map view
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.track_detail_map_tab));
EndToEndTestUtils.rotateCurrentActivity();
assertTrue(
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), false));
assertTrue(EndToEndTestUtils.findMenuItem(
trackListActivity.getString(R.string.menu_map_layer), false));
}
/**
* Test selecting map layer.
*/
public void testMapLayer() {
EndToEndTestUtils.createTrackIfEmpty(1, false);
selectMapLayer(R.string.menu_terrain);
selectMapLayer(R.string.menu_satellite_with_streets);
selectMapLayer(R.string.menu_satellite);
selectMapLayer(R.string.menu_map);
}
/**
* Tests the track controller position in landscape view and portrait view on
* {@link TrackListActivity} and {@link TrackDetailActivity}.
*/
public void testTrackControllerPostion() {
checkTrackControllerPosition();
EndToEndTestUtils.rotateCurrentActivity();
instrumentation.waitForIdleSync();
checkTrackControllerPosition();
EndToEndTestUtils.startRecording();
instrumentation.waitForIdleSync();
checkTrackControllerPosition();
EndToEndTestUtils.rotateCurrentActivity();
instrumentation.waitForIdleSync();
checkTrackControllerPosition();
EndToEndTestUtils.stopRecording(true);
EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync();
checkTrackControllerPosition();
EndToEndTestUtils.rotateCurrentActivity();
instrumentation.waitForIdleSync();
checkTrackControllerPosition();
}
/**
* Selects a map layer
*
* @param id the map layer id
*/
private void selectMapLayer(int id) {
// Make sure can see the map tab
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.track_detail_map_tab));
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_map_layer), true);
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(id));
EndToEndTestUtils.getButtonOnScreen(
trackListActivity.getString(R.string.generic_ok), true, true);
instrumentation.waitForIdleSync();
}
/**
* Checks the position of track controller in landscape view and portrait
* view.
*/
@SuppressWarnings("deprecation")
private void checkTrackControllerPosition() {
View controller = EndToEndTestUtils.SOLO.getCurrentActivity()
.findViewById(R.id.track_controler_container);
Display display = EndToEndTestUtils.SOLO.getCurrentActivity()
.getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
if (width > height) {
// In landscape view
Assert.assertTrue(controller.getWidth() < controller.getHeight());
Assert.assertTrue(controller.getTop() < height / 2);
Assert.assertTrue(controller.getRight() < width / 2);
} else {
// In portrait view
Assert.assertTrue(controller.getWidth() > controller.getHeight());
Assert.assertTrue(controller.getTop() > height / 2);
Assert.assertTrue(controller.getRight() > width / 2);
}
}
}
@@ -0,0 +1,155 @@
package com.google.android.apps.mytracks.endtoendtest.others;
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Environment;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager.LayoutParams;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import junit.framework.Assert;
/**
* A utility to support the big test cases, such as sensor test, stress test and
* so forth which under the package
* {@link com.google.android.apps.mytracks.endtoendtest.others}.
*
* @author Youtao Liu
*/
public class BigTestUtils {
public static final String DISABLE_MESSAGE = "This test is disabled";
public static final String MYTRACKS_PROCESS_NAME = "com.google.android.maps.mytracks";
public static final String MYTRACKS_TEST_INFO_FILE = "MyTracksTestInfo.txt";
private static final String TAG = BigTestUtils.class.getSimpleName();
/**
* Gets the memory usage of MyTracks process. This method would get the Pss
* memory. Pss is the amount of memory shared with other processes, accounted
* in a way that the amount is divided evenly between the processes that share
* it. This is memory that would not be released if the process was
* terminated, but is indicative of the amount that this process is
* "contributing" to the overall memory load.
*
* @param context
*/
public static String getMyTracksPssMemoryInfo(Context context) {
int MyTracksProcessId = -1;
ActivityManager activityManager = (ActivityManager) context
.getSystemService(Activity.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();
for (RunningAppProcessInfo runningAppProcessInfo : runningAppProcesses) {
if (runningAppProcessInfo.processName.equalsIgnoreCase(MYTRACKS_PROCESS_NAME)) {
MyTracksProcessId = runningAppProcessInfo.pid;
break;
}
}
if (MyTracksProcessId == -1) {
Assert.fail();
}
int pids[] = { MyTracksProcessId };
android.os.Debug.MemoryInfo[] memoryInfoArray = activityManager.getProcessMemoryInfo(pids);
int memoryUsage = memoryInfoArray[0].getTotalPss();
return String.format(Locale.US, " MyTracks TotalPss Memory: %d (kB) ", memoryUsage);
}
/**
* Gets the battery info of device, and then writes it to a file.
*
* @param context the context of application
*/
public static String getBatteryUsageInfo(Context context) {
Intent batteryIntent = context.getApplicationContext().registerReceiver(null,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
int rawlevel = batteryIntent.getIntExtra("level", -1);
double scale = batteryIntent.getIntExtra("scale", -1);
return String.format("Device has %s of %s battery left", rawlevel, scale);
}
/**
* Writes a string to battery info file. This method would add a time string
* before the given value.
*
* @param string string to write
* @param isAppend true means append to file
*/
public static void writeToFile(String string, boolean isAppend) {
String path = Environment.getExternalStorageDirectory() + File.separator
+ MYTRACKS_TEST_INFO_FILE;
try {
FileOutputStream fileOutputStream = new FileOutputStream(new File(path), isAppend);
OutputStreamWriter osw = new OutputStreamWriter(fileOutputStream);
try {
// Write the string to the file
osw.write(string);
} finally {
osw.flush();
osw.close();
}
} catch (Exception e) {
Log.e(TAG, "Meet error when write test info to file.", e);
}
return;
}
/**
* Monitors the battery and memory usage during test, and writes the usage
* info to a local file.
*
* @param context application context
* @param interval the milliseconds to get usage info
* @param testTime the total test milliseconds
*/
public static void moniterTest(Context context, int interval, int testTime) {
long startTime = System.currentTimeMillis();
while ((System.currentTimeMillis() - startTime) < testTime) {
String memoryUsageString = getMyTracksPssMemoryInfo(context);
String batteryUsageString = getBatteryUsageInfo(context);
String oneInfo = String.format("{%s: memory use %s, battery left %s. \r\n",
String.format("{%1$tm/%1$td/%1$tY %1$tH:%1$tM:%1$tS", new Date()), memoryUsageString,
batteryUsageString);
writeToFile(oneInfo, true);
Log.d(TAG, oneInfo);
EndToEndTestUtils.sleep(interval);
}
}
/**
* Unlocks and wakes up the device.
*/
public static void unlockAndWakeupDevice() {
// The menu item of setting should be found if the screen is not locked.
try {
EndToEndTestUtils.SOLO.getCurrentActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
Window wind = EndToEndTestUtils.SOLO.getCurrentActivity().getWindow();
wind.addFlags(LayoutParams.FLAG_DISMISS_KEYGUARD);
wind.addFlags(LayoutParams.FLAG_SHOW_WHEN_LOCKED);
wind.addFlags(LayoutParams.FLAG_TURN_SCREEN_ON);
}
});
} catch (Exception e) {
Log.e(TAG, "Meet error when unlock device screen, may the device is not locked.", e);
}
}
}
@@ -0,0 +1,177 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest.others;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
import com.google.android.apps.mytracks.endtoendtest.RunConfiguration;
import com.google.android.maps.mytracks.R;
import android.app.AlertDialog;
import android.app.Instrumentation;
import android.content.Context;
import android.content.DialogInterface;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
/**
* Tests the battery and memory usage of long tracks. As this test may be run a
* long time test and without connect to desktop computer during test. The test
* result will be recorded to a file. And at the beginning of test, it need
* user's confirm by click a button.
*
* @author Youtao Liu
*/
public class ResourceUsageTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private static final String TAG = ResourceUsageTest.class.getSimpleName();
public ResourceUsageTest() {
super(TrackListActivity.class);
}
private Instrumentation instrumentation;
private TrackListActivity trackListActivity;
private boolean runTest = false;
private static boolean isUserConfirmed = false;
private Context context;
/**
* Default duration for each test is half one hour.
*/
private int TEST_DURATION_IN_MILLISECONDS = 30 * 60 * 1000;
private int INTERVALE_TO_CHECK = 5 * 60 * 1000;
@Override
protected void setUp() throws Exception {
super.setUp();
runTest = RunConfiguration.getInstance().getRunResourceTest();
if (!runTest) {
return;
}
instrumentation = getInstrumentation();
trackListActivity = getActivity();
context = trackListActivity.getApplicationContext();
instrumentation.waitForIdleSync();
EndToEndTestUtils.setupForDebug(instrumentation, trackListActivity);
BigTestUtils.unlockAndWakeupDevice();
if (!isUserConfirmed) {
confirmTest();
}
BigTestUtils.writeToFile("Test case start:" + getName() + "\r\n", true);
}
/**
* Prompts a dialog to make user confirm whether start the test.
*/
private void confirmTest() {
try {
trackListActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
new AlertDialog.Builder(EndToEndTestUtils.SOLO.getCurrentActivity())
.setTitle("Confirm long time test.")
.setMessage(
String
.format(
"Please disconnect the power cord of your device and click 'Start' button. Each case need run %d minutes, and the battery/memory usage will be recorded in every %d minutes.",
TEST_DURATION_IN_MILLISECONDS / 1000 / 60, INTERVALE_TO_CHECK / 60 / 1000))
.setPositiveButton("Start Test", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
isUserConfirmed = true;
runTest = true;
BigTestUtils.writeToFile("Test start:\r\n", false);
}
}).setNegativeButton("Cancel Test", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
isUserConfirmed = true;
runTest = false;
fail();
}
}).show();
}
});
} catch (Throwable e) {
Log.e(TAG, "Meet error when create confirm dialog.", e);
}
// Waiting user confirm the testing
while (!isUserConfirmed) {
EndToEndTestUtils.sleep(EndToEndTestUtils.TINY_WAIT_TIME);
}
}
/**
* Tests the resource usage when display track list activity during recording.
*/
public void testBatteryUsage_showTrackList() {
recordingLongTrack(true, R.string.track_detail_map_tab);
}
/**
* Tests the resource usage when display map view during recording.
*/
public void testBatteryUsage_showMapView() {
recordingLongTrack(false, R.string.track_detail_map_tab);
}
/**
* Tests the resource usage when display chart view during recording.
*/
public void testBatteryUsage_showChartView() {
recordingLongTrack(false, R.string.track_detail_chart_tab);
}
/**
* Tests the resource usage when display stats view during recording.
*/
public void testBatteryUsage_showStatsView() {
recordingLongTrack(false, R.string.track_detail_stats_tab);
}
/**
* Records a long time track and keeps in the specified tab or in tracks list
* during recording.
*
* @param isShowTracksList true means show tracks list
* @param tabNameId the name string id of tab, it's useless when the first
* parameter is true.
*/
public void recordingLongTrack(boolean isShowTracksList, int tabNameId) {
if (!runTest) {
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
return;
}
EndToEndTestUtils.startRecording();
if (isShowTracksList) {
EndToEndTestUtils.SOLO.goBack();
} else {
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(tabNameId));
}
BigTestUtils.moniterTest(context, INTERVALE_TO_CHECK, TEST_DURATION_IN_MILLISECONDS);
BigTestUtils.unlockAndWakeupDevice();
EndToEndTestUtils.stopRecording(true);
}
@Override
protected void tearDown() throws Exception {
if (!runTest) {
return;
}
EndToEndTestUtils.SOLO.finishOpenedActivities();
BigTestUtils.writeToFile("Test case done:" + getName() + "\r\n\r\n", true);
super.tearDown();
}
}
@@ -0,0 +1,247 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest.others;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
import com.google.android.apps.mytracks.endtoendtest.RunConfiguration;
import com.google.android.maps.mytracks.R;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
/**
* Tests connecting to sensors.
*
* @author Youtao Liu
*/
public class SensorTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private static final String TAG = SensorTest.class.getSimpleName();
private static final String ZEPHYR_NAME = "HXM";
private static final String POLAR_NAME = "Polar";
public SensorTest() {
super(TrackListActivity.class);
}
private Instrumentation instrumentation;
private TrackListActivity trackListActivity;
private boolean runTest = false;
@Override
protected void setUp() throws Exception {
runTest = RunConfiguration.getInstance().getRunSensorTest();
super.setUp();
if (!runTest) {
return;
}
instrumentation = getInstrumentation();
trackListActivity = getActivity();
EndToEndTestUtils.setupForAllTest(instrumentation, trackListActivity);
}
/**
* Tests connecting to a Zephyr Bluetooth sensor while not recording. Before this test, a Zephyr
* sensor must be paired with the device.
*/
public void testConnectZephyrBluetoothSensor_notRecording() {
if (!runTest) {
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
return;
}
bluetoothSensorTest(R.string.settings_sensor_type_zephyr, ZEPHYR_NAME, false);
}
/**
* Tests connecting to a Zephyr Bluetooth sensor while under recording. Before this test, a Zephyr
* sensor must be paired with the device.
*/
public void testConnectZephyrBluetoothSensor_underRecording() {
if (!runTest) {
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
return;
}
bluetoothSensorTest(R.string.settings_sensor_type_zephyr, ZEPHYR_NAME, true);
}
/**
* Tests connecting to a Polar Bluetooth sensor while not recording. Before this test, a Polar
* sensor must be paired with the device.
*/
public void testConnectPolarBluetoothSensor_notRecording() {
if (!runTest) {
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
return;
}
bluetoothSensorTest(R.string.settings_sensor_type_polar, POLAR_NAME, false);
}
/**
* Tests connecting to a Polar Bluetooth sensor while under recording. Before this test, a Polar
* sensor must be paired with the device.
*/
public void testConnectPolarBluetoothSensor_underRecording() {
if (!runTest) {
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
return;
}
bluetoothSensorTest(R.string.settings_sensor_type_polar, POLAR_NAME, true);
}
/**
* Set the paired sensor.
*
* @param sensorTypeStringId the string id of paired sensors type
* @param nameString part of the sensor name string which can distinguish
* different Bluetooth sensors
* @param isUnderRecording true means test under recording
*/
private void bluetoothSensorTest(int sensorTypeStringId, String nameString,
boolean isUnderRecording) {
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.settings_sensor));
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.settings_sensor_type));
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(sensorTypeStringId));
checkPairedSensorsNumber(nameString);
// Set the paired sensor.
EndToEndTestUtils.SOLO.clickOnText(nameString);
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.SOLO.goBack();
if (isUnderRecording) {
assertTrue(checkSensorsStatus_underRecording());
} else {
assertTrue(checkSensorsStatus_notRecording());
}
}
/**
* Checks the number of paired sensors.
*/
private void checkPairedSensorsNumber(String nameString) {
EndToEndTestUtils.SOLO.clickOnText(trackListActivity
.getString(R.string.settings_sensor_bluetooth_sensor));
instrumentation.waitForIdleSync();
ArrayList<ListView> allListViews = EndToEndTestUtils.SOLO.getCurrentViews(ListView.class);
int number = allListViews.get(0).getCount();
if (number > 0
&& EndToEndTestUtils.SOLO.waitForText(nameString, 1, EndToEndTestUtils.SHORT_WAIT_TIME)) {
return;
}
Log.d(TAG, "No sensor is paried");
fail("No bluetooth sensor is paired. Please pair at Settings->Bluetooth before running the test.");
}
/**
* Tests connecting to a cadence ANT+ sensor.
*/
public void testConnectANTSensor_Cadence() {
if (!runTest) {
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
return;
}
useANTSeonsor();
assertTrue(checkSensorsStatus_notRecording());
checkANTSensorsStatus(R.id.sensor_state_cadence);
}
/**
* Tests connecting to cadence and heart rate ANT+ sensors at the same time.
*/
public void testConnectTwoANTSensors() {
if (!runTest) {
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
return;
}
useANTSeonsor();
assertTrue(checkSensorsStatus_notRecording());
checkANTSensorsStatus(R.id.sensor_state_cadence);
checkANTSensorsStatus(R.id.sensor_state_heart_rate);
}
/**
* Sets the setting to use ANT+ sensor
*/
private void useANTSeonsor() {
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.settings_sensor));
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.settings_sensor_type));
EndToEndTestUtils.SOLO.clickOnText(trackListActivity
.getString(R.string.settings_sensor_type_ant));
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.SOLO.goBack();
}
/**
* Checks whether the ANT+ sensor is connected with MyTracks.
*
* @param viewID the id to check which is not equal with None
*/
private void checkANTSensorsStatus(int viewID) {
TextView sensorValueText = ((TextView) EndToEndTestUtils.SOLO.getCurrentActivity()
.findViewById(viewID));
assertNotNull(sensorValueText);
String realValue = sensorValueText.getText().toString();
String noneValue = trackListActivity.getString(R.string.value_none);
assertNotSame(realValue, noneValue);
}
/**
* Checks whether the sensor is connected with MyTracks during recording.
*
* @return true means the sensor is connected with MyTracks
*/
private boolean checkSensorsStatus_underRecording() {
EndToEndTestUtils.instrumentation.waitForIdleSync();
EndToEndTestUtils.startRecording();
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_sensor_state), true);
boolean result = EndToEndTestUtils.SOLO.waitForText(
trackListActivity.getString(R.string.sensor_state_connected), 1,
EndToEndTestUtils.LONG_WAIT_TIME);
EndToEndTestUtils.stopRecording(true);
return result;
}
/**
* Checks whether the sensor is connected with MyTracks while not under recording.
*
* @return true means the sensor is connected with MyTracks
*/
private boolean checkSensorsStatus_notRecording() {
EndToEndTestUtils.instrumentation.waitForIdleSync();
EndToEndTestUtils.createTrackIfEmpty(0, false);
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_sensor_state), true);
return EndToEndTestUtils.SOLO.waitForText(
trackListActivity.getString(R.string.sensor_state_connected), 1,
EndToEndTestUtils.LONG_WAIT_TIME);
}
@Override
protected void tearDown() throws Exception {
if (!runTest) {
return;
}
EndToEndTestUtils.SOLO.finishOpenedActivities();
super.tearDown();
}
}
@@ -0,0 +1,197 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest.others;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
import com.google.android.apps.mytracks.endtoendtest.RunConfiguration;
import com.google.android.maps.mytracks.R;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
import android.widget.ListView;
/**
* Stress test of MyTracks.
*
* @author Youtao Liu
*/
public class StressTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private static final String TAG = StressTest.class.getSimpleName();
private static final int TEST_DURATION_IN_MILLISECONDS = 30 * 60 * 1000;
private static final int MAX_TRACK_NUMBER = 30;
private boolean runTest = false;
private long startTime = 0;
private int numberOfTracks;
public StressTest() {
super(TrackListActivity.class);
}
private Instrumentation instrumentation;
private TrackListActivity trackListActivity;
@Override
protected void setUp() throws Exception {
runTest = RunConfiguration.getInstance().getRunStressTest();
super.setUp();
if (!runTest) {
return;
}
instrumentation = getInstrumentation();
trackListActivity = getActivity();
EndToEndTestUtils.setupForAllTest(instrumentation, trackListActivity);
BigTestUtils.unlockAndWakeupDevice();
startTime = System.currentTimeMillis();
}
/**
* Records tracks and deletes them when there are more than
* {@link #MAX_TRACK_NUMBER} tracks. Keeps sending different GPS locations in
* each track, making it closer to the real stress.
*/
public void testRecordAndDeleteTracks() {
if (!runTest) {
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
return;
}
for (int i = 0; (System.currentTimeMillis() - startTime) < TEST_DURATION_IN_MILLISECONDS; i++) {
EndToEndTestUtils.startRecording();
// Points in a tracks keep increasing.
EndToEndTestUtils.sendGps(i * 10, 0, 10);
EndToEndTestUtils.stopRecording(true);
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.instrumentation.waitForIdleSync();
numberOfTracks = EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount();
if (numberOfTracks > MAX_TRACK_NUMBER) {
EndToEndTestUtils.deleteAllTracks();
}
logStatus(i);
}
}
/**
* Rotates screen when display map view. Keeps sending different GPS locations
* in each track, making it closer to the real stress.
*/
public void testRotateMapViewInTrackDetailActivity() {
if (!runTest) {
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
return;
}
EndToEndTestUtils.startRecording();
for (int i = 0; (System.currentTimeMillis() - startTime) < TEST_DURATION_IN_MILLISECONDS; i++) {
EndToEndTestUtils.sendGps(10, i * 10);
EndToEndTestUtils.rotateCurrentActivity();
Log.d(TAG, String.format("Totate %d times in %d minutes!", i,
(System.currentTimeMillis() - startTime) / 1000 / 60));
}
}
/**
* Switches view between MAP, CHART and STAT.
*/
public void testSwitchTabs() {
if (!runTest) {
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
return;
}
EndToEndTestUtils.startRecording();
int i = 0;
while ((System.currentTimeMillis() - startTime) < TEST_DURATION_IN_MILLISECONDS) {
EndToEndTestUtils.SOLO
.clickOnText(trackListActivity.getString(R.string.track_detail_map_tab));
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.clickOnText(trackListActivity
.getString(R.string.track_detail_chart_tab));
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.clickOnText(trackListActivity
.getString(R.string.track_detail_stats_tab));
instrumentation.waitForIdleSync();
logStatus(++i);
}
EndToEndTestUtils.stopRecording(true);
}
/**
* Records a long track.
*/
public void testRecordLongTrack() {
if (!runTest) {
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
return;
}
EndToEndTestUtils.startRecording();
int gpsNumber = 5000;
for (int i = 0; i < gpsNumber / 10; i++) {
EndToEndTestUtils.sendGps(10, i * 10);
}
EndToEndTestUtils.stopRecording(true);
}
/**
* Switches view between MAP, CHART and STAT. And create way points, pause and
* resume the track during recording.
*/
public void testSwitchTabs_wayPoints() {
if (!runTest) {
Log.d(TAG, BigTestUtils.DISABLE_MESSAGE);
return;
}
EndToEndTestUtils.startRecording();
int i = 0;
while ((System.currentTimeMillis() - startTime) < TEST_DURATION_IN_MILLISECONDS) {
// Create one way points.
EndToEndTestUtils.sendGps(10, 10 * i);
EndToEndTestUtils.createWaypoint(i);
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.generic_recording));
EndToEndTestUtils.pauseRecording();
EndToEndTestUtils.SOLO
.clickOnText(trackListActivity.getString(R.string.track_detail_map_tab));
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.clickOnText(trackListActivity
.getString(R.string.track_detail_chart_tab));
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.clickOnText(trackListActivity
.getString(R.string.track_detail_stats_tab));
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.generic_paused));
EndToEndTestUtils.resumeRecording();
logStatus(++i);
}
EndToEndTestUtils.stopRecording(true);
}
/**
* Logs status.
*
* @param times the number of times this test has been run
*/
private void logStatus(int times) {
int minutes =
(int) (TEST_DURATION_IN_MILLISECONDS - (System.currentTimeMillis() - startTime)) / 60
/ 1000;
Log.d(TAG, String.format(
"This test has run %d times and will be finished in %d minutes!", times, minutes));
Log.d(TAG, String.format("There are %d tracks!", numberOfTracks));
}
}
@@ -0,0 +1,159 @@
/*
* Copyright 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest.sync;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
import com.google.android.apps.mytracks.endtoendtest.GoogleUtils;
import com.google.android.apps.mytracks.endtoendtest.RunConfiguration;
import com.google.android.maps.mytracks.R;
import com.google.api.services.drive.Drive;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.ListView;
/**
* Tests the situation when user use multiple account in MyTracks.
*
* @author Youtao Liu
*/
public class MultiAccountsSyncTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private Drive drive;
private Instrumentation instrumentation;
private TrackListActivity trackListActivity;
public MultiAccountsSyncTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
trackListActivity = getActivity();
SyncTestUtils.setUpForSyncTest(instrumentation, trackListActivity);
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_1);
drive = SyncTestUtils
.getGoogleDrive(EndToEndTestUtils.trackListActivity.getApplicationContext());
}
/**
* Tests sync tracks with Google Drive of two accounts with following
* sequence:
* <ul>
* <li>1. Enable sync with account1.</li>
* <li>2. Create a track.</li>
* <li>3. Enable sync with account2.</li>
* <li>4. Create a track.</li>
* <li>5. Sync and check</li>
* <li>6. Enable sync with account1.</li>
* <li>7. Sync and check</li>
* <li>8. Enable sync with account2.</li>
* <li>9. Check</li>
* </ul>
*/
public void testSyncTracksWithMultiAccounts() throws Exception {
if (!RunConfiguration.getInstance().getRunSyncTest()) {
return;
}
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_1);
// Create tracks with first track.
EndToEndTestUtils.createSimpleTrack(0, true);
// Create tracks with second track.
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_2);
EndToEndTestUtils.createSimpleTrack(0, true);
// Sync with Google Drive and then check it of the second account.
EndToEndTestUtils.findMenuItem(
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
drive = SyncTestUtils.getGoogleDrive(trackListActivity.getApplicationContext());
SyncTestUtils.checkFilesNumber(drive);
// Check Google Drive of the first account.
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_1);
EndToEndTestUtils.findMenuItem(
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
drive = SyncTestUtils.getGoogleDrive(trackListActivity.getApplicationContext());
SyncTestUtils.checkFilesNumber(drive);
// Back to account1 change check that files are still existed.
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_2);
drive = SyncTestUtils.getGoogleDrive(trackListActivity.getApplicationContext());
SyncTestUtils.checkFilesNumber(drive);
}
/**
* Tests the behavior of MyTracks about delete operation and switch accounts
* with following sequence.:
* <ul>
* <li>1. Create 3 tracks.</li>
* <li>2. Delete 1 track.</li>
* <li>3. Sync with account2(account2 should have 2 files).</li>
* <li>4. Delete 1 track (account2 should have 1 file).</li>
* <li>5. Sync with account 1 (account 1 should have 1 file, account2 should
* also have 1 file).</li>
* </ul>
*/
public void testDeleteTracksWithMultiAccounts() throws Exception {
if (!RunConfiguration.getInstance().getRunSyncTest()) {
return;
}
EndToEndTestUtils.createSimpleTrack(0, true);
EndToEndTestUtils.createSimpleTrack(0, true);
EndToEndTestUtils.createSimpleTrack(0, true);
// Delete one track.
EndToEndTestUtils.SOLO.clickOnView(EndToEndTestUtils.SOLO.getCurrentViews(ListView.class)
.get(0).getChildAt(0));
EndToEndTestUtils.instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.clickOnMenuItem(EndToEndTestUtils.trackListActivity
.getString(R.string.menu_delete));
EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.trackListActivity
.getString(R.string.generic_yes));
// Switch account and delete another track.
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_2);
EndToEndTestUtils.SOLO.clickOnView(EndToEndTestUtils.SOLO.getCurrentViews(ListView.class)
.get(0).getChildAt(0));
EndToEndTestUtils.SOLO.clickOnMenuItem(EndToEndTestUtils.trackListActivity
.getString(R.string.menu_delete));
EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.trackListActivity
.getString(R.string.generic_yes));
// Check Google Drive of the first account.
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_1);
EndToEndTestUtils.findMenuItem(
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
drive = SyncTestUtils.getGoogleDrive(trackListActivity.getApplicationContext());
SyncTestUtils.checkFilesNumber(drive);
// Check Google Drive of the second account.
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_2);
EndToEndTestUtils.findMenuItem(
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
drive = SyncTestUtils.getGoogleDrive(trackListActivity.getApplicationContext());
SyncTestUtils.checkFilesNumber(drive);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
EndToEndTestUtils.SOLO.finishOpenedActivities();
}
}
@@ -0,0 +1,165 @@
/*
* Copyright 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest.sync;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
import com.google.android.apps.mytracks.endtoendtest.GoogleUtils;
import com.google.android.apps.mytracks.endtoendtest.RunConfiguration;
import com.google.android.maps.mytracks.R;
import com.google.api.services.drive.Drive;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import android.view.KeyEvent;
import java.io.IOException;
/**
* Tests making changes on Google Drive when syncing My Tracks with Google
* Drive.
*
* @author Youtao Liu
*/
public class SyncDriveWithMyTracksTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private Drive drive;
private Instrumentation instrumentation;
private TrackListActivity trackListActivity;
public SyncDriveWithMyTracksTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
trackListActivity = getActivity();
SyncTestUtils.setUpForSyncTest(instrumentation, trackListActivity);
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_1);
drive = SyncTestUtils
.getGoogleDrive(EndToEndTestUtils.trackListActivity.getApplicationContext());
}
/**
* Deletes all tracks in MyTracks and checks in Google Drive.
*
* @throws IOException
*/
public void testDeleteAllTracksInMyTracks() throws IOException {
if (!RunConfiguration.getInstance().getRunSyncTest()) {
return;
}
EndToEndTestUtils.findMenuItem(
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
SyncTestUtils.checkFilesNumber(drive);
}
/**
* Deletes one track in MyTracks and checks it in Google Drive.
*
* @throws IOException
*/
public void testDeleteOneTracksInMyTracks() throws IOException {
if (!RunConfiguration.getInstance().getRunSyncTest()) {
return;
}
EndToEndTestUtils.createTrackIfEmpty(2, false);
EndToEndTestUtils.SOLO.clickOnMenuItem(EndToEndTestUtils.trackListActivity
.getString(R.string.menu_delete));
EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.trackListActivity
.getString(R.string.generic_yes));
EndToEndTestUtils.findMenuItem(
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
SyncTestUtils.checkFile(EndToEndTestUtils.trackName, false, drive);
}
/**
* Creates one empty track and one non-empty track in MyTracks and then check
* them in Google Drive.
*
* @throws IOException
*/
public void testCreateTracksInMyTracks() throws IOException {
if (!RunConfiguration.getInstance().getRunSyncTest()) {
return;
}
EndToEndTestUtils.createSimpleTrack(0, true);
EndToEndTestUtils.createSimpleTrack(3, true);
EndToEndTestUtils.findMenuItem(
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
SyncTestUtils.checkFilesNumber(drive);
}
/**
* Edits a tracks in MyTracks and checks it on Google Drive after sync.
*
* @throws IOException
*/
public void testEditTrackInMyTracks() throws IOException {
if (!RunConfiguration.getInstance().getRunSyncTest()) {
return;
}
EndToEndTestUtils.createTrackIfEmpty(3, true);
// Sync this track.
EndToEndTestUtils.findMenuItem(
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
SyncTestUtils.checkFile(EndToEndTestUtils.trackName, true, drive);
String oldTrack = SyncTestUtils.getContentOfFile(
SyncTestUtils.getFile(EndToEndTestUtils.trackName, drive), drive);
String oldTrackName = EndToEndTestUtils.trackName;
// Edit this track.
EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.trackName);
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_edit), true);
String newTrackName = EndToEndTestUtils.TRACK_NAME_PREFIX + "_new" + System.currentTimeMillis();
String newType = EndToEndTestUtils.activityType + newTrackName;
String newDesc = "desc" + newTrackName;
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.waitForText(trackListActivity.getString(R.string.generic_save));
sendKeys(KeyEvent.KEYCODE_DEL);
EndToEndTestUtils.enterTextAvoidSoftKeyBoard(0, newTrackName);
EndToEndTestUtils.enterTextAvoidSoftKeyBoard(1, newType);
EndToEndTestUtils.enterTextAvoidSoftKeyBoard(2, newDesc);
EndToEndTestUtils.SOLO.clickOnButton(trackListActivity.getString(R.string.generic_save));
instrumentation.waitForIdleSync();
EndToEndTestUtils.SOLO.goBack();
instrumentation.waitForIdleSync();
// Sync again.
EndToEndTestUtils.findMenuItem(
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
// Check.
SyncTestUtils.checkFile(oldTrackName, false, drive);
SyncTestUtils.checkFile(newTrackName, true, drive);
String newTrack = SyncTestUtils.getContentOfFile(SyncTestUtils.getFile(newTrackName, drive),
drive);
assertNotSame(oldTrack, newTrack);
assertTrue(newTrack.indexOf(newTrackName) > 0);
assertTrue(newTrack.indexOf(newType) > 0);
assertTrue(newTrack.indexOf(newDesc) > 0);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
EndToEndTestUtils.SOLO.finishOpenedActivities();
}
}
@@ -0,0 +1,127 @@
/*
* Copyright 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest.sync;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
import com.google.android.apps.mytracks.endtoendtest.GoogleUtils;
import com.google.android.apps.mytracks.endtoendtest.RunConfiguration;
import com.google.android.apps.mytracks.io.sync.SyncUtils;
import com.google.android.maps.mytracks.R;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.model.File;
import android.app.Instrumentation;
import android.test.ActivityInstrumentationTestCase2;
import java.io.IOException;
/**
* Tests making changes on My Tracks when syncing My Tracks with Google Drive.
*
* @author Youtao Liu
*/
public class SyncMyTracksWithDriveTest extends ActivityInstrumentationTestCase2<TrackListActivity> {
private Drive drive;
private Instrumentation instrumentation;
private TrackListActivity trackListActivity;
public SyncMyTracksWithDriveTest() {
super(TrackListActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
instrumentation = getInstrumentation();
trackListActivity = getActivity();
SyncTestUtils.setUpForSyncTest(instrumentation, trackListActivity);
SyncTestUtils.enableSync(GoogleUtils.ACCOUNT_1);
drive = SyncTestUtils
.getGoogleDrive(EndToEndTestUtils.trackListActivity.getApplicationContext());
}
/**
* Deletes all tracks on Google Drive and checks in MyTracks.
*
* @throws IOException
*/
public void testDeleteAllTracksOnDrive() throws IOException {
if (!RunConfiguration.getInstance().getRunSyncTest()) {
return;
}
EndToEndTestUtils.createTrackIfEmpty(0, true);
EndToEndTestUtils.findMenuItem(
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
SyncTestUtils.checkFilesNumber(drive);
SyncTestUtils.removeKMLFiles(drive);
EndToEndTestUtils.findMenuItem(
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
SyncTestUtils.checkTracksNumber(0);
}
/**
* Deletes one file on Google Drive and checks it in MyTracks.
*
* @throws IOException
*/
public void testDeleteOneFileOnDrive() throws IOException {
if (!RunConfiguration.getInstance().getRunSyncTest()) {
return;
}
instrumentation.waitForIdleSync();
EndToEndTestUtils.createSimpleTrack(0, true);
EndToEndTestUtils.createSimpleTrack(0, true);
EndToEndTestUtils.findMenuItem(
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
SyncTestUtils.checkFilesNumber(drive);
// Remove one track from Google Drive
File file = SyncTestUtils.getFile(EndToEndTestUtils.trackName, drive);
SyncTestUtils.removeFile(file, drive);
EndToEndTestUtils.findMenuItem(
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
SyncTestUtils.checkFilesNumber(drive);
SyncTestUtils.checkTracksNumber(1);
}
/**
* Tests deleting and creating MyTracks folder on Google Dive by MyTracks.
*
* @throws IOException
*/
public void testCreateMyTracksOnDrive() throws IOException {
if (!RunConfiguration.getInstance().getRunSyncTest()) {
return;
}
instrumentation.waitForIdleSync();
EndToEndTestUtils.createSimpleTrack(0, true);
EndToEndTestUtils.createSimpleTrack(0, true);
EndToEndTestUtils.findMenuItem(
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
instrumentation.waitForIdleSync();
SyncTestUtils.checkFilesNumber(drive);
File folder = SyncUtils.getMyTracksFolder(trackListActivity.getApplicationContext(), drive);
assertNotNull(folder);
SyncTestUtils.removeFile(folder, drive);
EndToEndTestUtils.findMenuItem(
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
SyncTestUtils.checkFilesNumber(drive);
}
}
@@ -0,0 +1,311 @@
/*
* Copyright 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks.endtoendtest.sync;
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.apps.mytracks.endtoendtest.EndToEndTestUtils;
import com.google.android.apps.mytracks.endtoendtest.GoogleUtils;
import com.google.android.apps.mytracks.endtoendtest.RunConfiguration;
import com.google.android.apps.mytracks.io.sendtogoogle.SendToGoogleUtils;
import com.google.android.apps.mytracks.io.sync.SyncUtils;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.gms.auth.GoogleAuthException;
import com.google.android.maps.mytracks.R;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpResponse;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.model.File;
import android.app.Instrumentation;
import android.content.Context;
import android.util.Log;
import android.widget.ListView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import junit.framework.Assert;
/**
* Utilites for Google Drive sync endtoend test.
*
* @author Youtao Liu
*/
public class SyncTestUtils {
private static final String TAG = SyncTestUtils.class.getSimpleName();
public static boolean isCheckedRunSyncTest = false;
public static final String KML_FILE_POSTFIX = ".kml";
public static final long MAX_TIME_TO_WAIT_SYNC = 100000;
/**
* Sets up sync tests.
*
* @param instrumentation the instrumentation is used for test
* @param trackListActivity the startup activity
* @return a Google Drive object
*/
public static Drive setUpForSyncTest(Instrumentation instrumentation,
TrackListActivity trackListActivity) throws IOException, GoogleAuthException {
if (!isCheckedRunSyncTest || RunConfiguration.getInstance().getRunSyncTest()) {
EndToEndTestUtils.setupForAllTest(instrumentation, trackListActivity);
}
if (!isCheckedRunSyncTest) {
isCheckedRunSyncTest = true;
}
if (RunConfiguration.getInstance().getRunSyncTest()) {
enableSync(GoogleUtils.ACCOUNT_1);
Drive drive1 = getGoogleDrive(EndToEndTestUtils.trackListActivity.getApplicationContext());
removeKMLFiles(drive1);
EndToEndTestUtils.deleteAllTracks();
enableSync(GoogleUtils.ACCOUNT_2);
Drive drive2 = getGoogleDrive(EndToEndTestUtils.trackListActivity.getApplicationContext());
removeKMLFiles(drive2);
EndToEndTestUtils.deleteAllTracks();
return drive2;
}
return null;
}
/**
* Gets drive object of Google Drive.
*
* @param context the context of application
* @return a Google Drive object
*/
public static Drive getGoogleDrive(Context context) throws IOException, GoogleAuthException {
String googleAccount = PreferencesUtils.getString(context, R.string.google_account_key,
PreferencesUtils.GOOGLE_ACCOUNT_DEFAULT);
GoogleAccountCredential credential = SendToGoogleUtils.getGoogleAccountCredential(context,
googleAccount, SendToGoogleUtils.DRIVE_SCOPE);
return SyncUtils.getDriveService(credential);
}
/**
* Gets KML files from Google Drive of current account.
*
* @param context the context of application
* @param drive a Google Drive object
* @return KML file on Google drive
* @throws IOException
*/
public static List<File> getDriveFiles(Context context, Drive drive) throws IOException {
File folder = SyncUtils.getMyTracksFolder(context, drive);
if (folder == null) {
return new ArrayList<File>();
}
String folderId = folder.getId();
return drive.files().list()
.setQ(String.format(Locale.US, SyncUtils.MY_TRACKS_FOLDER_FILES_QUERY, folderId)).execute()
.getItems();
}
/**
* Finds whether a file is existed by the name of track.
*
* @param trackName name of track
* @param drive a Google Drive object
* @return the file be found
* @throws IOException
*/
public static File getFile(String trackName, Drive drive) throws IOException {
List<File> files = getDriveFiles(EndToEndTestUtils.trackListActivity.getApplicationContext(),
drive);
for (int i = 0; i < files.size(); i++) {
File file = files.get(i);
String title = file.getTitle();
if (title.equals(trackName + KML_FILE_POSTFIX)) {
return file;
}
}
return null;
}
/**
* Removes all KML files on Google Drive.
*
* @param drive a Google Drive object
* @throws IOException
*/
public static void removeKMLFiles(Drive drive) throws IOException {
List<File> files = getDriveFiles(
EndToEndTestUtils.trackListActivity.getApplicationContext(), drive);
for (int i = 0; i < files.size(); i++) {
File file = files.get(i);
removeFile(file, drive);
}
}
/**
* Removes one file on Google Drive.
*
* @param file the file to remove
* @param drive a Google Drive object
* @throws IOException
*/
public static void removeFile(File file, Drive drive) throws IOException {
drive.files().trash(file.getId()).execute();
}
/**
* Enables sync feature in MyTracks settings.
*
* @param accountName the account which is used to sync with
*/
public static void enableSync(String accountName) {
// EndToEndTestUtils.instrumentation.waitForIdleSync();
// EndToEndTestUtils.findMenuItem(
// EndToEndTestUtils.activityMytracks.getString(R.string.menu_settings), true);
// EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.activityMytracks
// .getString(R.string.settings_google));
// EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.activityMytracks
// .getString(R.string.settings_google_account_title));
// EndToEndTestUtils.instrumentation.waitForIdleSync();
//
// // Whether test account is bound.
// if (EndToEndTestUtils.SOLO.waitForText(accountName, 1, EndToEndTestUtils.SHORT_WAIT_TIME)) {
// EndToEndTestUtils.SOLO.clickOnText(accountName);
// EndToEndTestUtils.instrumentation.waitForIdleSync();
//
// if (EndToEndTestUtils.findTextView(EndToEndTestUtils.activityMytracks
// .getString(R.string.settings_google_account_confirm_title)) != null) {
// EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.activityMytracks
// .getString(R.string.generic_yes));
// }
// } else {
// Assert.fail();
// return;
// }
//
// EndToEndTestUtils.SOLO.waitForDialogToClose(EndToEndTestUtils.SHORT_WAIT_TIME);
// EndToEndTestUtils.instrumentation.waitForIdleSync();
// CheckBox syncCheckBox = EndToEndTestUtils.SOLO.getCurrentViews(CheckBox.class).get(0);
// if (!syncCheckBox.isChecked()) {
// EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.activityMytracks
// .getString(R.string.menu_sync_drive));
//
// EndToEndTestUtils.SOLO.waitForText(
// EndToEndTestUtils.activityMytracks.getString(R.string.sync_drive_confirm_message).split(
// "%")[0], 1, EndToEndTestUtils.SHORT_WAIT_TIME);
// Assert.assertTrue(EndToEndTestUtils.SOLO.searchText(accountName, true));
// EndToEndTestUtils.SOLO.clickOnText(EndToEndTestUtils.activityMytracks
// .getString(R.string.generic_yes));
// }
//
// // Add this sleep to work around a exception after switch account.
// EndToEndTestUtils.sleep(15000);
// EndToEndTestUtils.SOLO.goBack();
// EndToEndTestUtils.SOLO.goBack();
// EndToEndTestUtils.instrumentation.waitForIdleSync();
}
/**
* Checks the files number on Google Drive
*
* @param drive a Google Drive object
* @throws IOException
*/
public static void checkFilesNumber(Drive drive) throws IOException {
EndToEndTestUtils.instrumentation.waitForIdleSync();
long startTime = System.currentTimeMillis();
int trackNumber = EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount();
List<File> files = getDriveFiles(EndToEndTestUtils.trackListActivity.getApplicationContext(),
drive);
while (System.currentTimeMillis() - startTime < MAX_TIME_TO_WAIT_SYNC) {
try {
if (files.size() == trackNumber) {
return;
}
trackNumber = EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount();
files = getDriveFiles(EndToEndTestUtils.trackListActivity.getApplicationContext(), drive);
EndToEndTestUtils.sleep(EndToEndTestUtils.SHORT_WAIT_TIME);
EndToEndTestUtils.findMenuItem(
EndToEndTestUtils.trackListActivity.getString(R.string.menu_sync_now), true);
} catch (GoogleJsonResponseException e) {
Log.e(TAG, e.getMessage(), e);
}
}
Assert.assertEquals(files.size(), trackNumber);
}
/**
* Checks the files number on Google Drive
*
* @param number number of files on Google Drive
*/
public static void checkTracksNumber(int number) {
long startTime = System.currentTimeMillis();
int trackNumber = EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount();
while (System.currentTimeMillis() - startTime < MAX_TIME_TO_WAIT_SYNC) {
if (trackNumber == number) {
return;
}
trackNumber = EndToEndTestUtils.SOLO.getCurrentViews(ListView.class).get(0).getCount();
Log.d(TAG, trackNumber + ":" + number);
}
Assert.assertEquals(trackNumber, number);
}
/**
* Checks one file on Google Drive
*
* @param trackName the name of track
* @param shouldExist true means this track should be existed
* @param drive a Google Drive object
* @return true means the actual result is same as expectation
* @throws IOException
*/
public static boolean checkFile(String trackName, boolean shouldExist, Drive drive)
throws IOException {
long startTime = System.currentTimeMillis();
while (System.currentTimeMillis() - startTime < MAX_TIME_TO_WAIT_SYNC) {
boolean exist = getFile(trackName, drive) != null;
if (exist == shouldExist) {
return true;
}
}
Assert.fail();
return false;
}
/**
* Gets the content of a file on Google Drive.
*
* @param file file to read
* @param drive a Google Drive object
* @return the string content of the file
* @throws IOException
*/
public static String getContentOfFile(File file, Drive drive) throws IOException {
HttpResponse resp = drive.getRequestFactory()
.buildGetRequest(new GenericUrl(file.getDownloadUrl())).execute();
BufferedReader br = new BufferedReader(new InputStreamReader(resp.getContent()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
String fileContent = sb.toString();
br.close();
return fileContent;
}
}