11

was just wondering if I can determine if my app currently runs in a Testing environment. Reason is that I am running automated screenshots and want to hide/modify parts of my App only when running that UI Test.

For example I'd like to skip registering for push notifications to avoid that iOS Popup at launch.

I'm searching for something like

if (kTestingMode) { ... } 

I know that we do have a driver that basically launches the app and then connects. Guess the App actually does not even know if it is running in Testmode or not. But maybe someone knows an answer.

Thanks!

Robin Reiter
  • 2,281
  • 15
  • 24

4 Answers4

23

Some answers aim to detect if you are in debug mode. The question was about how to detect if you are in a test environment, not if you are in debug mode. In fact, when you run a test, you are in debug mode, but you can run an app in debug mode even without running a test.

In order to properly detect if you are running a test, you can check for the presence of the key FLUTTER_TEST in Platform.environment.

import 'dart:io' show Platform;

if (Platform.environment.containsKey('FLUTTER_TEST')) { ... } 
Luca Venturini
  • 352
  • 3
  • 11
9

Another solutions is to use --dart-define build environment variable. It is available from Flutter 1.17

Example of running tests with --dart-define:

flutter drive --dart-define=testing_mode=true --target=test_driver/main.dart

In code you can check this environment variable with the following code:

const bool.fromEnvironment('testing_mode', defaultValue: false)

Not using const can lead to the variable not being read on mobile, see here.

OnkelZukunft
  • 172
  • 4
  • 8
  • interesting , with `const` and without `const` really make a different, no wonder why – zap Sep 12 '21 at 13:36
  • This is a great solution if you are running integration tests with flutter drive command. But it doesn't for if you want to launch tests through Firebase test lab for example – Leo Jul 06 '22 at 10:38
3

Okay I just found a solution my myself. What I did is introduce a global variable which I will set in my main driver.

First I created a new globals.dart file:

library my_prj.globals;

bool testingActive = false;

Then, in my test_driver/main.dart file I import that and set the testingActive variable to true

import '../lib/globals.dart' as globals;

..

void main() {
  final DataHandler handler = (_) async {
    final response = {};
    return Future.value(c.jsonEncode(response));
  };
  // Enable integration testing with the Flutter Driver extension.
  // See https://flutter.io/testing/ for more info.
  enableFlutterDriverExtension(handler: handler);

  globals.testingActive = true;

  WidgetsApp.debugAllowBannerOverride = false; // remove debug banner
  runApp(App());
} 

Now, I do have this global variable everywhere in my Flutter App by simply importing and checking.

e.g. in my app.dart

import '../globals.dart' as globals;

...

if (globals.testingActive) {
   print("We are in a testing environment!");
}

Is there a better solution? Guess this works just fine!

Robin Reiter
  • 2,281
  • 15
  • 24
  • Your answer is good, but I guess you will be benefited with the answer which I gave. Let me know how did you find it. – Alok Oct 16 '19 at 07:17
  • Only this way worked for me when I was launching integration test in Firebase test lab. – Leo Jul 06 '22 at 10:37
3

I have another solution for this, may be this would work out as well for you. Let me know if that goes well with you or not.

1. So, I am suggesting to use assert(), as it only runs on debug mode.

Here is an example for navigator:

assert(() {
  if (navigator == null && !nullOk) {
    throw new FlutterError(
      'Error!!!'
    );
  }
  return true;
}());

Note: In particular the () at the end of the call - assert can only operate on a boolean, so just passing in a function doesn't work.

2. Other way is to use kReleaseMode from package package:flutter/foundation.dart

kReleaseMode is a constant. Therefore the compiler is correctly able to remove unused code, and we can safely do:

import 'package:flutter/foundation.dart' as Foundation;

//is release mode
if (Foundation.kReleaseMode) {
  print('release mode');
} else {
  print('debug mode');
}

3. This is the snippet which will be helpful for you:

bool get isInDebugMode {
  bool inDebugMode = false;
  assert(inDebugMode = true);
  return inDebugMode;
}

If not you can configure your IDE to launch a different main.dart in debug mode where you can set a boolean.

Alok
  • 8,452
  • 13
  • 55
  • 93
  • 1
    Thanks for your answer. But I do not think this is a good solution. I do run my code very often in debug mode (without a test running). If I would implement your solution my code would behave in debug mode like it would in testing mode. For example I'd like to use the "if testing" check to automatically login a user. Or to hide or show certain elements that are actually not there in the app. If I simply check for debug I'd always have these changes even though I am not actually running a test. – Robin Reiter Oct 16 '19 at 07:21
  • Your call @RobinReiter. – Alok Oct 16 '19 at 07:25