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

Setup patrol integration tests #2196

Merged
merged 10 commits into from
Jan 13, 2025
84 changes: 84 additions & 0 deletions .github/workflows/integration-tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
on:
pull_request:
hoangdat marked this conversation as resolved.
Show resolved Hide resolved

name: Integration

jobs:
integration_test:
name: Integration Test
runs-on: ubuntu-latest
permissions:
id-token: write
contents: write
actions: write
checks: write
pull-requests: write

env:
USERNAME: ${{ secrets.USERNAME }}
PASSWORD: ${{ secrets.PASSWORD }}
SERVER_URL: ${{ secrets.SERVER_URL }}

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v2
with:
project_id: ${{ secrets.GOOGLE_CLOUD_PROJECT_ID }}
workload_identity_provider: ${{ secrets.GOOGLE_CLOUD_WORKLOAD_IDENTITY_PROVIDER_ID }}
service_account: ${{ secrets.GOOGLE_CLOUD_SERVICE_ACCOUNT }}

- name: Setup Cloud SDK
uses: google-github-actions/setup-gcloud@v2

- name: Setup flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.24.0"
hoangdat marked this conversation as resolved.
Show resolved Hide resolved
channel: "stable"
cache: true
cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:-${{ hashFiles('**/pubspec.lock') }}"

- name: Set up Java
uses: actions/setup-java@v4
with:
java-version: 17
hoangdat marked this conversation as resolved.
Show resolved Hide resolved
distribution: "temurin"

- uses: webfactory/[email protected]
with:
ssh-private-key: ${{ secrets.SSH_KEY }}
hoangdat marked this conversation as resolved.
Show resolved Hide resolved

- name: setup project
run:
flutter pub get && flutter pub run build_runner build --delete-conflicting-outputs

- name: Run Patrol Tests
shell: bash

env:
USERNAME: ${{ secrets.USERNAME }}
PASSWORD: ${{ secrets.PASSWORD }}
SERVER_URL: ${{ secrets.SERVER_URL }}
run: |

dart pub global activate patrol_cli

flutter build apk --config-only

patrol build android \
-v \
--dart-define=USERNAME="$USERNAME" \
--dart-define=SERVER_URL="$SERVER_URL" \
--dart-define=PASSWORD="$PASSWORD"

gcloud firebase test android run \
--type instrumentation \
--app build/app/outputs/apk/debug/app-debug.apk \
--test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk \
--device model=MediumPhone.arm,version=34 \
--timeout 5m \
--use-orchestrator \
--environment-variables clearPackageData=true
6 changes: 6 additions & 0 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ android {
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
testInstrumentationRunner "pl.leancode.patrol.PatrolJUnitRunner"
testInstrumentationRunnerArguments clearPackageData: "true"
hoangdat marked this conversation as resolved.
Show resolved Hide resolved
}

signingConfigs {
Expand All @@ -75,6 +77,9 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
testOptions {
execution "ANDROIDX_TEST_ORCHESTRATOR"
}
}

flutter {
Expand All @@ -88,6 +93,7 @@ dependencies {
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
implementation 'androidx.multidex:multidex:2.0.1'
androidTestUtil "androidx.test:orchestrator:1.5.1"
}

apply plugin: 'com.google.gms.google-services'
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package app.twake.android.chat;

import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import pl.leancode.patrol.PatrolJUnitRunner;

@RunWith(Parameterized.class)
public class MainActivityTest {
@Parameters(name = "{0}")
public static Object[] testCases() {
PatrolJUnitRunner instrumentation = (PatrolJUnitRunner) InstrumentationRegistry.getInstrumentation();
// replace "MainActivity.class" with "io.flutter.embedding.android.FlutterActivity.class"
// if in AndroidManifest.xml in manifest/application/activity you have
// android:name="io.flutter.embedding.android.FlutterActivity"
instrumentation.setUp(MainActivity.class);
instrumentation.waitForPatrolAppService();
return instrumentation.listDartTests();
}

public MainActivityTest(String dartTestName) {
this.dartTestName = dartTestName;
}

private final String dartTestName;

@Test
public void runDartTest() {
PatrolJUnitRunner instrumentation = (PatrolJUnitRunner) InstrumentationRegistry.getInstrumentation();
instrumentation.runDartTest(dartTestName);
}
}
34 changes: 34 additions & 0 deletions docs/adr/0025-add-patrol-integration-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# 25. Add patrol integration tests

Date: 2024-12-24

## Status

**Accepted**

## Context

- The need for integration tests to handle real scenarios
- The need to handle interactions with native views in tests such as notification popups or webviews
- Mocking matrix's behaviour using mockito causes a lot of unexpected issues

hoangdat marked this conversation as resolved.
Show resolved Hide resolved
## Decision

- Add integration tests using Patrol

### Why Patrol?

- Native Interaction: Patrol offers reliable tools for interacting with native views such as
notification popups, platform alerts, or webviews—functionality that can otherwise be cumbersome
with basic Flutter integration tests.
- Reduced Unpredictability: Since Patrol focuses on real-device or simulator-based tests, it helps
reduce the unpredictability that can arise from heavy mocking with tools like Mockito.
## Consequences

- Setup patrol locally:
- Run `dart pub global activate patrol_cli` to enable Patrol CLI
- Run tests locally:
- to run tests we use `patrol test -t path/to/test --dart-define=arg1='value' `
- to run tests in dev mode this will enable hot restarting the tests we
use : `patrol develop -t path/to/test --dart-define=arg1='value' `
arguments are passed for each test using `dart-define` as shown above
193 changes: 0 additions & 193 deletions integration_test/app_test.dart

This file was deleted.

15 changes: 15 additions & 0 deletions integration_test/base/base_scenario.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:patrol/patrol.dart';

abstract class BaseScenario {
final PatrolIntegrationTester $;

const BaseScenario(this.$);

Future<void> execute();

Future<void> expectViewVisible(PatrolFinder patrolFinder) async {
await $.waitUntilVisible(patrolFinder);
expect(patrolFinder, findsWidgets);
}
}
Loading
Loading