Skip to content

Commit

Permalink
Fixed issue with running many instrumentation tests (#536)
Browse files Browse the repository at this point in the history
During tests, activities were not closed properly causing increasing
memory usage, which resulted in failing tests because of
out of memory errors.
This has been fixed by using the test orchestrator which runs
each test in its own instrumentation instance.

Removed the instrumentationTest flavor and replaced it by using the
default debug build type. The flavor was used to keep the required
permissions during testing separate from release versions. This can
also be accomplished using the debug build type.

The PagerSlidingTabStrip from astuetz doesn't work with the new
android build tools. As the project seems dead, I replaced it with
PagerTabStrip from the support library.
  • Loading branch information
poisdeux authored and SyncedSynapse committed May 3, 2018
1 parent 75f8326 commit f631efe
Show file tree
Hide file tree
Showing 55 changed files with 123 additions and 148 deletions.
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ android:
# "tools" always refers to the latest build tools version. Remove this
# when travis is able to parse "build-tools-23.0.3" correctly.
# See https://github.com/travis-ci/travis-ci/issues/5036
- tools
# - tools
# needed build tools
- build-tools-26.0.2
- build-tools-27.0.3

# The SDK version used to compile your project
- android-26
Expand All @@ -27,4 +27,4 @@ android:
before_script:

script:
- ./gradlew lintFullRelease testFullDebugUnitTest assembleFullRelease
- ./gradlew assembleRelease lintRelease testDebugUnitTest
126 changes: 51 additions & 75 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ def getVersionName = { ->

android {
compileSdkVersion 26
buildToolsVersion "26.0.2"
buildToolsVersion "27.0.3"

defaultConfig {
applicationId "org.xbmc.kore"
minSdkVersion 15
targetSdkVersion 26
versionCode 19
versionName = getVersionName()
vectorDrawables.useSupportLibrary = true
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}

File keystoreFile = file('keystore.properties')
Expand All @@ -38,38 +40,22 @@ android {
}
}

sourceSets {
fullDebug {
assets.srcDirs += 'src/testUtils/assets'
}
test {
java.srcDirs += 'src/testUtils/java'
}
androidTest {
java.srcDirs += 'src/testUtils/java'
}
instrumentationTest {
assets.srcDirs += 'src/testUtils/assets'
}
}

productFlavors {
full {
}
// sourceSets {
// test {
// java.srcDirs += 'src/testUtils/java'
// assets.srcDirs += 'src/testUtils/assets'
// }
// androidTest {
// java.srcDirs += 'src/testUtils/java'
// assets.srcDirs += 'src/testUtils/assets'
// }
// }

instrumentationTest {
applicationId "org.xbmc.kore.instrumentationtest"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
proguardFiles 'proguardTest-rules.pro'
}
testOptions {
execution 'ANDROID_TEST_ORCHESTRATOR'
}

buildTypes {
// debug {
// minifyEnabled true
// proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
// }

release {
if (keystoreFile.exists()) {
signingConfig signingConfigs.release
Expand All @@ -86,7 +72,7 @@ android {
//The xml launcher icon introduced in API 26 causes lint to generate
//an error that the icon is not a PNG format
//This reduces the error to a warning
warning 'IconLauncherFormat'
// warning 'IconLauncherFormat'
}

// allprojects {
Expand All @@ -111,66 +97,56 @@ ext {
}

dependencies {
compile "com.android.support:support-v4:${supportLibVersion}"
compile "com.android.support:appcompat-v7:${supportLibVersion}"
compile "com.android.support:cardview-v7:${supportLibVersion}"
compile "com.android.support:preference-v14:${supportLibVersion}"
compile "com.android.support:support-v13:${supportLibVersion}"
compile "com.android.support:design:${supportLibVersion}"

compile 'com.fasterxml.jackson.core:jackson-databind:2.5.2'
compile 'com.jakewharton:butterknife:8.8.1'
implementation "com.android.support:support-v4:${supportLibVersion}"
implementation "com.android.support:appcompat-v7:${supportLibVersion}"
implementation "com.android.support:cardview-v7:${supportLibVersion}"
implementation "com.android.support:preference-v14:${supportLibVersion}"
implementation "com.android.support:support-v13:${supportLibVersion}"
implementation "com.android.support:design:${supportLibVersion}"

implementation 'com.fasterxml.jackson.core:jackson-databind:2.5.2'
implementation 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
compile 'com.squareup.okhttp:okhttp:2.3.0'
compile 'com.squareup.picasso:picasso:2.5.2'
compile 'de.greenrobot:eventbus:2.4.0'
compile 'org.jmdns:jmdns:3.5.1'
compile 'com.astuetz:pagerslidingtabstrip:1.0.1'
compile 'at.blogc:expandabletextview:1.0.3'
compile 'com.sothree.slidinguppanel:library:3.3.1'

androidTestCompile 'com.android.support.test:runner:1.0.1'
androidTestCompile 'com.android.support.test:rules:1.0.1'
androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
androidTestCompile 'com.android.support.test.espresso:espresso-core:3.0.1'
androidTestCompile "com.android.support:support-v13:${supportLibVersion}"
instrumentationTestCompile 'junit:junit:4.12'

testCompile 'org.robolectric:robolectric:3.1.1'
testCompile 'junit:junit:4.12'

compile fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.squareup.okhttp:okhttp:2.3.0'
implementation 'com.squareup.picasso:picasso:2.5.2'
implementation 'de.greenrobot:eventbus:2.4.0'
implementation 'org.jmdns:jmdns:3.5.1'
implementation 'at.blogc:expandabletextview:1.0.3'
implementation 'com.sothree.slidinguppanel:library:3.3.1'

androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test:rules:1.0.1'
androidTestUtil 'com.android.support.test:orchestrator:1.0.1'
androidTestImplementation 'org.hamcrest:hamcrest-library:1.3'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
androidTestImplementation "com.android.support:support-v13:${supportLibVersion}"
androidTestImplementation 'junit:junit:4.12'

testImplementation 'org.robolectric:robolectric:3.1.1'
debugImplementation 'junit:junit:4.12'
implementation fileTree(dir: 'libs', include: ['*.jar'])
}

// Get the path to ADB. Required when running tests directly from Android Studio.
// Source: http://stackoverflow.com/a/26771087/112705
def adb = android.getAdbExe().toString()

// Source: http://stackoverflow.com/q/29908110/112705
def adb = android.getAdbExecutable().toString()
afterEvaluate {
task grantAnimationPermissionDev(type: Exec, dependsOn: 'installInstrumentationTestDebug') {
task grantAnimationPermissionDev(type: Exec, dependsOn: installDebug) {
doFirst {
println("Executing: $adb shell pm grant $android.productFlavors.instrumentationTest.applicationId android.permission.SET_ANIMATION_SCALE")
commandLine "$adb shell pm grant $android.productFlavors.instrumentationTest.applicationId android.permission.SET_ANIMATION_SCALE".split(' ')
println("Executing: $adb shell pm grant $android.defaultConfig.applicationId android.permission.SET_ANIMATION_SCALE")
commandLine "$adb shell pm grant $android.defaultConfig.applicationId android.permission.SET_ANIMATION_SCALE".split(' ')
}
}

// When launching individual tests from Android Studio, it seems that only the assemble tasks
// get called directly, not the install* versions
tasks.each { task ->
if (task.name.startsWith('assembleInstrumentationTestDebugAndroidTest')) {
if (task.name.startsWith('connectedDebugAndroidTest')) {
task.dependsOn grantAnimationPermissionDev
}
}
}

/**
* Android gradle plugin 2.3.x contains a bug where the assets for fullDebug
* are not copied. The task assembleFullDebug does copy the required assets,
* so this dependency fixes the issue.
* Makes sure assets are copied before running the unit tests
*/
tasks.whenTaskAdded { task ->
if (task.name.contains("compileFullDebugUnitTestSources")) {
task.dependsOn assembleFullDebug
if (task.name.contains("testDebugUnitTest")) {
task.dependsOn assembleDebug
}
}
8 changes: 0 additions & 8 deletions app/proguardTest-rules.pro

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@
import static android.support.test.espresso.Espresso.pressBack;
import static android.support.test.espresso.action.ViewActions.clearText;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.action.ViewActions.swipeLeft;
import static android.support.test.espresso.action.ViewActions.swipeRight;
import static android.support.test.espresso.action.ViewActions.typeText;
import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
Expand Down Expand Up @@ -209,24 +207,10 @@ public void perform(UiController uiController, View view) {

/**
* Clicks on tab that contains the text given by stringResourceId.
* If the click fails tries again after a swipe left. If the click fails
* after that try once more after swiping right two times. The first swipe right
* is performed to negate the previous swipe left.
* @param stringResourceId text displayed in Tab that should be clicked
*/
public static void clickTab(int stringResourceId) {
try {
onView(withText(stringResourceId)).perform(click());
} catch (Exception e1) {
try {
onView(withId(R.id.pager_tab_strip)).perform(swipeLeft());
onView(withText(stringResourceId)).perform(click());
} catch (Exception e2) {
onView(withId(R.id.pager_tab_strip)).perform(swipeRight());
onView(withId(R.id.pager_tab_strip)).perform(swipeRight());
onView(withText(stringResourceId)).perform(click());
}
}
onView(withId(R.id.pager)).perform(ViewActions.setCurrentViewPagerItem(stringResourceId));
}

/**
Expand Down
2 changes: 2 additions & 0 deletions app/src/androidTest/java/org/xbmc/kore/testhelpers/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ public static void enableAnimations(Context context) {
int permStatus = context.checkCallingOrSelfPermission(ANIMATION_PERMISSION);
if (permStatus == PackageManager.PERMISSION_GRANTED) {
setSystemAnimationsScale(DEFAULT);
} else {
LogUtils.LOGD(TAG, "disableAnimations: permission " + ANIMATION_PERMISSION + " not granted");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import android.support.test.espresso.action.ScrollToAction;
import android.support.test.espresso.util.HumanReadables;
import android.support.test.espresso.util.TreeIterables;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.widget.SeekBar;

Expand Down Expand Up @@ -157,4 +159,42 @@ public void perform(UiController uiController, View view) {
}
};
}

public static ViewAction setCurrentViewPagerItem(final int pageTitleResourceId) {
return new ViewAction() {

@Override
public Matcher<View> getConstraints() {
return new TypeSafeMatcher<View>() {
@Override
protected boolean matchesSafely(View item) {
return item instanceof ViewPager;
}

@Override
public void describeTo(Description description) {
description.appendText("is a SeekBar.");
}
};
}

@Override
public String getDescription() {
return null;
}

@Override
public void perform(UiController uiController, View view) {
ViewPager viewPager = (ViewPager) view;
String expectedTitle = view.getResources().getString(pageTitleResourceId);
PagerAdapter pagerAdapter = viewPager.getAdapter();
for(int i = 0; i < pagerAdapter.getCount(); i++) {
if (expectedTitle.contentEquals(pagerAdapter.getPageTitle(i))) {
viewPager.setCurrentItem(i);
return;
}
}
}
};
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
5 changes: 0 additions & 5 deletions app/src/instrumentationTest/README.md

This file was deleted.

5 changes: 0 additions & 5 deletions app/src/main/java/org/xbmc/kore/ui/AbstractTabsFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
import android.view.View;
import android.view.ViewGroup;

import com.astuetz.PagerSlidingTabStrip;

import org.xbmc.kore.R;
import org.xbmc.kore.utils.LogUtils;
import org.xbmc.kore.utils.SharedElementTransition;
Expand All @@ -39,7 +37,6 @@ abstract public class AbstractTabsFragment extends AbstractFragment
implements SharedElementTransition.SharedElement {
private static final String TAG = LogUtils.makeLogTag(AbstractTabsFragment.class);

@BindView(R.id.pager_tab_strip) PagerSlidingTabStrip pagerTabStrip;
@BindView(R.id.pager) ViewPager viewPager;

private Unbinder unbinder;
Expand All @@ -64,8 +61,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa
unbinder = ButterKnife.bind(this, root);

viewPager.setAdapter(createTabsAdapter(getDataHolder()));
pagerTabStrip.setViewPager(viewPager);

return root;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,17 @@
package org.xbmc.kore.ui.sections.audio;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.astuetz.PagerSlidingTabStrip;

import org.xbmc.kore.R;
import org.xbmc.kore.ui.AbstractCursorListFragment;
import org.xbmc.kore.ui.AbstractFragment;
import org.xbmc.kore.ui.AbstractTabsFragment;
import org.xbmc.kore.utils.LogUtils;
import org.xbmc.kore.utils.TabsAdapter;

import butterknife.ButterKnife;
import butterknife.BindView;

/**
* Container for the various music lists
*/
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/drawable/ic_sunny_white_24dp.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
<vector android:alpha="1.00" android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FFFFFFFF" android:pathData="M6.76 4.84l-1.8-1.79-1.41 1.41 1.79 1.79 1.42-1.41zM4 10.5H1v2h3v-2zm9-9.95h-2V3.5h2V.55zm7.45 3.91l-1.41-1.41-1.79 1.79 1.41 1.41 1.79-1.79zm-3.21 13.7l1.79 1.8 1.41-1.41-1.8-1.79-1.4 1.4zM20 10.5v2h3v-2h-3zm-8-5c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6zm-1 16.95h2V19.5h-2v2.95zm-7.45-3.91l1.41 1.41 1.79-1.8-1.41-1.41-1.79 1.8z"/>
<path android:fillColor="#FFFFFFFF" android:pathData="M6.76 4.84l-1.8-1.79-1.41 1.41 1.79 1.79 1.42-1.41zM4 10.5H1v2h3v-2zm9-9.95h-2V3.5h2V0.55zm7.45 3.91l-1.41-1.41-1.79 1.79 1.41 1.41 1.79-1.79zm-3.21 13.7l1.79 1.8 1.41-1.41-1.8-1.79-1.4 1.4zM20 10.5v2h3v-2h-3zm-8-5c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6zm-1 16.95h2V19.5h-2v2.95zm-7.45-3.91l1.41 1.41 1.79-1.8-1.41-1.41-1.79 1.8z"/>
</vector>
16 changes: 9 additions & 7 deletions app/src/main/res/layout/fragment_default_view_pager.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.astuetz.PagerSlidingTabStrip
android:id="@+id/pager_tab_strip"
android:layout_width="match_parent"
android:layout_height="@dimen/tab_strip_height"
style="@style/TabStrip"/>

<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
android:layout_height="match_parent">

<android.support.v4.view.PagerTabStrip
android:id="@+id/pager_tab_strip"
android:layout_width="match_parent"
android:layout_height="@dimen/tab_strip_height"
style="@style/TabStrip"/>

</android.support.v4.view.ViewPager>

</LinearLayout>
Loading

0 comments on commit f631efe

Please sign in to comment.