Adds espresso testing for add_to_app/android_fullscreen (#323)

pull/373/head
Andrew Brogdon 4 years ago committed by GitHub
parent bff4d459f7
commit face0f564a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

3
.gitignore vendored

@ -67,6 +67,9 @@
# Web related
**/web/**/lib/generated_plugin_registrant.dart
# Service account files
svc-keyfile.json
# Exceptions to above rules.
!**/ios/**/default.mode1v3
!**/ios/**/default.mode2v3

@ -3,74 +3,95 @@ git:
jobs:
include:
- name: "iOS tests, stable channel"
os: osx
osx_image: xcode11.2
language: objective-c
script: ./tool/travis_ios_script.sh
env: FLUTTER_VERSION=stable
- name: iOS tests, stable channel
os: osx
osx_image: xcode11.2
language: objective-c
script: "./tool/travis_ios_script.sh"
env: FLUTTER_VERSION=stable
- name: "Android tests, stable channel"
os: linux
dist: trusty
language: android
android:
components:
- build-tools-28.0.3
- android-28
script: ./tool/travis_android_script.sh
env: FLUTTER_VERSION=stable
- name: Android tests, stable channel
os: linux
dist: trusty
language: android
android:
components:
- build-tools-28.0.3
- android-28
script: "./tool/travis_android_script.sh"
env: FLUTTER_VERSION=stable
- name: "Flutter tests, stable channel"
os: linux
dist: trusty
language: ruby
script: ./tool/travis_flutter_script.sh
env: FLUTTER_VERSION=stable
- name: Flutter tests, stable channel
os: linux
dist: trusty
language: ruby
script: "./tool/travis_flutter_script.sh"
env: FLUTTER_VERSION=stable
- name: "iOS tests, beta channel"
os: osx
osx_image: xcode11.2
language: objective-c
script: ./tool/travis_ios_script.sh
env: FLUTTER_VERSION=beta
- name: iOS tests, beta channel
os: osx
osx_image: xcode11.2
language: objective-c
script: "./tool/travis_ios_script.sh"
env: FLUTTER_VERSION=beta
- name: "Android tests, beta channel"
os: linux
dist: trusty
language: android
android:
components:
- build-tools-28.0.3
- android-28
script: ./tool/travis_android_script.sh
env: FLUTTER_VERSION=beta
- name: Android tests, beta channel
os: linux
dist: trusty
language: android
android:
components:
- build-tools-28.0.3
- android-28
script: "./tool/travis_android_script.sh"
env: FLUTTER_VERSION=beta
- name: "Flutter tests, beta channel"
os: linux
dist: trusty
language: ruby
script: ./tool/travis_flutter_script.sh
env: FLUTTER_VERSION=beta
- name: Flutter tests, beta channel
os: linux
dist: trusty
language: ruby
script: "./tool/travis_flutter_script.sh"
env: FLUTTER_VERSION=beta
allow_failures:
- env: FLUTTER_VERSION=beta
- env: FLUTTER_VERSION=beta
env:
global:
# Disabling this makes it easier to install our own copy of gcloud
- CLOUDSDK_CORE_DISABLE_PROMPTS=1
before_script:
- git clone https://github.com/flutter/flutter.git -b $FLUTTER_VERSION
- ./flutter/bin/flutter doctor
- chmod +x tool/travis_*_script.sh
- git clone https://github.com/flutter/flutter.git -b $FLUTTER_VERSION
- "./flutter/bin/flutter doctor"
- chmod +x tool/travis_*_script.sh
cache:
cocoapods: true
directories:
- $HOME/shared/.pub-cache
- "$HOME/shared/.pub-cache"
- "$HOME/google-cloud-sdk"
notifications:
email:
brogdon+github@gmail.com
email: brogdon+github@gmail.com
# Building master alone means that we don't run two builds for
# each pull request.
branches:
only: [master]
only:
- master
before_install:
# Decrypt credentials for Firebase Test Lab service account. This key will only
# decrypt properly when run from within the flutter/samples repo (not a PR from
# a fork, for example), so failure is expected in some cases. The Android test
# script is the only one that uses this value, and will account for a lack of
# credentials.
- openssl aes-256-cbc -K $encrypted_ccb0f43ba178_key -iv $encrypted_ccb0f43ba178_iv
-in svc-keyfile.json.enc -out svc-keyfile.json -d || rm svc-keyfile.json || true
- ls -la
# Install our own copy of gcloud. This is necessary because the default copy is
# so old it doesn't offer a firebase component.
- if [ ! -d "$HOME/google-cloud-sdk/bin" ]; then rm -rf "$HOME/google-cloud-sdk";
curl https://sdk.cloud.google.com | bash > /dev/null; fi
- source $HOME/google-cloud-sdk/path.bash.inc
- gcloud components update
- gcloud version

@ -13,6 +13,7 @@ android {
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
}
buildTypes {
release {
@ -26,13 +27,16 @@ android {
}
dependencies {
implementation 'androidx.multidex:multidex:2.0.1'
implementation project(':flutter')
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
androidTestImplementation project(':espresso')
androidTestImplementation "com.google.truth:truth:0.42"
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
api 'androidx.test:core:1.2.0'
}

@ -4,25 +4,68 @@
package dev.flutter.example.androidfullscreen
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.core.app.ActivityScenario
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.flutter.EspressoFlutter.onFlutterWidget
import androidx.test.espresso.flutter.action.FlutterActions.click
import androidx.test.espresso.flutter.assertion.FlutterAssertions.matches
import androidx.test.espresso.flutter.matcher.FlutterMatchers
import androidx.test.espresso.flutter.matcher.FlutterMatchers.withText
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
class MainActivityTest {
@Before
fun setUp() {
ActivityScenario.launch(MainActivity::class.java)
}
@Test
fun flutterTextUpdatesOnClick() {
// Launch Flutter module.
onView(withId(R.id.launch_button)).perform(androidx.test.espresso.action.ViewActions.click())
// Verify state is inited correctly.
onFlutterWidget(withText("Taps: 0"))
.check(matches(FlutterMatchers.isExisting()))
// Verify the increment button works.
onFlutterWidget(withText("Tap me!")).perform(click())
onFlutterWidget(withText("Taps: 1"))
.check(matches(FlutterMatchers.isExisting()))
}
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("dev.flutter.example.androidfullscreen", appContext.packageName)
fun nativeTextViewUpdatesOnClick() {
// Verify Android TextView is inited correctly.
onView(withId(R.id.counter_label)).check(
androidx.test.espresso.assertion.ViewAssertions.matches(
// TODO(redbrogdon): This should be a check for 0 rather than 1. Because our state
// management is hardcoded into the Application object, though, and that object is
// reused across tests, this test begins with a counter already incremented by the
// previous one. This situation can be corrected via DI or a number of other
// approaches.
androidx.test.espresso.matcher.ViewMatchers.withText("Current count: 1")
)
)
// Launch Flutter module.
onView(withId(R.id.launch_button)).perform(androidx.test.espresso.action.ViewActions.click())
// Increment count.
onFlutterWidget(withText("Tap me!")).perform(click())
// Exit Flutter module and verify that the Android TextView is updated correctly.
onFlutterWidget(withText("Exit this screen")).perform(click())
onView(withId(R.id.counter_label)).check(
androidx.test.espresso.assertion.ViewAssertions.matches(
// TODO(redbrogdon): s/2/1
androidx.test.espresso.matcher.ViewMatchers.withText("Current count: 2")
)
)
}
}

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dev.flutter.example.androidfullscreen">
<!-- Include Cleartext traffic for the espresso package -->
<application android:usesCleartextTraffic="true" />
</manifest>

@ -13,17 +13,15 @@
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="io.flutter.embedding.android.FlutterActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"
android:exported="true"
/>
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize" />
</application>
</manifest>
</manifest>

@ -4,7 +4,7 @@
package dev.flutter.example.androidfullscreen
import android.app.Application
import androidx.multidex.MultiDexApplication
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.FlutterEngineCache
import io.flutter.embedding.engine.dart.DartExecutor
@ -12,7 +12,7 @@ import io.flutter.plugin.common.MethodChannel
const val ENGINE_ID = "1"
class MyApplication : Application() {
class MyApplication : MultiDexApplication() {
var count = 0
private lateinit var channel: MethodChannel

@ -7,7 +7,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.1'
classpath 'com.android.tools.build:gradle:3.6.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

@ -1,6 +1,6 @@
#Tue Sep 17 09:33:13 PDT 2019
#Wed Mar 11 09:25:37 PDT 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip

@ -27,7 +27,6 @@ android {
dependencies {
implementation project(':flutter')
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.1.0'

@ -13,6 +13,7 @@ android {
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
}
buildTypes {
release {
@ -46,12 +47,14 @@ dependencies {
transitive = true
}
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.multidex:multidex:2.0.1'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
androidTestImplementation "com.google.truth:truth:0.42"
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
api 'androidx.test:core:1.2.0'
}

@ -4,7 +4,7 @@
package dev.flutter.example.androidusingprebuiltmodule
import android.app.Application
import androidx.multidex.MultiDexApplication
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.FlutterEngineCache
import io.flutter.embedding.engine.dart.DartExecutor
@ -12,7 +12,7 @@ import io.flutter.plugin.common.MethodChannel
const val ENGINE_ID = "1"
class MyApplication : Application() {
class MyApplication : MultiDexApplication() {
var count = 0
private lateinit var channel: MethodChannel

@ -57,16 +57,40 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
espresso:
dependency: "direct dev"
description:
name: espresso
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.1+2"
file:
dependency: transitive
description:
name: file
url: "https://pub.dartlang.org"
source: hosted
version: "5.1.0"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_driver:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
fuchsia_remote_debug_protocol:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
image:
dependency: transitive
description:
@ -74,6 +98,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.4"
intl:
dependency: transitive
description:
name: intl
url: "https://pub.dartlang.org"
source: hosted
version: "0.16.0"
json_rpc_2:
dependency: transitive
description:
name: json_rpc_2
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
matcher:
dependency: transitive
description:
@ -88,6 +126,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.8"
nested:
dependency: transitive
description:
name: nested
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.4"
path:
dependency: transitive
description:
@ -109,13 +154,34 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.0"
platform:
dependency: transitive
description:
name: platform
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.1"
process:
dependency: transitive
description:
name: process
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.12"
provider:
dependency: "direct main"
description:
name: provider
url: "https://pub.dartlang.org"
source: hosted
version: "3.2.0"
version: "4.0.2"
pub_semver:
dependency: transitive
description:
name: pub_semver
url: "https://pub.dartlang.org"
source: hosted
version: "1.4.2"
quiver:
dependency: transitive
description:
@ -184,6 +250,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.8"
vm_service_client:
dependency: transitive
description:
name: vm_service_client
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.6+2"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
xml:
dependency: transitive
description:
@ -193,3 +273,4 @@ packages:
version: "3.5.0"
sdks:
dart: ">=2.6.0-dev <3.0.0"
flutter: ">=1.12.1 <2.0.0"

@ -9,11 +9,14 @@ environment:
dependencies:
flutter:
sdk: flutter
provider: ^3.1.0
provider: ^4.0.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter_driver:
sdk: flutter
espresso: ^0.0.1+2
flutter:
uses-material-design: true

@ -1,14 +1,10 @@
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility that Flutter provides. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
// Copyright 2019 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_module/main.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:provider/provider.dart';
class MockCounterModel extends ChangeNotifier implements CounterModel {

@ -0,0 +1,13 @@
// Copyright 2020 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter_driver/driver_extension.dart';
import 'package:flutter_module/main.dart' as app;
// This alternate entrypoint is used for espresso testing. See
// https://pub.dev/packages/espresso for details.
void main() {
enableFlutterDriverExtension();
app.main();
}

Binary file not shown.

@ -53,4 +53,28 @@ do
popd
done
# If the credentials don't exist, this script isn't being run from within the
# flutter/samples repo. Rather than throw an error, allow the test to pass
# successfully.
if [ ! -f "svc-keyfile.json" ]
then
echo "Keyfile for Firebase Test Lab not found. Skipping integration tests."
exit 0
fi
# At this time, espresso tests only exist for android_fullscreen. These will
# eventually be rolled out to each Android project and included in the loop
# above.
echo "== Espresso testing 'android_fullscreen' on Flutter's ${FLUTTER_VERSION} channel =="
pushd "add_to_app/android_fullscreen"
./gradlew app:assembleAndroidTest
./gradlew app:assembleDebug -Ptarget=../flutter_module/test_driver/example.dart
gcloud auth activate-service-account --key-file=../../svc-keyfile.json
gcloud --quiet config set project test-lab-project-ccbec
gcloud firebase test android run --type instrumentation \
--app app/build/outputs/apk/debug/app-debug.apk \
--test app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk\
--timeout 5m
popd
echo "-- Success --"

Loading…
Cancel
Save