Skip to content

Commit

Permalink
Merge pull request #46 from fs/take-screenshots-when-ui-tests-failed
Browse files Browse the repository at this point in the history
Take screenshots when ui tests failed
  • Loading branch information
Ilya Eremin authored Apr 14, 2017
2 parents 66836d7 + 19dea64 commit a07d701
Show file tree
Hide file tree
Showing 11 changed files with 185 additions and 40 deletions.
33 changes: 18 additions & 15 deletions .idea/codeStyleSettings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 25 additions & 5 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
apply plugin: 'com.android.application'
apply plugin: 'me.tatarka.retrolambda'
apply plugin: 'spoon'
apply from: 'checkstyle/checkstyle.gradle'

apply from: '../deps.gradle'
Expand All @@ -21,6 +22,8 @@ android {
applicationId APPLICATION_ID
versionCode 1
versionName '1.0-beta'
testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
com.android.ddmlib.DdmPreferences.setTimeOut(60000)
}

productFlavors {
Expand Down Expand Up @@ -61,7 +64,6 @@ android {

dexOptions {
preDexLibraries = !isCI
incremental = !isCI
}

packagingOptions {
Expand All @@ -76,6 +78,10 @@ android {
lintConfig file("$projectDir/lint.xml")
warningsAsErrors true
}

configurations.all {
// resolutionStrategy.force "com.android.support:support-annotations:$versions.support"
}
}

repositories {
Expand All @@ -88,18 +94,32 @@ dependencies {
// compile retrofitLibs
// compile okHttpLibs

compile 'com.google.code.gson:gson:2.4'
compile 'com.jakewharton:butterknife:7.0.0' // view injection
compile 'com.github.bumptech.glide:glide:3.7.0'

testCompile unitTestLibs
androidTestCompile androidTestsLibs
}

compile 'com.google.code.gson:gson:2.4'
// Grant animation permissions to avoid test failure because of ui sync.
task grantAnimationPermissions(type: Exec, dependsOn: ['installStagingDebug', 'installProductionDebug']) {
group = 'test'
description = 'Grant permissions for testing.'

def absolutePath = file('..') // Get project absolute path
commandLine "$absolutePath/app/set_animation_permissions.sh com.flatstack.android".split(" ")
}

configurations {
testCompile.exclude module: 'commons-logging'
testCompile.exclude module: 'httpclient'
// Source: http://stackoverflow.com/q/29908110/112705
afterEvaluate {
// 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.endsWith('AndroidTest')) {
task.dependsOn grantAnimationPermissions
}
}
}

apply from: "quality.gradle"
15 changes: 15 additions & 0 deletions app/set_animation_permissions.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
adb=$ANDROID_HOME/platform-tools/adb
package=$1

if [ "$#" = 0 ]; then
echo "No parameters found, run with sh set_animation_permissions.sh <package>"
exit 0
fi

# get all the devices
devices=$($adb devices | grep -v 'List of devices' | cut -f1 | grep '.')

for device in $devices; do
echo "Setting permissions to device" $device "for package" $package
$adb -s $device shell pm grant $package android.permission.SET_ANIMATION_SCALE
done
13 changes: 13 additions & 0 deletions app/src/androidTest/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.flatstack.android"
>

<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<!-- Disable animations on debug builds so that the animations do not interfere with Espresso
tests. Adding this permission to the manifest is not sufficient - you must also grant the
permission over adb! -->
<uses-permission android:name="android.permission.SET_ANIMATION_SCALE"/>

</manifest>
34 changes: 34 additions & 0 deletions app/src/androidTest/java/com/flatstack/android/MainScreenTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.flatstack.android;

import android.support.test.runner.AndroidJUnit4;

import com.flatstack.android.main_screen.MainActivity;

import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;

/**
* Created by ereminilya on 6/4/17.
*/

@RunWith(AndroidJUnit4.class)
public class MainScreenTest {

@Rule
public ScreenshotActivityRule<MainActivity> testRule =
new ScreenshotActivityRule<>(MainActivity.class);

@Test
public void whenAppLaunch_androidBaseVisible() throws Exception {
onView(allOf(withId(R.id.title), withText(R.string.app_name)))
.check(matches(isDisplayed()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.flatstack.android;

import android.app.Activity;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.espresso.Espresso;
import android.support.test.espresso.base.DefaultFailureHandler;
import android.support.test.rule.ActivityTestRule;

import com.squareup.spoon.Spoon;

import org.junit.runner.Description;
import org.junit.runners.model.Statement;

/**
* Created by ereminilya on 6/4/17.
*/

public class ScreenshotActivityRule<T extends Activity> extends ActivityTestRule<T> {

public ScreenshotActivityRule(Class<T> activityClass) {
super(activityClass);
}

@Override
public Statement apply(Statement base, Description description) {
String testClassName = description.getClassName();
String testMethodName = description.getMethodName();
Context context = InstrumentationRegistry.getTargetContext();
Espresso.setFailureHandler((error, matcher) -> {
Spoon.screenshot(getActivity(), "failure", testClassName, testMethodName);
new DefaultFailureHandler(context).handle(error, matcher);
});
return super.apply(base, description);
}

}
4 changes: 3 additions & 1 deletion app/src/main/res/layout/fragment_main.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
Expand All @@ -8,6 +9,7 @@
>

<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
Expand Down
7 changes: 0 additions & 7 deletions app/src/main/res/values-v19/themes.xml

This file was deleted.

4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
classpath 'me.tatarka:gradle-retrolambda:3.2.5' // use Java 8 lambdas on android
classpath('com.stanfy.spoon:spoon-gradle-plugin:1.2.2') {
exclude module: 'guava'
}
classpath 'com.google.guava:guava:17.0'
}
}

Expand Down
35 changes: 30 additions & 5 deletions circle.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,44 @@
machine:
environment:
ANDROID_HOME: /usr/local/android-sdk-linux
GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"'
java:
version: oraclejdk8
java:
version: oraclejdk8
environment:
TERM: "dumb"
ADB_INSTALL_TIMEOUT: 5000
GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"'

general:
artifacts:
- "/home/ubuntu/android-base/app/build/reports"
- "/home/ubuntu/android-base/app/build/spoon"

dependencies:
pre:
- chmod +x app/set_animation_permissions.sh
- echo y | android update sdk --no-ui --all --filter "tools,platform-tools,android-25,extra-google-m2repository"
- echo y | android update sdk --no-ui --all --filter "build-tools-25.0.1"
- echo y | android update sdk --no-ui --all --filter "extra-android-m2repository"

post:
# Create the android emulator
- echo n | android create avd -n test_android_17 -f -t android-17
# [HINT] Circle-CI already have built-in emulator (circleci-android22), but it's so heavy.
# Make a SD Card image file for the android emulator
- mksdcard -l e 128M sdcard.img

test:
pre:
- emulator -avd test_android_17 -no-audio -no-boot-anim -no-window -sdcard sdcard.img:
background: true
parallel: true
override:
- ./gradlew checkstyle lintProductionRelease testProductionReleaseUnitTest
- circle-android wait-for-boot
- sleep 20
- adb shell input keyevent 82
- adb shell settings put global window_animation_scale 0.0

- adb shell settings put global transition_animation_scale 0.0
- adb shell settings put global animator_duration_scale 0.0
- ./gradlew spoonProductionDebugAndroidTest

#deployment:
# production: # just a label; label names are completely up to you
Expand Down
13 changes: 6 additions & 7 deletions deps.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@ ext {
TARGET_SDK_VERSION : 25
]
supportDeps = [
appcompatV7 : "com.android.support:appcompat-v7:$versions.support",
recyclerView : "com.android.support:recyclerview-v7:$versions.support",
supportAnnotation: "com.android.support:support-annotations:$versions.support",
// design : "com.android.support:design:$versions.support",
appcompatV7 : "com.android.support:appcompat-v7:$versions.support",
recyclerView: "com.android.support:recyclerview-v7:$versions.support",
design : "com.android.support:design:$versions.support"
// gridLayout : "com.android.support:gridlayout-v7:$versions.support"
// cardView : "com.android.support:cardview-v7:$versions.support"
// palette : "com.android.support:palette-v7:$versions.support"
Expand All @@ -33,15 +32,15 @@ ext {
unitTests = [
supportAnnotation: "com.android.support:support-annotations:$versions.support",
junit : 'junit:junit:4.12',
robolectric : 'org.robolectric:robolectric:3.0',
assertj : 'com.squareup.assertj:assertj-android:1.0.0'
]
androidTests = [
espressoCore : "com.android.support.test.espresso:espresso-core:$versions.espressoVersion",
espressoContrib: "com.android.support.test.espresso:espresso-contrib:$versions.espressoVersion",
espressoIntents: "com.android.support.test.espresso:espresso-intents:$versions.espressoVersion",
testRunner : "com.android.support.test:runner:0.5",
testRules : "com.android.support.test:rules:0.5"
testRules : "com.android.support.test:rules:0.5",
spoon : 'com.squareup.spoon:spoon-client:1.6.4'
]

supportLibs = supportDeps.values()
Expand All @@ -50,4 +49,4 @@ ext {
rxJavaLibs = rxJava.values()
unitTestLibs = unitTests.values()
androidTestsLibs = androidTests.values() + supportLibs
}
}

0 comments on commit a07d701

Please sign in to comment.