Check if App is running in a Testing Environment - flutter

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!

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')) { ... }

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.

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!

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.

Related

Avoid `print` calls in production code while using flutter [duplicate]

This question already has answers here:
Avoid `print` calls in production code. (Documentation)
(6 answers)
Closed 4 months ago.
My code keeps giving me a warning...
Avoid print calls in production code.
How do I resolve it?
Use debugPrint instead. Just know that debugPrint can only take a String? so you might need to use toString() or correctly format the data you are trying to display.
import 'package:flutter/foundation.dart';
debugPrint('This is a debugPrint');
You can use print statement in only debug mode when app run in release mode print statement avoid. Write print using below both method:-
import 'package:flutter/foundation.dart';
if (kDebugMode) {
print("Hello");
}
OR
debugPrint('This is a debugPrint');
Print() is a function which helps you in debugging process, it's not a good idea to use it unconditionally, you may leak some sensitive information in Release version of your app
It's better to make sure that you're using this function in Debug mode
There are some options:
Using debugPrint() instead of print()
debugPrint('some debug info ...')
Using assert() function which will be called in Debug mode only
assert(() {
print('some debug info ...');
return true;
});
Checking Debug Mode before using print()
import 'package:flutter/foundation.dart';
...
if (kDebugMode) {
print('some debug info ...');
}
If you're sure that you have enough control on using print() function, you can ignore that warning by using ignore directive :
Use this on top of the file : // ignore_for_file: avoid_print
Or add this line before print() function
// ignore: avoid_print
print('some debug info ...');
To ignore that warning for the whole project, you can add this lines to analysis_options.yaml file of the project :
include: package:flutter_lints/flutter.yaml
linter:
rules:
avoid_print: false

GLib.NetworkMonitor incorrect initial network availability in Flatpak app

I'm packaging a Flatpak application that checks the network availability on startup. Since switching to Flatpak packaging I've noticed that the GLib.NetworkMonitor is initially reporting no network availability, but very shortly thereafter the network-changed signal is emitted to indicate that there is a network connection.
This appears to be Flatpak related - maybe due to the sandbox not having a connection initially?
I don't see this behavior documented anywhere, so I don't want to assume that there will always be a signal emitted initially.
public class MyApplication : Gtk.Application {
private bool is_network_available;
construct {
// After the application is fully started, UI initialized, etc. this gets
// triggered and reports change to `true`
network_monitor.network_changed.connect (() => {
debug ("Network availability changed: %s", network_monitor.get_network_available ().to_string ());
});
}
protected override void activate () {
// Check the initial state of the network connection
is_network_available = network_monitor.get_network_available ();
debug (is_network_available); // Reports false
}
}
Is this expected for Flatpak packaged applications? Is there a more reliable method to perform this check on startup?
It’s a bug in GLib: https://gitlab.gnome.org/GNOME/glib/-/issues/1718
For the moment you will have to work around it some way. Assuming that a signal will always be emitted on startup is not guaranteed behaviour, so if you use that as a workaround you should make it conditional on the GLib version, and disable your workaround code if built against a version of GLib which is fixed. (No versions of GLib are fixed yet, though.)

Standard Input and Output operations in flutter

What is the approach for using standard i/o in flutter? I've tried the following code but there is no render and build gets stuck.
import 'dart:io';
void main() {
stdout.writeln("Enter value");
String str = stdin.readLineSync();
// user inputs value
print(str);
}
The documentation says
> To read text synchronously from the command line (the program blocks
> waiting for user to type information):
String inputText = stdin.readLineSync();
But how to appropriately input values? Because flutter run doesn't let me input values.
Actually, what you're doing doesn't require you to use Flutter. You can run it using Dart. The thing is that Flutter is meant for application development for Android, iOS, Web and other such platforms. It isn't created for such applications that you desire.

How to stop automatically closing browser when writing protractor test cases

