Add support for integration tests

Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>
This commit is contained in:
tobiasKaminsky 2018-03-02 12:08:09 +01:00
parent aac3f6a21a
commit 76d3747748
No known key found for this signature in database
GPG Key ID: 0E00D4D47D0C5AF7
13 changed files with 642 additions and 362 deletions

13
.codecov.yml Normal file
View File

@ -0,0 +1,13 @@
codecov:
branch: master
ci:
- drone.nextcloud.com
coverage:
precision: 2
round: down
range: "70...100"
comment:
layout: "header, diff, changes, uncovered, tree"
behavior: default

View File

@ -1,35 +1,34 @@
pipeline: pipeline:
test: compile:
image: nextcloudci/android:android-35 image: nextcloudci/android:android-35
commands: commands:
# uncomment gplay for Gplay, Modified only # uncomment gplay for Gplay
- sh -c "if [ '$FLAVOUR' != 'Generic' ]; then sed -i '/.*com.google.*/s/^.*\\/\\///g' build.gradle; fi" - sh -c "if [ '${FLAVOR}' = 'Gplay' ]; then sed -i '/.*com.google.*/s/^.*\\/\\///g' build.gradle; fi"
# build app and assemble APK
- sh -c "if [ '${FLAVOR}' != 'Lint' ]; then ./gradlew assemble${FLAVOR}; fi"
when:
matrix:
FLAVOR: [Generic, Gplay]
# - echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI -c 20M test:
# - emulator -avd test -no-window & image: nextcloudci/android:android-35
# - ./wait_for_emulator.sh privileged: true
commands:
# build app and assemble APK, in debug mode - emulator -avd android-27 -no-window -no-audio &
- sh -c "if [ '$FLAVOUR' != 'Lint' ]; then ./gradlew assemble${FLAVOUR}; fi" - ./wait_for_emulator.sh
- ./gradlew jacocoTestGplayDebugUnitTestReport || scripts/uploadReport.sh $LOG_USERNAME $LOG_PASSWORD $DRONE_BUILD_NUMBER "Unit"
# run all the instrumented tests of app module - DISABLED until we get an stable setup for Espresso in Travis - ./gradlew assembleGplayDebug installGplayDebugAndroidTest
# - ./gradlew connectedDebugAndroidTest --info - ./gradlew createGplayDebugCoverageReport || scripts/uploadReport.sh $LOG_USERNAME $LOG_PASSWORD $DRONE_BUILD_NUMBER "IT"
- ./gradlew combinedTestReport
# install app, then assemble and install instrumented tests of app module - curl -o codecov.sh https://codecov.io/bash
# - ./gradlew :install${FLAVOUR}Debug - bash ./codecov.sh -t fc506ba4-33c3-43e4-a760-aada38c24fd5
# - ./gradlew :install${FLAVOUR}DebugAndroidTest secrets: [ LOG_USERNAME, LOG_PASSWORD ]
when:
# run sample instrumented unit test matrix:
# TODO fails because test runner is not available FLAVOR: Gplay
#- adb shell am instrument -w -e debug false -e class com.owncloud.android.datamodel.OCFileUnitTest com.owncloud.android.test/android.support.test.runner.AndroidJUnitRunner
environment:
- ANDROID_TARGET=android-32
- ANDROID_ABI=armeabi-v7a
- LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/:/opt/android-sdk-linux/tools/lib64/gles_mesa/
lint: lint:
image: nextcloudci/android:android-32 image: nextcloudci/android:android-35
commands: commands:
# needs gplay # needs gplay
- sed -i '/.*com.google.*/s/^.*\\/\\///g' build.gradle - sed -i '/.*com.google.*/s/^.*\\/\\///g' build.gradle
@ -38,7 +37,7 @@ pipeline:
secrets: [ GIT_USERNAME, GIT_TOKEN, LOG_USERNAME, LOG_PASSWORD ] secrets: [ GIT_USERNAME, GIT_TOKEN, LOG_USERNAME, LOG_PASSWORD ]
when: when:
matrix: matrix:
FLAVOUR: Lint FLAVOR: Lint
notify: notify:
image: drillster/drone-email image: drillster/drone-email
@ -56,9 +55,16 @@ pipeline:
branch: master branch: master
matrix: matrix:
FLAVOUR: FLAVOR:
- Generic - Generic
- Gplay - Gplay
- Lint - Lint
services:
server:
image: nextcloudci/server:server-1
when:
matrix:
FLAVOR: Gplay
branches: master branches: master

View File

