Check whether Running the app or Testing UI
Now we can simply check this with one line of code for "UITesting".
[[[NSProcessInfo processInfo] arguments]
containsObject:@"-ui_testing"]
-ui_testing would appear only when testing the app.
How to check application state under swift UI Test
You can do this in Swift 4, using XCUIApplication.state
, which will give you information about the state of the app - whether it's in the foreground or background etc. however, it's not possible to find this information in Swift 3 and below. Essentially, UI testing in Swift 3 doesn't support leaving the app.
How to let the app know if it's running Unit tests in a pure Swift project?
Instead of checking if the tests are running to avoid side-effects, you could run the tests without the host app itself. Go to Project Settings -> select the test target -> General -> Testing -> Host Application -> select 'None'.
Just remember to include all files you need to run the tests, as well as libraries normally included by the Host app target.
How to hit a breakpoint in application while running UI test in iOS?
Select your test scheme and go to Edit Scheme...
Select 'Test' in the sidebar and in the 'Info' category check the 'Debug executable' option.
When you run the tests in that scheme, breakpoints in both the test target and the app under test will be hit.
Check if App is running in a Testing Environment
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!
How to detect if app is being built for device or simulator in Swift
Update 30/01/19
While this answer may work, the recommended solution for a static check (as clarified by several Apple engineers) is to define a custom compiler flag targeting iOS Simulators. For detailed instructions on how to do to it, see @mbelsky's answer.
Original answer
If you need a static check (e.g. not a runtime if/else) you can't detect the simulator directly, but you can detect iOS on a desktop architecture like follows
#if (arch(i386) || arch(x86_64)) && os(iOS)
...
#endif
After Swift 4.1 version
Latest use, now directly for all in one condition for all types of simulators need to apply only one condition -
#if targetEnvironment(simulator)
// your simulator code
#else
// your real device code
#endif
For more clarification, you can check Swift proposal SE-0190
For older version -
Clearly, this is false on a device, but it returns true for the iOS Simulator, as specified in the documentation:
The arch(i386) build configuration returns true when the code is compiled for the 32–bit iOS simulator.
If you are developing for a simulator other than iOS, you can simply vary the os
parameter: e.g.
Detect the watchOS simulator
#if (arch(i386) || arch(x86_64)) && os(watchOS)
...
#endif
Detect the tvOS simulator
#if (arch(i386) || arch(x86_64)) && os(tvOS)
...
#endif
Or, even, detect any simulator
#if (arch(i386) || arch(x86_64)) && (os(iOS) || os(watchOS) || os(tvOS))
...
#endif
If you instead are ok with a runtime check, you can inspect the TARGET_OS_SIMULATOR
variable (or TARGET_IPHONE_SIMULATOR
in iOS 8 and below), which is truthy on a simulator.
Please notice that this is different and slightly more limited than using a preprocessor flag. For instance you won't be able to use it in place where a if/else
is syntactically invalid (e.g. outside of functions scopes).
Say, for example, that you want to have different imports on the device and on the simulator. This is impossible with a dynamic check, whereas it's trivial with a static check.
#if (arch(i386) || arch(x86_64)) && os(iOS)
import Foo
#else
import Bar
#endif
Also, since the flag is replaced with a 0
or a 1
by the swift preprocessor, if you directly use it in a if/else
expression the compiler will raise a warning about unreachable code.
In order to work around this warning, see one of the other answers.
Related Topics
Swift Performseguewithidentifier Not Working
Swiftui: Navigationdestinationlink Deprecated
Swiftui Withanimation Completion Callback
Google Maps iOS Sdk, Getting Current Location of User
Uiimagepickercontroller Crashes App | Swift3, Xcode8
Firebase Fcm Silent Push Notifications for iOS
Uibutton Does Not Work When It in Uiscrollview
Why Is Our Monotouch App Breaking in the Garbage Collector? It Is Not Out of Memory
Https iOS with Self Signed Certificate
1St April Dates of 80S Failed to Parse in iOS 10.0
How to Fix Failed to Fetch Default Token Error
Facebook Sdk 3.1 for iOS - Runs on iOS6, But Crashes on iOS 5.X
Disabling Nslog for Production in Swift Project