Commit 5978698

derdilla <82763757+NobodyForNothing@users.noreply.github.com>
2024-06-11 12:10:58
implement integration testing
Signed-off-by: derdilla <82763757+NobodyForNothing@users.noreply.github.com>
1 parent 330b920
Changed files (8)
app
android
app
src
androidTest
java
com
derdilla
blood_pressure_app
integration_test
test_driver
docs
app/android/app/src/androidTest/java/com/derdilla/blood_pressure_app/MainActivityTest.java
@@ -0,0 +1,12 @@
+package com.example.myapp;
+
+import androidx.test.rule.ActivityTestRule;
+import dev.flutter.plugins.integration_test.FlutterTestRunner;
+import org.junit.Rule;
+import org.junit.runner.RunWith;
+
+@RunWith(FlutterTestRunner.class)
+public class MainActivityTest {
+    @Rule
+    public ActivityTestRule<MainActivity> rule = new ActivityTestRule<>(MainActivity.class, true, false);
+}
\ No newline at end of file
app/android/app/build.gradle
@@ -51,6 +51,7 @@ android {
         targetSdkVersion = flutter.targetSdkVersion
         versionCode = flutterVersionCode.toInteger()
         versionName = flutterVersionName
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
     }
     signingConfigs {
        release {
@@ -93,4 +94,10 @@ flutter {
     source '../..'
 }
 
-dependencies { }
+dependencies {
+    testImplementation 'junit:junit:4.12'
+
+    // https://developer.android.com/jetpack/androidx/releases/test/#1.2.0
+    androidTestImplementation 'androidx.test:runner:1.2.0'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
+}
app/integration_test/add_measurement_test.dart
@@ -0,0 +1,55 @@
+import 'package:blood_pressure_app/components/dialoges/add_measurement_dialoge.dart';
+import 'package:blood_pressure_app/components/measurement_list/measurement_list_entry.dart';
+import 'package:blood_pressure_app/main.dart' as app;
+import 'package:flutter/material.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:integration_test/integration_test.dart';
+
+void main() {
+  final IntegrationTestWidgetsFlutterBinding binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+
+  testWidgets('Can enter value only measurements', (WidgetTester tester) async {
+    final localizations = await AppLocalizations.delegate.load(const Locale('en'));
+    app.main();
+    await tester.pumpAndSettle();
+    expect(find.byType(AddEntryDialoge), findsNothing);
+    expect(find.byType(MeasurementListRow), findsNothing);
+
+    expect(find.byIcon(Icons.add), findsOneWidget);
+    await tester.tap(find.byIcon(Icons.add));
+    await tester.pumpAndSettle();
+    expect(find.byType(AddEntryDialoge), findsOneWidget);
+
+    await tester.enterText(find.byType(TextFormField).at(0), '123'); // sys
+    await tester.enterText(find.byType(TextFormField).at(1), '67'); // dia
+    await tester.enterText(find.byType(TextFormField).at(2), '56'); // pul
+    
+    await tester.tap(find.text(localizations.btnSave));
+    await tester.pumpAndSettle();
+    expect(find.byType(AddEntryDialoge), findsNothing);
+
+    // Gets up to 5s to load from fs.
+    int retries = 10;
+    while(find.text(localizations.loading).hasFound && retries >= 0) {
+      retries--;
+      await tester.pump(Duration(milliseconds: 500));
+    }
+    await tester.pump();
+
+    expect(find.byType(MeasurementListRow), findsOneWidget);
+    expect(find.descendant(
+      of: find.byType(MeasurementListRow),
+      matching: find.text('123'),
+    ), findsOneWidget,);
+    expect(find.descendant(
+      of: find.byType(MeasurementListRow),
+      matching: find.text('67'),
+    ), findsOneWidget,);
+    expect(find.descendant(
+      of: find.byType(MeasurementListRow),
+      matching: find.text('56'),
+    ), findsOneWidget,);
+
+  });
+}
app/test_driver/integration_test.dart
@@ -0,0 +1,3 @@
+import 'package:integration_test/integration_test_driver.dart';
+
+Future<void> main() => integrationDriver();
\ No newline at end of file
app/.gitignore
@@ -1,4 +1,5 @@
 # Miscellaneous
+*.mocks.dart
 *.class
 *.log
 *.pyc
app/pubspec.lock
@@ -230,6 +230,11 @@ packages:
     description: flutter
     source: sdk
     version: "0.0.0"
+  flutter_driver:
+    dependency: transitive
+    description: flutter
+    source: sdk
+    version: "0.0.0"
   flutter_lints:
     dependency: "direct dev"
     description:
@@ -285,6 +290,11 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.4.1"
+  fuchsia_remote_debug_protocol:
+    dependency: transitive
+    description: flutter
+    source: sdk
+    version: "0.0.0"
   function_tree:
     dependency: "direct main"
     description:
@@ -332,6 +342,11 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "4.1.7"
+  integration_test:
+    dependency: "direct dev"
+    description: flutter
+    source: sdk
+    version: "0.0.0"
   intl:
     dependency: "direct main"
     description:
@@ -368,18 +383,18 @@ packages:
     dependency: transitive
     description:
       name: leak_tracker
-      sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
+      sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
       url: "https://pub.dev"
     source: hosted
-    version: "10.0.4"
+    version: "10.0.5"
   leak_tracker_flutter_testing:
     dependency: transitive
     description:
       name: leak_tracker_flutter_testing
-      sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
+      sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
       url: "https://pub.dev"
     source: hosted
-    version: "3.0.3"
+    version: "3.0.5"
   leak_tracker_testing:
     dependency: transitive
     description:
@@ -424,18 +439,18 @@ packages:
     dependency: transitive
     description:
       name: material_color_utilities
-      sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
+      sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
       url: "https://pub.dev"
     source: hosted
-    version: "0.8.0"
+    version: "0.11.1"
   meta:
     dependency: transitive
     description:
       name: meta
-      sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
+      sha256: "25dfcaf170a0190f47ca6355bdd4552cb8924b430512ff0cafb8db9bd41fe33b"
       url: "https://pub.dev"
     source: hosted
-    version: "1.12.0"
+    version: "1.14.0"
   mockito:
     dependency: "direct dev"
     description:
@@ -548,6 +563,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.1.8"
+  process:
+    dependency: transitive
+    description:
+      name: process
+      sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32"
+      url: "https://pub.dev"
+    source: hosted
+    version: "5.0.2"
   provider:
     dependency: "direct main"
     description:
@@ -721,6 +744,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.2.0"
+  sync_http:
+    dependency: transitive
+    description:
+      name: sync_http
+      sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961"
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.3.1"
   synchronized:
     dependency: transitive
     description:
@@ -741,10 +772,10 @@ packages:
     dependency: transitive
     description:
       name: test_api
-      sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
+      sha256: "2419f20b0c8677b2d67c8ac4d1ac7372d862dc6c460cdbb052b40155408cd794"
       url: "https://pub.dev"
     source: hosted
-    version: "0.7.0"
+    version: "0.7.1"
   translations_cleaner:
     dependency: "direct dev"
     description:
@@ -837,10 +868,10 @@ packages:
     dependency: transitive
     description:
       name: vm_service
-      sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
+      sha256: "7475cb4dd713d57b6f7464c0e13f06da0d535d8b2067e188962a59bac2cf280b"
       url: "https://pub.dev"
     source: hosted
-    version: "14.2.1"
+    version: "14.2.2"
   watcher:
     dependency: transitive
     description:
@@ -857,6 +888,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "0.5.1"
+  webdriver:
+    dependency: transitive
+    description:
+      name: webdriver
+      sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e"
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.0.3"
   win32:
     dependency: transitive
     description:
app/pubspec.yaml
@@ -38,6 +38,8 @@ dependencies:
   fluttertoast: ^8.2.4
 
 dev_dependencies:
+  integration_test:
+    sdk: flutter
   file: any
   flutter_test:
     sdk: flutter
docs/testing.md
@@ -0,0 +1,26 @@
+# Testing
+
+Testing means catching bugs early and automated testing has already prevented 
+multiple bugs from getting reintroduced. Therefor the goal is to have the 
+entire codebase covered by extensive tests.
+
+#### Running unit tests
+
+```bash
+flutter test
+```
+
+#### Running integration tests
+
+To run integration tests an android emulator needs to be running.
+
+```bash
+flutter drive \
+  --driver=test_driver/integration_test.dart \
+  --target=integration_test/<testName>.dart \
+  --browser-name android-chrome --android-emulator \
+  --flavor github
+```
+
+To ues the emulator `--browser-name android-chrome --android-emulator` is 
+required. `--flavor github` is needed for the driver to find the apk.