@ -16,6 +16,10 @@ buildscript {
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.1.2' classpath 'com.android.tools.build:gradle:3.1.2'
classpath 'com.google.gms:google-services:3.0.0' classpath 'com.google.gms:google-services:3.0.0'
classpath 'org.codehaus.groovy:groovy-all:2.4.12'
classpath('com.dicedmelon.gradle:jacoco-android:0.1.2') {
exclude group: 'org.codehaus.groovy', module: 'groovy-all'
}
} }
} }
@ -23,6 +27,7 @@ apply plugin: 'com.android.application'
apply plugin: 'checkstyle' apply plugin: 'checkstyle'
apply plugin: 'pmd' apply plugin: 'pmd'
apply plugin: 'findbugs' apply plugin: 'findbugs'
apply plugin: 'jacoco-android'
configurations.all { configurations.all {
// check for updates every build // check for updates every build
@ -33,6 +38,7 @@ ext {
supportLibraryVersion = '27.1.1' supportLibraryVersion = '27.1.1'
googleLibraryVersion = '12.0.1' googleLibraryVersion = '12.0.1'
androidLibraryVersion = '1.0.40' androidLibraryVersion = '1.0.40'
jacocoVersion = "0.7.4.201502262128"
travisBuild = System.getenv("TRAVIS") == "true" travisBuild = System.getenv("TRAVIS") == "true"
@ -99,6 +105,12 @@ android {
flavorDimensions "default" flavorDimensions "default"
buildTypes {
debug {
testCoverageEnabled true
}
}
productFlavors { productFlavors {
// used for f-droid // used for f-droid
generic { generic {
@ -251,6 +263,14 @@ dependencies {
implementation 'org.jetbrains:annotations:15.0' implementation 'org.jetbrains:annotations:15.0'
androidTestImplementation 'tools.fastlane:screengrab:1.0.0' androidTestImplementation 'tools.fastlane:screengrab:1.0.0'
// jacocoAnt "org.jacoco:org.jacoco.ant:${jacocoVersion}"
// jacocoAgent "org.jacoco:org.jacoco.agent:${jacocoVersion}"
// androidJacocoAgent "org.jacoco:org.jacoco.agent:${jacocoVersion}"
// androidJacocoAnt "org.jacoco:org.jacoco.ant:${jacocoVersion}"
// androidJacocoAnt "org.jacoco:org.jacoco.core:${jacocoVersion}"
// androidJacocoAnt "org.jacoco:org.jacoco.report:${jacocoVersion}"
// androidJacocoAnt "org.jacoco:org.jacoco.agent:${jacocoVersion}"
} }
configurations.all { configurations.all {
@ -270,5 +290,23 @@ android.applicationVariants.all { variant ->
} }
} }
task combinedTestReport(type: JacocoReport) {
reports {
xml.enabled = true
html.enabled = true
}
def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*']
def debugTree = fileTree(dir: "$project.buildDir/intermediates/classes/gplay/debug", excludes: fileFilter)
def mainSrc = "$project.projectDir/src/main/java"
sourceDirectories = files([mainSrc])
classDirectories = files([debugTree])
executionData = fileTree(dir: project.buildDir, includes: [
'jacoco/testGplayDebugUnitTest.exec', 'outputs/code-coverage/connected/flavors/GPLAY/*coverage.ec'
])
}
// uncomment for gplay (must be at the bottom) // uncomment for gplay (must be at the bottom)
//apply plugin: 'com.google.gms.google-services' //apply plugin: 'com.google.gms.google-services'

19
scripts/uploadReport.sh Executable file
View File

@ -0,0 +1,19 @@
#!/usr/bin/env bash
URL=https://nextcloud.kaminsky.me/remote.php/webdav/integrationTests
ID=$3
USER=$1
PASS=$2
TYPE=$4
if [ $TYPE = "IT" ]; then
cd build/reports/androidTests/connected/flavors/GPLAY
else
cd build/reports/tests/testGplayDebugUnitTest
fi
find . -type d -exec curl -u $USER:$PASS -X MKCOL $URL/$ID/$(echo {} | sed s#\./##) \;
find . -type f -exec curl -u $USER:$PASS -X PUT $URL/$ID/$(echo {} | sed s#\./##) --upload-file {} \;
echo "Uploaded failing tests to https://nextcloud.kaminsky.me/index.php/s/XqY52jBr9ZYfDiz -> $ID"
exit 1

View File

@ -0,0 +1,90 @@
package com.owncloud.android;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.support.test.runner.AndroidJUnit4;
import android.test.ApplicationTestCase;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.OwnCloudClientFactory;
import com.owncloud.android.lib.common.accounts.AccountUtils;
import com.owncloud.android.utils.FileStorageUtils;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import java.io.File;
import java.io.IOException;
/**
* Common base for all integration tests
*/
@RunWith(AndroidJUnit4.class)
public abstract class AbstractIT extends ApplicationTestCase<MainApp> {
protected static OwnCloudClient client;
protected static Account account;
protected static Context context;
private static final String username = "test";
private static final String password = "test";
private static final String baseUrl = "server";
public AbstractIT() {
super(MainApp.class);
}
@BeforeClass
public static void beforeAll() {
try {
context = MainApp.getAppContext();
Account temp = new Account(username + "@" + baseUrl, MainApp.getAccountType());
if (!com.owncloud.android.authentication.AccountUtils.exists(temp, context)) {
AccountManager accountManager = AccountManager.get(context);
accountManager.addAccountExplicitly(temp, password, null);
accountManager.setUserData(temp, AccountUtils.Constants.KEY_OC_ACCOUNT_VERSION,
Integer.toString(com.owncloud.android.authentication.AccountUtils.ACCOUNT_VERSION));
accountManager.setUserData(temp, AccountUtils.Constants.KEY_OC_VERSION, "14.0.0.0");
accountManager.setUserData(temp, AccountUtils.Constants.KEY_OC_BASE_URL, "http://" + baseUrl);
}
account = com.owncloud.android.authentication.AccountUtils.getOwnCloudAccountByName(context,
username + "@" + baseUrl);
if (account == null) {
throw new ActivityNotFoundException();
}
client = OwnCloudClientFactory.createOwnCloudClient(account, context);
createDummyFiles();
} catch (OperationCanceledException e) {
e.printStackTrace();
} catch (AuthenticatorException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (AccountUtils.AccountNotFoundException e) {
e.printStackTrace();
}
}
protected FileDataStorageManager getStorageManager() {
return new FileDataStorageManager(account, context.getContentResolver());
}
private static void createDummyFiles() throws IOException {
new File(FileStorageUtils.getSavePath(account.name)).mkdirs();
File file = new File(FileStorageUtils.getSavePath(account.name) + "/123.txt");
file.createNewFile();
}
}

View File

@ -0,0 +1,48 @@
package com.owncloud.android;
import android.support.test.runner.AndroidJUnit4;
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.operations.CreateFolderOperation;
import com.owncloud.android.operations.common.SyncOperation;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Tests related to file operations
*/
@RunWith(AndroidJUnit4.class)
public class FileIT extends AbstractIT {
@Test
public void testCreateFolder() {
String path = "/testFolder/";
// folder does not exist yet
assertNull(getStorageManager().getFileByPath(path));
SyncOperation syncOp = new CreateFolderOperation(path, true);
RemoteOperationResult result = syncOp.execute(client, getStorageManager());
assertTrue(result.isSuccess());
// folder exists
assertTrue(getStorageManager().getFileByPath(path).isFolder());
}
@Test
public void testCreateNonExistingSubFolder() {
String path = "/testFolder/1/2/3/4/5/";
// folder does not exist yet
assertNull(getStorageManager().getFileByPath(path));
SyncOperation syncOp = new CreateFolderOperation(path, true);
RemoteOperationResult result = syncOp.execute(client, getStorageManager());
assertTrue(result.isSuccess());
// folder exists
assertTrue(getStorageManager().getFileByPath(path).isFolder());
}
}

View File

@ -0,0 +1,70 @@
package com.owncloud.android;
import android.support.test.runner.AndroidJUnit4;
import com.owncloud.android.db.OCUpload;
import com.owncloud.android.files.services.FileUploader;
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.operations.UploadFileOperation;
import com.owncloud.android.utils.FileStorageUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Tests related to file uploads
*/
@RunWith(AndroidJUnit4.class)
public class UploadIT extends AbstractIT {
@Test
public void testSimpleUpload() {
OCUpload ocUpload = new OCUpload(FileStorageUtils.getSavePath(account.name) + "/123.txt",
"/testUpload/1.txt", account.name);
UploadFileOperation newUpload = new UploadFileOperation(
account,
null,
ocUpload,
false,
false,
FileUploader.LOCAL_BEHAVIOUR_COPY,
context,
false,
false
);
newUpload.addRenameUploadListener(() -> {
// dummy
});
newUpload.setRemoteFolderToBeCreated();
RemoteOperationResult result = newUpload.execute(client, getStorageManager());
assertTrue(result.isSuccess());
}
@Test
public void testUploadInNonExistingFolder() {
OCUpload ocUpload = new OCUpload(FileStorageUtils.getSavePath(account.name) + "/123.txt",
"/testUpload/2/3/4/1.txt", account.name);
UploadFileOperation newUpload = new UploadFileOperation(
account,
null,
ocUpload,
false,
false,
FileUploader.LOCAL_BEHAVIOUR_COPY,
context,
false,
false
);
newUpload.addRenameUploadListener(() -> {
// dummy
});
newUpload.setRemoteFolderToBeCreated();
RemoteOperationResult result = newUpload.execute(client, getStorageManager());
assertTrue(result.isSuccess());
}
}

View File

@ -1,136 +1,136 @@
/** //**
* ownCloud Android client application // * ownCloud Android client application
* // *
* Copyright (C) 2015 ownCloud Inc. // * Copyright (C) 2015 ownCloud Inc.
* // *
* This program is free software: you can redistribute it and/or modify // * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, // * it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation. // * as published by the Free Software Foundation.
* // *
* This program is distributed in the hope that it will be useful, // * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of // * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. // * GNU General Public License for more details.
* // *
* You should have received a copy of the GNU General Public License // * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. // * along with this program. If not, see <http://www.gnu.org/licenses/>.
* // *
*/ // */
//
package com.owncloud.android.authentication; //package com.owncloud.android.authentication;
//
import android.app.Activity; //import android.app.Activity;
import android.content.Context; //import android.content.Context;
import android.content.Intent; //import android.content.Intent;
import android.os.Bundle; //import android.os.Bundle;
import android.os.RemoteException; //import android.os.RemoteException;
import android.support.test.InstrumentationRegistry; //import android.support.test.InstrumentationRegistry;
import android.support.test.rule.ActivityTestRule; //import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4; //import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.UiDevice; //import android.support.test.uiautomator.UiDevice;
import android.test.suitebuilder.annotation.LargeTest; //import android.test.suitebuilder.annotation.LargeTest;
//
import com.owncloud.android.R; //import com.owncloud.android.R;
//
import org.junit.Before; //import org.junit.Before;
import org.junit.Rule; //import org.junit.Rule;
import org.junit.Test; //import org.junit.Test;
import org.junit.runner.RunWith; //import org.junit.runner.RunWith;
//
import java.lang.reflect.Field; //import java.lang.reflect.Field;
//
import static android.support.test.espresso.Espresso.onView; //import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click; //import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard; //import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard;
import static android.support.test.espresso.action.ViewActions.typeText; //import static android.support.test.espresso.action.ViewActions.typeText;
import static android.support.test.espresso.assertion.ViewAssertions.matches; //import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isEnabled; //import static android.support.test.espresso.matcher.ViewMatchers.isEnabled;
import static android.support.test.espresso.matcher.ViewMatchers.withId; //import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static org.hamcrest.Matchers.not; //import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertTrue; //import static org.junit.Assert.assertTrue;
//
@RunWith(AndroidJUnit4.class) //@RunWith(AndroidJUnit4.class)
@LargeTest //@LargeTest
public class AuthenticatorActivityTest { //public class AuthenticatorActivityTest {
//
public static final String EXTRA_ACTION = "ACTION"; // public static final String EXTRA_ACTION = "ACTION";
public static final String EXTRA_ACCOUNT = "ACCOUNT"; // public static final String EXTRA_ACCOUNT = "ACCOUNT";
//
private static final int WAIT_LOGIN = 5000; // private static final int WAIT_LOGIN = 5000;
//
private static final String ERROR_MESSAGE = "Activity not finished"; // private static final String ERROR_MESSAGE = "Activity not finished";
private static final String RESULT_CODE = "mResultCode"; // private static final String RESULT_CODE = "mResultCode";
//
//
@Rule // @Rule
public ActivityTestRule<AuthenticatorActivity> mActivityRule = new ActivityTestRule<AuthenticatorActivity>( // public ActivityTestRule<AuthenticatorActivity> mActivityRule = new ActivityTestRule<AuthenticatorActivity>(
AuthenticatorActivity.class){ // AuthenticatorActivity.class){
@Override // @Override
protected Intent getActivityIntent() { // protected Intent getActivityIntent() {
//
Context targetContext = InstrumentationRegistry.getInstrumentation() // Context targetContext = InstrumentationRegistry.getInstrumentation()
.getTargetContext(); // .getTargetContext();
Intent result = new Intent(targetContext, AuthenticatorActivity.class); // Intent result = new Intent(targetContext, AuthenticatorActivity.class);
result.putExtra(EXTRA_ACTION, AuthenticatorActivity.ACTION_CREATE); // result.putExtra(EXTRA_ACTION, AuthenticatorActivity.ACTION_CREATE);
result.putExtra(EXTRA_ACCOUNT, ""); // result.putExtra(EXTRA_ACCOUNT, "");
return result; // return result;
} // }
}; // };
//
@Before // @Before
public void init(){ // public void init(){
UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); // UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
/*Point[] coordinates = new Point[4]; // /*Point[] coordinates = new Point[4];
coordinates[0] = new Point(248, 1020); // coordinates[0] = new Point(248, 1020);
coordinates[1] = new Point(248, 429); // coordinates[1] = new Point(248, 429);
coordinates[2] = new Point(796, 1020); // coordinates[2] = new Point(796, 1020);
coordinates[3] = new Point(796, 429);*/ // coordinates[3] = new Point(796, 429);*/
try { // try {
if (!uiDevice.isScreenOn()) { // if (!uiDevice.isScreenOn()) {
uiDevice.wakeUp(); // uiDevice.wakeUp();
//uiDevice.swipe(coordinates, 10); // //uiDevice.swipe(coordinates, 10);
} // }
} catch (RemoteException e) { // } catch (RemoteException e) {
e.printStackTrace(); // e.printStackTrace();
} // }
} // }
//
@Test // @Test
public void checkLogin() // public void checkLogin()
throws InterruptedException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { // throws InterruptedException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Bundle arguments = InstrumentationRegistry.getArguments(); // Bundle arguments = InstrumentationRegistry.getArguments();
//
// Get values passed // // Get values passed
String testUser = arguments.getString("TEST_USER"); // String testUser = arguments.getString("TEST_USER");
String testPassword = arguments.getString("TEST_PASSWORD"); // String testPassword = arguments.getString("TEST_PASSWORD");
String testServerURL = arguments.getString("TEST_SERVER_URL"); // String testServerURL = arguments.getString("TEST_SERVER_URL");
//
// Check that login button is disabled // // Check that login button is disabled
onView(withId(R.id.buttonOK)) // onView(withId(R.id.buttonOK))
.check(matches(not(isEnabled()))); // .check(matches(not(isEnabled())));
//
// Type server url // // Type server url
onView(withId(R.id.hostUrlInput)) // onView(withId(R.id.hostUrlInput))
.perform(typeText(testServerURL), closeSoftKeyboard()); // .perform(typeText(testServerURL), closeSoftKeyboard());
onView(withId(R.id.account_username)).perform(click()); // onView(withId(R.id.account_username)).perform(click());
//
// Type user // // Type user
onView(withId(R.id.account_username)) // onView(withId(R.id.account_username))
.perform(typeText(testUser), closeSoftKeyboard()); // .perform(typeText(testUser), closeSoftKeyboard());
//
// Type user pass // // Type user pass
onView(withId(R.id.account_password)) // onView(withId(R.id.account_password))
.perform(typeText(testPassword), closeSoftKeyboard()); // .perform(typeText(testPassword), closeSoftKeyboard());
onView(withId(R.id.buttonOK)).perform(click()); // onView(withId(R.id.buttonOK)).perform(click());
//
// Check that the Activity ends after clicking // // Check that the Activity ends after clicking
//
Thread.sleep(WAIT_LOGIN); // Thread.sleep(WAIT_LOGIN);
Field f = Activity.class.getDeclaredField(RESULT_CODE); // Field f = Activity.class.getDeclaredField(RESULT_CODE);
f.setAccessible(true); // f.setAccessible(true);
int mResultCode = f.getInt(mActivityRule.getActivity()); // int mResultCode = f.getInt(mActivityRule.getActivity());
//
assertTrue(ERROR_MESSAGE, mResultCode == Activity.RESULT_OK); // assertTrue(ERROR_MESSAGE, mResultCode == Activity.RESULT_OK);
//
} // }
} //}

View File

@ -3,19 +3,18 @@
* *
* @author David A. Velasco * @author David A. Velasco
* Copyright (C) 2016 ownCloud Inc. * Copyright (C) 2016 ownCloud Inc.
* * <p>
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, * it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation. * as published by the Free Software Foundation.
* * <p>
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* * <p>
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/ */

View File

@ -1,131 +1,131 @@
package com.owncloud.android.screenshots; //package com.owncloud.android.screenshots;
//
import android.content.Intent; //import android.content.Intent;
import android.support.test.espresso.Espresso; //import android.support.test.espresso.Espresso;
import android.support.test.espresso.action.ViewActions; //import android.support.test.espresso.action.ViewActions;
import android.support.test.espresso.contrib.DrawerActions; //import android.support.test.espresso.contrib.DrawerActions;
import android.support.test.espresso.matcher.PreferenceMatchers; //import android.support.test.espresso.matcher.PreferenceMatchers;
import android.support.test.rule.ActivityTestRule; //import android.support.test.rule.ActivityTestRule;
//
import com.owncloud.android.R; //import com.owncloud.android.R;
import com.owncloud.android.ui.activity.FileDisplayActivity; //import com.owncloud.android.ui.activity.FileDisplayActivity;
import com.owncloud.android.ui.activity.Preferences; //import com.owncloud.android.ui.activity.Preferences;
//
import junit.framework.Assert; //import junit.framework.Assert;
//
import org.junit.BeforeClass; //import org.junit.BeforeClass;
import org.junit.ClassRule; //import org.junit.ClassRule;
import org.junit.Rule; //import org.junit.Rule;
import org.junit.Test; //import org.junit.Test;
import org.junit.runner.RunWith; //import org.junit.runner.RunWith;
import org.junit.runners.JUnit4; //import org.junit.runners.JUnit4;
//
import tools.fastlane.screengrab.Screengrab; //import tools.fastlane.screengrab.Screengrab;
import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy; //import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy;
import tools.fastlane.screengrab.locale.LocaleTestRule; //import tools.fastlane.screengrab.locale.LocaleTestRule;
//
import static android.support.test.espresso.Espresso.onData; //import static android.support.test.espresso.Espresso.onData;
import static android.support.test.espresso.Espresso.onView; //import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click; //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.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText; //import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.anything; //import static org.hamcrest.Matchers.anything;
import static org.hamcrest.core.AnyOf.anyOf; //import static org.hamcrest.core.AnyOf.anyOf;
//
@RunWith(JUnit4.class) //@RunWith(JUnit4.class)
public class ScreenshotsIT { //public class ScreenshotsIT {
@ClassRule // @ClassRule
public static final LocaleTestRule localeTestRule = new LocaleTestRule(); // public static final LocaleTestRule localeTestRule = new LocaleTestRule();
//
@Rule // @Rule
public ActivityTestRule<FileDisplayActivity> fileDisplayRule = new ActivityTestRule<>(FileDisplayActivity.class); // public ActivityTestRule<FileDisplayActivity> fileDisplayRule = new ActivityTestRule<>(FileDisplayActivity.class);
//
@Rule // @Rule
public ActivityTestRule<Preferences> preferencesRule = new ActivityTestRule<>(Preferences.class, true, false); // public ActivityTestRule<Preferences> preferencesRule = new ActivityTestRule<>(Preferences.class, true, false);
//
@BeforeClass // @BeforeClass
public static void beforeAll() { // public static void beforeAll() {
Screengrab.setDefaultScreenshotStrategy(new UiAutomatorScreenshotStrategy()); // Screengrab.setDefaultScreenshotStrategy(new UiAutomatorScreenshotStrategy());
} // }
//
@Test // @Test
public void gridViewScreenshot() throws InterruptedException { // public void gridViewScreenshot() throws InterruptedException {
fileDisplayRule.launchActivity(new Intent()); // fileDisplayRule.launchActivity(new Intent());
//
Espresso.openContextualActionModeOverflowMenu(); // Espresso.openContextualActionModeOverflowMenu();
onView(anyOf(withText(R.string.action_switch_grid_view), withId(R.id.action_switch_view))).perform(click()); // onView(anyOf(withText(R.string.action_switch_grid_view), withId(R.id.action_switch_view))).perform(click());
//
Thread.sleep(1000); // Thread.sleep(1000);
//
Screengrab.screenshot("01_gridView"); // Screengrab.screenshot("01_gridView");
//
Espresso.openContextualActionModeOverflowMenu(); // Espresso.openContextualActionModeOverflowMenu();
onView(anyOf(withText(R.string.action_switch_list_view), withId(R.id.action_switch_view))).perform(click()); // onView(anyOf(withText(R.string.action_switch_list_view), withId(R.id.action_switch_view))).perform(click());
//
Assert.assertTrue(true); // if we reach this, everything is ok // Assert.assertTrue(true); // if we reach this, everything is ok
} // }
//
@Test // @Test
public void listViewScreenshot() throws InterruptedException { // public void listViewScreenshot() throws InterruptedException {
fileDisplayRule.launchActivity(new Intent()); // fileDisplayRule.launchActivity(new Intent());
//
// go into work folder // // go into work folder
onData(anything()).inAdapterView(withId(R.id.list_root)).atPosition(0).perform(click()); // onData(anything()).inAdapterView(withId(R.id.list_root)).atPosition(0).perform(click());
//
Screengrab.screenshot("02_listView"); // Screengrab.screenshot("02_listView");
//
Assert.assertTrue(true); // if we reach this, everything is ok // Assert.assertTrue(true); // if we reach this, everything is ok
} // }
//
@Test // @Test
public void drawerScreenshot() throws InterruptedException { // public void drawerScreenshot() throws InterruptedException {
fileDisplayRule.launchActivity(new Intent()); // fileDisplayRule.launchActivity(new Intent());
//
onView(withId(R.id.drawer_layout)).perform(DrawerActions.open()); // onView(withId(R.id.drawer_layout)).perform(DrawerActions.open());
//
Screengrab.screenshot("03_drawer"); // Screengrab.screenshot("03_drawer");
//
onView(withId(R.id.drawer_layout)).perform(DrawerActions.close()); // onView(withId(R.id.drawer_layout)).perform(DrawerActions.close());
//
Assert.assertTrue(true); // if we reach this, everything is ok // Assert.assertTrue(true); // if we reach this, everything is ok
} // }
//
@Test // @Test
public void multipleAccountsScreenshot() throws InterruptedException { // public void multipleAccountsScreenshot() throws InterruptedException {
fileDisplayRule.launchActivity(new Intent()); // fileDisplayRule.launchActivity(new Intent());
//
onView(withId(R.id.drawer_layout)).perform(DrawerActions.open()); // onView(withId(R.id.drawer_layout)).perform(DrawerActions.open());
onView(withId(R.id.drawer_active_user)).perform(click()); // onView(withId(R.id.drawer_active_user)).perform(click());
//
Screengrab.screenshot("04_accounts"); // Screengrab.screenshot("04_accounts");
//
onView(withId(R.id.drawer_layout)).perform(DrawerActions.close()); // onView(withId(R.id.drawer_layout)).perform(DrawerActions.close());
//
Assert.assertTrue(true); // if we reach this, everything is ok // Assert.assertTrue(true); // if we reach this, everything is ok
} // }
//
@Test // @Test
public void autoUploadScreenshot() throws InterruptedException { // public void autoUploadScreenshot() throws InterruptedException {
fileDisplayRule.launchActivity(new Intent()); // fileDisplayRule.launchActivity(new Intent());
//
onView(withId(R.id.drawer_layout)).perform(DrawerActions.open()); // onView(withId(R.id.drawer_layout)).perform(DrawerActions.open());
onView(anyOf(withText(R.string.drawer_synced_folders), withId(R.id.nav_synced_folders))).perform(click()); // onView(anyOf(withText(R.string.drawer_synced_folders), withId(R.id.nav_synced_folders))).perform(click());
//
Screengrab.screenshot("05_autoUpload"); // Screengrab.screenshot("05_autoUpload");
//
Assert.assertTrue(true); // if we reach this, everything is ok // Assert.assertTrue(true); // if we reach this, everything is ok
} // }
//
@Test // @Test
public void davdroidScreenshot() throws InterruptedException { // public void davdroidScreenshot() throws InterruptedException {
preferencesRule.launchActivity(new Intent()); // preferencesRule.launchActivity(new Intent());
//
onData(PreferenceMatchers.withTitle(R.string.prefs_category_more)).perform(ViewActions.scrollTo()); // onData(PreferenceMatchers.withTitle(R.string.prefs_category_more)).perform(ViewActions.scrollTo());
//
Thread.sleep(1000); // Thread.sleep(1000);
//
Screengrab.screenshot("06_davdroid"); // Screengrab.screenshot("06_davdroid");
//
Assert.assertTrue(true); // if we reach this, everything is ok // Assert.assertTrue(true); // if we reach this, everything is ok
} // }
} //}

View File

@ -18,24 +18,20 @@
package com.owncloud.android.uiautomator; package com.owncloud.android.uiautomator;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.support.test.InstrumentationRegistry; import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SdkSuppress; import android.support.test.filters.SdkSuppress;
import android.support.test.runner.AndroidJUnit4; import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice; import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject; import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException; import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.UiSelector; import android.support.test.uiautomator.UiSelector;
import android.support.test.uiautomator.Until;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
@ -69,51 +65,51 @@ public class InitialTest {
/** /**
* Start owncloud app * Start owncloud app
*/ */
@Test // @Test
public void startAppFromHomeScreen() { // public void startAppFromHomeScreen() {
// Perform a short press on the HOME button // // Perform a short press on the HOME button
mDevice.pressHome(); // mDevice.pressHome();
//
// Wait for launcher // // Wait for launcher
final String launcherPackage = getLauncherPackageName(); // final String launcherPackage = getLauncherPackageName();
assertThat(launcherPackage, notNullValue()); // assertThat(launcherPackage, notNullValue());
mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT); // mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT);
//
// Launch the app // // Launch the app
Context context = InstrumentationRegistry.getContext(); // Context context = InstrumentationRegistry.getContext();
final Intent intent = context.getPackageManager() // final Intent intent = context.getPackageManager()
.getLaunchIntentForPackage(OWNCLOUD_APP_PACKAGE); // .getLaunchIntentForPackage(OWNCLOUD_APP_PACKAGE);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); // intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intent); // context.startActivity(intent);
//
// Wait for the app to appear // // Wait for the app to appear
mDevice.wait(Until.hasObject(By.pkg(OWNCLOUD_APP_PACKAGE).depth(0)), LAUNCH_TIMEOUT); // mDevice.wait(Until.hasObject(By.pkg(OWNCLOUD_APP_PACKAGE).depth(0)), LAUNCH_TIMEOUT);
} // }
/** /**
* Start Settings app * Start Settings app
* *
* @throws UiObjectNotFoundException * @throws UiObjectNotFoundException
*/ */
@Test // @Test
public void startSettingsFromHomeScreen() throws UiObjectNotFoundException { // public void startSettingsFromHomeScreen() throws UiObjectNotFoundException {
//
mDevice.pressHome(); // mDevice.pressHome();
//
// Wait for launcher // // Wait for launcher
final String launcherPackage = getLauncherPackageName(); // final String launcherPackage = getLauncherPackageName();
assertThat(launcherPackage, notNullValue()); // assertThat(launcherPackage, notNullValue());
mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT); // mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT);
//
// Launch the app // // Launch the app
Context context = InstrumentationRegistry.getContext(); // Context context = InstrumentationRegistry.getContext();
final Intent intent = context.getPackageManager() // final Intent intent = context.getPackageManager()
.getLaunchIntentForPackage(ANDROID_SETTINGS_PACKAGE); // .getLaunchIntentForPackage(ANDROID_SETTINGS_PACKAGE);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); // intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intent); // context.startActivity(intent);
//
clickByText(SETTINGS_DATA_USAGE_OPTION); // clickByText(SETTINGS_DATA_USAGE_OPTION);
} // }
/** /**
* Uses package manager to find the package name of the device launcher. Usually this package * Uses package manager to find the package name of the device launcher. Usually this package

View File

@ -55,6 +55,7 @@ public class ErrorMessageAdapterUnitTest {
private final static String MOCK_TO_DELETE = "to delete this file"; private final static String MOCK_TO_DELETE = "to delete this file";
private final static String PATH_TO_DELETE = "/path/to/a.file"; private final static String PATH_TO_DELETE = "/path/to/a.file";
private final static String EXPECTED_ERROR_MESSAGE = "You do not have permission to delete this file"; private final static String EXPECTED_ERROR_MESSAGE = "You do not have permission to delete this file";
private final static String ACCOUNT_TYPE = "nextcloud";
@Mock @Mock
Resources mMockResources; Resources mMockResources;
@ -67,7 +68,7 @@ public class ErrorMessageAdapterUnitTest {
when(mMockResources.getString(R.string.forbidden_permissions_delete)) when(mMockResources.getString(R.string.forbidden_permissions_delete))
.thenReturn(MOCK_TO_DELETE); .thenReturn(MOCK_TO_DELETE);
Account account = new Account("name", MainApp.getAccountType()); Account account = new Account("name", ACCOUNT_TYPE);
// ... when method under test is called ... // ... when method under test is called ...
String errorMessage = ErrorMessageAdapter.getErrorCauseMessage( String errorMessage = ErrorMessageAdapter.getErrorCauseMessage(

View File

@ -17,7 +17,7 @@ until [[ "$bootanim" =~ "stopped" ]]; do
fi fi
fi fi
let "checkcounter += 1" let "checkcounter += 1"
sleep 10 sleep 5
done done
echo "($checkcounter) Done" echo "($checkcounter) Done"
adb -e shell input keyevent 82 adb -e shell input keyevent 82