I am new to writing test cases using protractor for non angular application. I wrote a sample test case.Here the browser closes automatically after running test case.How can I prevent this. Here is my code
var submitBtnElm = $('input[data-behavior=saveContribution]');
it('Should Search', function() {
browser.driver.get('http://localhost/enrollments/osda1.html');
browser.driver.findElement(by.id('contributePercentValue')).sendKeys(50);
submitBtnElm.click().then(function() {
});
});
I was also struggling with a similar issue where i had a test case flow where we were interacting with multiple application and when using Protractor the browser was closing after executing one conf.js file. Now when I looked into the previous response it was like adding delay which depends on how quick your next action i performed or it was hit or miss case. Even if we think from debugging perspective most of the user would be performing overnight runs and they would want to have browser active for couple of hours before they analyze the issue. So I started looking into the protractor base code and came across a generic solution which can circumvent this issue, independent of any browser. Currently the solution is specific to requirement that browser should not close after one conf.js file is executed, then could be improved if someone could add a config parameter asking the user whether they want to close the browser after their run.
The browser could be reused for future conf.js file run by using tag --seleniumSessionId in command line.
Solution:
Go to ..\AppData\Roaming\npm\node_modules\protractor\built where your
protractor is installed.
Open driverProvider.js file and go to function quitDriver
Replace return driver.quit() by return 0
As far as my current usage there seems to be no side effect of the code change, will update if I came across any other issue due to this change. Snapshot of code snippet below.
Thanks
Gleeson
Snapshot of code snippet:
Add browser.pause() at the end of your it function. Within the function itself.
I found Gleeson's solution is working, and that really helped me. The solution was...
Go to %APPDATA%Roaming\npm\node_modules\protractor\built\driverProviders\
Find driverProviders.js
Open it in notepad or any other text editor
Find and Replace return driver.Quit() to return 0
Save the file
Restart your tests after that.
I am using
node v8.12.0
npm v6.4.1
protractor v5.4.1
This solution will work, only if you installed npm or protractor globally; if you have installed your npm or protractor locally (in your folder) then, you have to go to your local protractor folder and do the same.
I suggest you to use browser.driver.sleep(500); before your click operation.
See this.
browser.driver.sleep(500);
element(by.css('your button')).click();
browser.driver.sleep(500);
Add a callback function in It block and the browser window doesn't close until you call it.
So perform the action that you need and place the callback at your convenience
var submitBtnElm = $('input[data-behavior=saveContribution]');
it('Should Search', function(callback) {
browser.driver.get('http://localhost/enrollments/osda1.html');
browser.driver.findElement(by.id('contributePercentValue')).sendKeys(50);
submitBtnElm.click().then(function() {
// Have all the logic you need
// Then invoke callback
callback();
});
});
The best way to make browser NOT to close for some time, Use browser.wait(). Inside the wait function write logic for checking either visibilityOf() or invisibilityOf() of an element, which is not visible or it will take time to become invisible on UI. In this case wait() keep on checking the logic until either condition met or timeout reached. You can increase the timeout if you want browser visible more time.
var EC=protractor.ExpectedConditions;
var submitBtnElm = $('input[data-behavior=saveContribution]');
it('Should Search', function() {
browser.driver.get('http://localhost/enrollments/osda1.html');
browser.driver.findElement(by.id('contributePercentValue')).sendKeys(50);
submitBtnElm.click().then(function() {
browser.wait(function(){
EC.invisibilityOf(submitBtnElm).call().then(function(isPresent){
if(isPresent){
return true;
}
});
},20000,'error message');
});
});
I'm sure there is a change triggered on your page by the button click. It might be something as subtle as a class change on an element or as obvious as a <p></p> element with the text "Saved" displayed. What I would do is, after the test, explicitly wait for this change.
[...]
return protractor.browser.wait(function() {
return element(by.cssContainingText('p', 'Saved')).isPresent();
}, 10000);
You could add such a wait mechanism to the afterEach() method of your spec file, so that your tests are separated even without the Protractor Angular implicit waits.
var submitBtnElm = $('input[data-behavior=saveContribution]');
it('Should Search', function() {
browser.driver.get('http://localhost/enrollments/osda1.html');
browser.driver.findElement(by.id('contributePercentValue')).sendKeys(50);
submitBtnElm.click().then(function() {
});
browser.pause(); // it should leave browser alive after test
});
browser.pause() should leave browser alive until you let it go.
#Edit Another approach is to set browser.ignoreSynchronization = true before browser.get(...). Protractor wouldn't wait for Angular loaded and you could use usual element(...) syntax.
Protractor will close browsers, that it created, so an approach that I am using is to start the browser via the webdriver-reuse-session npm package.
DISCLAIMER: I am the author of this package
It is a new package, so let me know if it solves your problem. I am using it with great success.

Inconsistent output to Eclipse Console View

I am invoking a compiler command but the compiler messages are not getting displayed in the Eclipse Console View consistently.
I have my launch() method implemented the same way as first code block of
this question; I have the command-line string setup which I use to call DebugPlugin.exec() method. However, unlike the the author of the question above, my output Eclipse console is very inconsistent. T
There is no activity in the console when I invoke the command and the console continues to display the "No console to display at this time." But after invoking the command numerous time and activating different consoles from the drop-down menu, the console occasionally does become active and message is displayed.
I am confused with how the eclipse is behaving and not sure how to resolve this issue. Any comment and/or recommendation would be appreciated.
Thanks!!
--
EDIT
To add some more info, running the external process using External Tools works fine. I add the compiler process c:\path\myprocess.exe in Locations field and the file to compile in the Arguments field within the External Tools Configuration window. When I run it, all the output is displayed fine. It just won't display when I run it programmatically through LaunchConfigurationDelegate class.
Maybe try bringing the console to front programmatically see if it helps:
* Bring the console to front.
*/
public static void showConsole() {
Display.getDefault().asyncExec(new Runnable() {
#Override
public void run() {
IWorkbenchWindow window = CUIPlugin.getActiveWorkbenchWindow();
if (window != null) {
IWorkbenchPage page = window.getActivePage();
if (page != null) {
IViewPart consoleView =
page.findView(IConsoleConstants.ID_CONSOLE_VIEW);
if (consoleView == null) {
IWorkbenchPart activePart = page.getActivePart();
try {
consoleView =
page.showView(IConsoleConstants.ID_CONSOLE_VIEW);
} catch (PartInitException pie) {
CUIPlugin.log(pie);
}
// restore focus stolen by the creation of the
// console
page.activate(activePart);
} else {
boolean bringToTop = true;
if (bringToTop) {
page.bringToTop(consoleView);
}
}
}
}
}
});
}
Finally got it to work. The main change I've made is having my MyLaunchConfigurationDelegate extend LaunchConfigurationDelegate instead of just implementing ILaunchConfigurationDelegate. When observed through the debugger, the launch() method went through similar code path as external process that was launched via External Tools when MyLaunchConfigurationDelegate extended LaunchConfigurationDelegate.
I guess it was lack of information on my part but I wasn't sure which part of the code was more important to share.
Another piece of code that was removed was:
IProcess dbgProcess = DebugPlugin.newProcess(launch, compilerProcess, "XVR Compiler", processAttributes);
...
launch.removeProcess(dbgProcess);
I've added it while attempting different approach in debugging this issue and it actually caused more issues by removing the debugProcess before it has chance to display output to the console.