Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add automatic screenshot taking, add german translation and fully integrate it in Android #36

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
52 changes: 52 additions & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ android {
targetSdkVersion androidSDKVersion
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}

compileOptions {
Expand All @@ -44,11 +45,62 @@ android {
packagingOptions {
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
exclude 'LICENSE.txt'
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23+'
compile project(':core')

androidTestCompile 'com.android.support:support-annotations:23.0.1'
androidTestCompile 'com.android.support.test:runner:0.4.1'
androidTestCompile 'com.android.support.test:rules:0.4.1'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
}

def getAdbPath() {
def path
def localProperties = project.file("../local.properties")
if (localProperties.exists()) {
Properties properties = new Properties()
localProperties.withInputStream { instr ->
properties.load(instr)
}
def sdkDir = properties.getProperty('sdk.dir')
if (sdkDir) {
path = sdkDir
} else {
path = "$System.env.ANDROID_HOME"
}
} else {
path = "$System.env.ANDROID_HOME"
}

return path + "/platform-tools/adb"
}

task takeScreenshots() {
dependsOn "connectedAndroidTestDebug"
println("Note: Animations MUST BE disabled, go to ->Settings -> Developer Options and disable them.")
println("This note is always shown:)")
}

task pullScreenshots() {
dependsOn takeScreenshots
doLast {
def stdout = new ByteArrayOutputStream()
exec {
commandLine 'cmd', '/C' + getAdbPath(), 'shell', 'echo', '$EXTERNAL_STORAGE'
standardOutput = stdout;
}

def extStorage = stdout.toString()
def pathOnDevice = extStorage.toString().trim() + "/screenshot"

exec {
commandLine 'cmd', '/C' + getAdbPath(), 'pull', pathOnDevice, "$projectDir/screenshot"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
* Copyright (C) 2013-2015 RoboVM AB
*
* 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 org.robovm.store;

import android.app.Activity;
import android.os.SystemClock;
import android.support.test.InstrumentationRegistry;
import android.support.test.annotation.UiThreadTest;
import android.test.ActivityInstrumentationTestCase2;

import org.junit.Before;
import org.robovm.store.api.RoboVMWebService;
import org.robovm.store.fragments.ShippingDetailsFragment;
import org.robovm.store.model.Order;
import org.robovm.store.model.Product;
import org.robovm.store.model.User;

import static android.support.test.espresso.Espresso.onData;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.anything;

/**
* Automatically takes screenshots of the different fragments of the app.
* Screenshots are stored in EXTERNAL_STORAGE/screenshots, they are transfered to android/screenshots
* Animations MUST BE disabled, go to ->Settings -> Developer Options and disable them.
*/
public class ScreenshotAutomation
extends ActivityInstrumentationTestCase2<StoreAppActivity> {

private StoreAppActivity mActivity;

public ScreenshotAutomation() {
super(StoreAppActivity.class);
}

@UiThreadTest
@Before
public void setUp() throws Exception {
super.setUp();
injectInstrumentation(InstrumentationRegistry.getInstrumentation());
mActivity = getActivity();
onView(withText(mActivity.getString(R.string.app_name))).perform(click()); //Unfocus the app title
clearBasket();
}

private void clearBasket() {
try {
runTestOnUiThread(() -> RoboVMWebService.getInstance().getBasket().clear());
} catch (Throwable t) {
t.printStackTrace();
}
RoboVMWebService.getInstance().getBasket().getOrders().clear();
}

@UiThreadTest
public void testTakeScreenshotOfProductList() {
SystemClock.sleep(5000);
takeScreenshot("product_list", mActivity);
}

@UiThreadTest
public void testTakeScreenshotOfProductDetail() {
onData(anything())
.inAdapterView(withId(android.R.id.list))
.atPosition(0)
.perform(click());
SystemClock.sleep(2000);
takeScreenshot("product_detail", mActivity);
}

@UiThreadTest
public void testTakeScreenshotOfBasket() throws Throwable {
runTestOnUiThread(() -> {
RoboVMWebService.getInstance().getProducts((products) -> {
for (Product product : products) {
RoboVMWebService.getInstance().getBasket().add(new Order(product));
}
});
}
);
SystemClock.sleep(15000);
onView(withId(R.id.cart_menu_item)).perform(click());
takeScreenshot("basket_list", mActivity);
}

@UiThreadTest
public void testTakeScreenshotOfInstructions() throws Throwable {
runTestOnUiThread(mActivity::showLogin);
SystemClock.sleep(2000);
takeScreenshot("login_without_instructions", mActivity);
}

@UiThreadTest
public void testTakeScreenshotOfShippingScreen() throws Throwable {
runTestOnUiThread(() -> {
User u = new User();
u.setCountry("");
ShippingDetailsFragment shipping = new ShippingDetailsFragment(u);
mActivity.switchScreens(shipping);
}
);

SystemClock.sleep(2000);
takeScreenshot("shipping_screen", mActivity);
}

@UiThreadTest
public void testTakeScreenshotOfBragScreen() throws Throwable {
runTestOnUiThread(mActivity::orderCompleted);
SystemClock.sleep(2000);
takeScreenshot("brag_screen", mActivity);
}


private void takeScreenshot(String name, Activity mActivity) {
// Take screenshots, save one with a timestamp, the other without, so we can easily pull it back via adb.
//Some screenshots can't be taken if it isn't run from the ui-thread!
try {
runTestOnUiThread(() -> {
ScreenshotTaker.takeScreenshotWithTimestamp(name, mActivity);
ScreenshotTaker.takeScreenshot("latest_" + name, mActivity);
});
} catch (Throwable t) {
System.err.println("Failed to take screenshot, name: " + name);
t.printStackTrace();
}
}

}
87 changes: 87 additions & 0 deletions android/src/androidTest/java/org/robovm/store/ScreenshotTaker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright (C) 2013-2015 RoboVM AB
*
* 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 org.robovm.store;

import android.app.Activity;
import android.graphics.Bitmap;
import android.view.View;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

public class ScreenshotTaker {

/**
* Takes a screenshot of the given activity.
* Saves the screenshot as png, it's saved as MM_DD_YY_HH-MM-SS_filename.png
* All screenshots are saved on the external storage in the "screenshot" folder
*
* @param fileName the name of the file that is added after the timestamp
* @param activity the activitiy to take the screenshot of
*/
public static void takeScreenshotWithTimestamp(String fileName, Activity activity) {
Date d = new Date();
Calendar c = Calendar.getInstance(Locale.ENGLISH);
String time = c.get(Calendar.MONTH) + "_" + c.get(Calendar.DAY_OF_MONTH)
+ "_" + c.get(Calendar.YEAR) + "_" + +c.get(Calendar.HOUR_OF_DAY)
+ "-" + c.get(Calendar.MINUTE) + "-" + c.get(Calendar.SECOND);
takeScreenshot(time + "_" + fileName, activity);
}

/**
* Takes a screenshot of the given activity.
* Saves the screenshot as png, it's saved as filename.png
* All screenshots are saved on the external storage in the "screenshot" folder
*
* @param fileName the name of the screenshot file
* @param activity the activitiy to take the screenshot of
*/
public static void takeScreenshot(String fileName, Activity activity) {
File root = android.os.Environment.getExternalStorageDirectory();
File dir = new File(root.getAbsolutePath() + "/screenshot");
dir.mkdirs();
File imageFile = new File(dir, fileName + ".png");

View view = activity.getWindow().getDecorView().getRootView();
view.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);

OutputStream os = null;

try {
os = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);
os.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException ee) {
ee.printStackTrace();
} finally {
try {
os.close();
} catch (Exception e) {
}
}
}
}
6 changes: 6 additions & 0 deletions android/src/debug/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.robovm.store">

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>
Loading