add screengrab support / refactoring

This commit is contained in:
David Luhmer 2016-03-19 20:07:43 +01:00
parent b95d4c10cd
commit 69311fd87b
11 changed files with 318 additions and 59 deletions

View file

@ -94,6 +94,13 @@ dependencies {
testCompile 'org.robolectric:robolectric:3.0-rc3'
testCompile 'junit:junit:4.1'
testCompile("org.mockito:mockito-core:1.10.19") {
exclude group: 'org.hamcrest'
}
testCompile 'com.google.dexmaker:dexmaker:1.2'
testCompile 'com.google.dexmaker:dexmaker-mockito:1.2'
androidTestCompile 'com.squareup.okhttp:mockwebserver:2.5.0'
androidTestCompile "com.android.support:support-annotations:${SUPPORT_VERSION}"
@ -112,5 +119,10 @@ dependencies {
compile 'com.nbsp:library:1.02'
//androidTestCompile 'tools:fastlane:screengrab:0.3.0'
androidTestCompile 'tools.fastlane:screengrab:0.3.1'
androidTestCompile("org.mockito:mockito-core:1.10.19") {
exclude group: 'org.hamcrest'
}
androidTestCompile 'com.google.dexmaker:dexmaker:1.2'
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2'
}

View file

@ -1,37 +0,0 @@
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import de.luhmer.owncloudnewsreader.NewsReaderListActivity;
import de.luhmer.owncloudnewsreader.R;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
/**
* Created by David on 06.03.2016.
*/
@RunWith(AndroidJUnit4.class)
public class ScreenshotTest {
/*
@ClassRule
public static final LocalTestRule localTestRule = new LocalTestRule();
@Rule
public ActivityTestRule<NewsReaderListActivity> mActivityRule = new ActivityTestRule<>(NewsReaderListActivity.class);
@Test
public void changeText_sameActivity() {
Screengrab
}
*/
}

View file

@ -0,0 +1,209 @@
package screengrab;
import android.app.Instrumentation;
import android.content.SharedPreferences;
import android.graphics.Point;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.support.v4.content.SharedPreferencesCompat;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.test.UiThreadTest;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Mockito;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import de.luhmer.owncloudnewsreader.NewsReaderDetailFragment;
import de.luhmer.owncloudnewsreader.NewsReaderListActivity;
import de.luhmer.owncloudnewsreader.NewsReaderListFragment;
import de.luhmer.owncloudnewsreader.R;
import de.luhmer.owncloudnewsreader.SettingsActivity;
import de.luhmer.owncloudnewsreader.adapter.NewsListRecyclerAdapter;
import de.luhmer.owncloudnewsreader.adapter.ViewHolder;
import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm;
import de.luhmer.owncloudnewsreader.model.PodcastItem;
import de.luhmer.owncloudnewsreader.model.UserInfo;
import tools.fastlane.screengrab.Screengrab;
import tools.fastlane.screengrab.locale.LocaleTestRule;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
/**
* Created by David on 06.03.2016.
*/
@RunWith(AndroidJUnit4.class)
public class ScreenshotTest {
@ClassRule
public static final LocaleTestRule localTestRule = new LocaleTestRule();
@Rule
public ActivityTestRule<NewsReaderListActivity> mActivityRule = new ActivityTestRule<>(NewsReaderListActivity.class);
private MenuItem menuItem;
private NewsReaderListActivity activity;
private NewsReaderListFragment nrlf;
private NewsReaderDetailFragment nrdf;
private int itemPos = 5;
@Before
public void setup() {
menuItem = Mockito.mock(MenuItem.class);
activity = mActivityRule.getActivity();
nrlf = mActivityRule.getActivity().getSlidingListFragment();
nrdf = mActivityRule.getActivity().getNewsReaderDetailFragment();
SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(mActivityRule.getActivity());
UserInfo userInfo = new UserInfo.Builder()
.setUserId("1")
.setDisplayName("David")
.setAvatar(null)
.build();
try {
mPrefs.edit().putString("USER_INFO", NewsReaderListFragment.toString(userInfo)).commit();
mPrefs.edit().putBoolean(SettingsActivity.CB_SKIP_DETAILVIEW_AND_OPEN_BROWSER_DIRECTLY_STRING, false).commit();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testTakeScreenshots() {
Screengrab.screenshot("startup");
Mockito.when(menuItem.getItemId()).thenReturn(android.R.id.home);
activity.runOnUiThread(new Runnable() {
public void run() {
//Set url to mock
nrlf.bindUserInfoToUI(true);
mActivityRule.getActivity().onOptionsItemSelected(menuItem); //Open Drawer
nrlf.getListView().expandGroup(2);
}
});
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Screengrab.screenshot("slider_open");
activity.runOnUiThread(new Runnable() {
public void run() {
activity.onOptionsItemSelected(menuItem); //Close Drawer
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
activity.onClick(null, itemPos); //Select item
}
});
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Screengrab.screenshot("detail_activity");
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
NewsListRecyclerAdapter na = (NewsListRecyclerAdapter) nrdf.getRecyclerView().getAdapter();
ViewHolder vh = (ViewHolder) nrdf.getRecyclerView().getChildViewHolder(nrdf.getRecyclerView().getLayoutManager().findViewByPosition(itemPos));
na.ChangeReadStateOfItem(vh, false);
}
});
}
@Test
public void testPodcast() {
activity.runOnUiThread(new Runnable() {
public void run() {
//Set url to mock
nrlf.bindUserInfoToUI(true);
mActivityRule.getActivity().onOptionsItemSelected(menuItem); //Open Drawer
nrlf.getListView().expandGroup(2);
nrlf.onChildClickListener.onChildClick(null, null, 2, 2, 0); //Click on Android Central Podcast
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Screengrab.screenshot("podcast_list");
activity.runOnUiThread(new Runnable() {
public void run() {
ViewHolder vh = (ViewHolder) nrdf.getRecyclerView().getChildViewHolder(nrdf.getRecyclerView().getLayoutManager().findViewByPosition(1));
PodcastItem podcastItem = DatabaseConnectionOrm.ParsePodcastItemFromRssItem(activity, vh.getRssItem());
activity.openMediaItem(podcastItem);
}
});
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Screengrab.screenshot("podcast_running");
activity.runOnUiThread(new Runnable() {
public void run() {
activity.pausePodcast();
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

View file

@ -42,6 +42,7 @@ import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.support.design.widget.Snackbar;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
@ -845,11 +846,13 @@ public class NewsReaderListActivity extends PodcastFragmentActivity implements
}
}
protected NewsReaderListFragment getSlidingListFragment() {
@VisibleForTesting
public NewsReaderListFragment getSlidingListFragment() {
return ((NewsReaderListFragment) getSupportFragmentManager().findFragmentById(R.id.left_drawer));
}
protected NewsReaderDetailFragment getNewsReaderDetailFragment() {
@VisibleForTesting
public NewsReaderDetailFragment getNewsReaderDetailFragment() {
return (NewsReaderDetailFragment) getSupportFragmentManager().findFragmentById(R.id.content_frame);
}

View file

@ -24,13 +24,13 @@ package de.luhmer.owncloudnewsreader;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.util.Base64;
import android.util.Log;
import android.util.TypedValue;
@ -65,6 +65,7 @@ import de.luhmer.owncloudnewsreader.helper.AsyncTaskHelper;
import de.luhmer.owncloudnewsreader.helper.ThemeChooser;
import de.luhmer.owncloudnewsreader.interfaces.ExpListTextClicked;
import de.luhmer.owncloudnewsreader.model.FolderSubscribtionItem;
import de.luhmer.owncloudnewsreader.model.UserInfo;
import de.luhmer.owncloudnewsreader.reader.HttpJsonRequest;
import de.luhmer.owncloudnewsreader.reader.owncloud.API;
import de.luhmer.owncloudnewsreader.reader.owncloud.OwnCloudReaderMethods;
@ -212,7 +213,7 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM
};
OnChildClickListener onChildClickListener = new OnChildClickListener() {
public OnChildClickListener onChildClickListener = new OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v,
@ -248,7 +249,9 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM
public ExpandableListView getListView() {
return eListView;
}
protected void showTapLogoToSyncShowcaseView() {
@ -279,7 +282,7 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM
return null; //API NOT SUPPORTED!
UserInfo ui = new UserInfo();
UserInfo.Builder ui = new UserInfo.Builder();
InputStream inputStream = HttpJsonRequest.getInstance().PerformJsonRequest(api.getUserUrl());
JsonReader reader = new JsonReader(new InputStreamReader(inputStream, "UTF-8"));
@ -289,10 +292,10 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM
while(reader.hasNext() && (currentName = reader.nextName()) != null) {
switch(currentName) {
case "userId":
ui.mUserId = reader.nextString();
ui.setUserId(reader.nextString());
break;
case "displayName":
ui.mDisplayName = reader.nextString();
ui.setDisplayName(reader.nextString());
break;
case "avatar":
com.google.gson.stream.JsonToken jt = reader.peek();
@ -307,7 +310,7 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM
if (currentName.equals("data")) {
String encodedImage = reader.nextString();
byte[] decodedString = Base64.decode(encodedImage, Base64.DEFAULT);
ui.mAvatar = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
ui.setAvatar(BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length));
Log.v(TAG, encodedImage);
} else {
reader.skipValue();
@ -323,7 +326,7 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM
}
reader.close();
return ui;
return ui.build();
} catch (Exception e) {
if(e.getMessage().equals("Method Not Allowed")) { //Remove if old version is used
SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
@ -351,6 +354,10 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM
}
protected void bindUserInfoToUI() {
bindUserInfoToUI(false);
}
public void bindUserInfoToUI(boolean testMode) {
SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
String mUsername = mPrefs.getString(SettingsActivity.EDT_USERNAME_STRING, null);
String mOc_root_path = mPrefs.getString(SettingsActivity.EDT_OWNCLOUDROOTPATH_STRING, getString(R.string.app_name));
@ -358,6 +365,10 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM
userTextView.setText(mUsername);
urlTextView.setText(mOc_root_path);
if(testMode) { //Hide real url in test mode
urlTextView.setText("https://example.com/owncloud");
}
String uInfo = mPrefs.getString("USER_INFO", null);
if(uInfo == null)
return;
@ -380,14 +391,8 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM
}
private class UserInfo implements Serializable {
private String mUserId;
private String mDisplayName;
private Bitmap mAvatar;
}
/** Read the object from Base64 string. */
private static Object fromString(String s) throws IOException,
public static Object fromString(String s) throws IOException,
ClassNotFoundException {
byte [] data = Base64.decode(s, Base64.DEFAULT);
ObjectInputStream ois = new ObjectInputStream(
@ -398,7 +403,7 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM
}
/** Write the object to a Base64 string. */
private static String toString(Serializable o) throws IOException {
public static String toString(Serializable o) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream( baos );
oos.writeObject(o);

View file

@ -12,6 +12,7 @@ import android.content.res.Resources;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.VisibleForTesting;
import android.support.v4.view.GravityCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
@ -482,7 +483,8 @@ public class PodcastFragmentActivity extends AppCompatActivity implements IPlayP
return px;
}
protected void openMediaItem(MediaItem mediaItem) {
@VisibleForTesting
public void openMediaItem(MediaItem mediaItem) {
Intent intent = new Intent(this, PodcastPlaybackService.class);
if(mediaItem instanceof TTSItem)
intent.putExtra(PodcastPlaybackService.TTS_ITEM, mediaItem);

View file

@ -0,0 +1,46 @@
package de.luhmer.owncloudnewsreader.model;
import android.graphics.Bitmap;
import java.io.Serializable;
/**
* Created by dluhmer on 19.03.16.
*/
public class UserInfo implements Serializable {
public static class Builder {
private String userId;
private String displayName;
private Bitmap avatar;
public Builder setUserId(String userId) {
this.userId = userId;
return this;
}
public Builder setDisplayName(String displayName) {
this.displayName = displayName;
return this;
}
public Builder setAvatar(Bitmap avatar) {
this.avatar = avatar;
return this;
}
public UserInfo build() {
return new UserInfo(userId, displayName, avatar);
}
}
private UserInfo(String userId, String displayName, Bitmap avatar) {
this.mUserId = userId;
this.mDisplayName = displayName;
this.mAvatar = avatar;
}
public final String mUserId;
public final String mDisplayName;
public final Bitmap mAvatar;
}

16
Screengrabfile Normal file
View file

@ -0,0 +1,16 @@
# remove the leading '#' to uncomment lines
app_package_name 'de.luhmer.owncloudnewsreader'
use_tests_in_packages ['screengrab']
# use_tests_in_classes ['ScreenshotTest']
app_apk_path 'News-Android-App/build/outputs/apk/News-Android-App-debug-unaligned.apk'
tests_apk_path 'News-Android-App/build/outputs/apk/News-Android-App-debug-androidTest-unaligned.apk'
locales ['en-US', 'fr-FR', 'it-IT']
# clear all previously generated screenshots in your local output directory before creating new ones
clear_previous_screenshots true
# For more information about all available options run
# screengrab --help

3
executeScreengrab.sh Normal file
View file

@ -0,0 +1,3 @@
# export PATH=$PATH:/Users/dluhmer/Library/Android/sdk/platform-tools/
./gradlew assembleDebug assembleAndroidTest
screengrab

View file

@ -1,6 +1,6 @@
#Sun Dec 07 11:51:22 CET 2014
#Sat Mar 19 10:26:26 CET 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2-all.zip

0
gradlew vendored Normal file → Executable file
View file