Nosuchelement exception when activity is visible - appium

Having this strange situation. My code is resulting in no such element exception in scenario 1, but in scenario 2 it’s working.
Note: This issue is only on Android, on iOS tests not having issue on login.
Scenario 1: [FAIL]
The activity loads,
Using webdriver wait for checking if the element is clickable,
Timeout after the time limit 20 - 30 second.
Debugging:
I am waiting for app to complete login on the emulator and then performed step 2. Still facing no such element exception despite of activity completely being loaded.
Scenario 2: [PASS] pusing to background
The activity loads,
Pushing app to background and bringing it back,
Using webdriver wait for checking if the element is clickable,
Element is recognized, going ahead with remaining tests.
Operating sytem:
Android - Nexus 6 emulator on Android 8.0
POM:
<testng.version>6.14.3</testng.version>
<appium.java.version>6.1.0</appium.java.version>
<apachepoi.version>3.17</apachepoi.version>
<selenium.version>3.14.0</selenium.version>
<allure.version>1.4.0.RC4</allure.version>
<aspectj.version>1.8.11</aspectj.version>
<firefox.version>3.14.0</firefox.version>
<sauceondemand.version>2.14</sauceondemand.version>
<sauceclientfactory.version>2.14</sauceclientfactory.version>
<saucetestng.version>2.1.23</saucetestng.version>
<log4j.version>1.2.17</log4j.version>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>

Related

Why is my "AppLifecycleState" "resumed" twice?

I am using call_number plugin to make a call from my app. I am tracking the AppLifecycleState to take actions. This is the order in which states are changing-
AppLifecycleState.inactive
AppLifecycleState.resumed
AppLifecycleState.inactive
AppLifecycleState.paused
AppLifecycleState.inactive
AppLifecycleState.resumed
Last 4-I understand the flow, but I am unable to understand why is state changing to resumed the first time. According to the documentation - "The application is visible and responding to user input." when it is in resumed state but when I press button, call is directly placed.
I wonder if it is being done by the plugin in background but I don't see my app coming up even for a split second.

How to restart Android app (/app state) within Espresso test?

I'm testing login page - specifically "Autologin" checkbox, so that user being logged-in once, will be automatically logged-in upon reopening the app (by default user should login from scratch).
How can I simulate this behaviour? Is restarting an app is the only way? Can I reset an app somehow to initial screen (as if being restarted), but so that userdata/cookies should be kept?
My initial solution was to close the app by Espresso.pressBackUnconditionally() (it is similar to Espresso.pressBack() but will not throw an exception when Espresso navigates outside the application or process under test) and to launch activity again: activityRule.launchActivity(null).
However, at the end we came up with more sophisticated solution of relaunching activity within instrumentation:
with(activityRule) {
finishActivity()
launchActivity(null)
}
Activity test rule is deprecated.
You can do this using the following code in Kotlin
activityScenarioRule.scenario.close()
ActivityScenario.launch(YourActivity::class.java, null)

How to check application state under swift UI Test

Some background
I am currently writing a UI Test for a settings pane, and click on buttons to enable certain permissions such as push notifications and location services.
However, if the alert for the permission has been displayed before (regardless of the user allowing or denying access to the permission), the alert will not display again, and will just take the user to the settings app. Unfortunately, these settings do not reset, meaning the first time I run the UI tests, alerts will show; and on all subsequent UI test runs, the buttons will take me to the settings app unless I reset the device before the tests begin.
My issue
Thus, my test needs to know if the app went into the background, and attempt to foreground it to continue the testing:
if app.state == background {
foregroundApp()
}
// continue with other tests
Is there any way to determine if the app is in the background?
What I tried
I researched methods to determine the state of the application (running/background/etc) from a UI test, and was not able to find much. I tried to check whether certain elements exist:
if (app.navigationBars.element.exists) ...
but this gives me runtime errors[1] if the user is taken to the settings page because the app under test is in the background, and the test cannot lookup the navigationBars (or other elements).
I tried using some of the methods from Facebook's private headers for XCUIApplication() and XCUIElement().
XCUIApplication().state always returns 3 no matter what state the app is currently in, and any attempts to call XCUIApplication().resolve() to foreground the app give me the same errors as before[1]
I tried to rewrite the logic to foreground the app before resuming the tests, but methods such as XCUIApplication().launch() kill the app before restarting, which I cannot do. Only siri service seems to work for me, but I cannot access the siri service through the corporate proxy, and modifying proxy permissions is not possible.
Is there any other way to check the app state?
Errors
[1] This error is printed every time I try to do something involving state. I do not call snapshotView anywhere, and thus the suggestion to use afterScreenUpdates is useless.
Failure to get snapshot within 15.0s
Cannot snapshot view (<UIKeyboardImpl: 0x7febcc75d000; frame = (0 0;
414 226); layer = <CALayer: 0x608000625720>>) with
afterScreenUpdates:NO, because the view is not in a window. Use
afterScreenUpdates:YES.`
tl;dr
I need to check whether the app I am UI testing has entered the background (i.e. user pressed the home button). Checking for existence of particular elements such as navigation bars doesn't work, neither do most methods from Facebook's private headers for XCUIApplication/XCUIElement. Foregrounding the app also causes issues, and relaunching the app is not an option; neither is siri service.
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.

Unity ios game get killed in background when login into Facebook

i've met a problem when integrating my game with Facebook Unity SDK, the latest version, on IOS7, IPhone-4s.
Each time the game requests a Facebook login operation, game will become inactive and turns into background, and a Facebook login page appears, then IOS will killed my game, even the memory used by that game is only 90M or so. After login completed, IOS re-launched game, at which time Facebook SDK couldn't find the previous game process who performed the login operation and thus the login result could not be passed into new game instance.
So, there are two questions:
1) Is there any way to make game process alive in background? I have no idea why 90M memory usage is large enough that IOS want to kill my process.
2) Is there any way let the new game process get login result performed by the previous game process?
3) Is there any way to open embedded webView login dialog of Facebook in unity when performs a login operation instead of jumping out my game?
thanks you.
------------ UPDATE ----------
Solution found for the 3rd question:
1) Locating Facebook/Editor/iOS/FbUnityInterface.mm
2) Find method -(void)login:(const char *)scope { ... }
3) change
openWithBehavior:FBSessionLoginBehaviorWithFallbackToWebView
to
openWithBehavior:FBSessionLoginBehaviorForcingWebView
4) now, each time you request login, an embed web-view dialog will be popped out instead of jumping out of current game to Facebook login dialog.
1) First of all make sure that you haven't checked 'PlayerSettings | Other Settings | Configuration | Exit on suspend' option, which kills your app when you leave it.
90MB on iPhone4S could be quite a lot, the device itself has only 512 MB RAM memory, where system takes a lot. If you have many apps open, then your app, then facebook app which nowadays is not lightweight as well, then the biggest active process (your game) could be killed.
2) Yes there is. Facebook Unity3d plugin has a method for checking the logged status, which should return true after succesfull login (even if the app was killed).
if( FB.IsLoggedIn )
{
// your code here
}
3) There is no easy way to do that with current version of Unity3D Facebook plugin.
Try making a debug build in Xcode and see what it says when the application is killed in the background. It should give a stacktrace to see what happens. That 90MB shouldn't be a problem for an iPhone4S so out of memory crash could be ruled out.

Firebase Analytics events from iOS not showing up

I am testing the new Google-powered Firebase, and have implemented remote notifications and crash reporting. I am, however, having massive problems with getting Analytics to work.
I track events with FIRAnalytics.logEventWithName(...) and save user pproperties with FIRAnalytics.setUserPropertyString(...). However, no matter what I do, no data shows up in the Firebase Analytics Console.
Well, I do receive some events, but those are not sent by me (like first_open and session_start). Also, this data seems to drop in after a very long time.
Furthermore, when I track events and save user data, I receive the following:
Upload task scheduled to be executed in approx. (s): 3102.294599890709
This seems really strange - Firebase waiting almost an hour before trying to send the next batch of data must be a bug, or is it configurable? When I waited that extremely long delay out, data was sent...but does not show up.
Firebase events are batched together and uploaded once every hour in order to prevent excessive battery drain on the devices. On iOS when you background the app before the 1h upload target the events will be dispatched at this time in the background.
You can enable debug logging for iOS (https://firebase.google.com/docs/analytics/ios/events#view_events_in_the_xcode_debug_console) to see when events are uploaded in debug console.
Once the events are uploaded there is delay at about 3h before the data will show up in the Firebase Analytics dashboard. Also the default day range excludes "today" so you only see events from yesterday. You can switch the date picker to include Today if you like to see the latest events.
The main reason to delay/batch data uploading is to save battery. Each time the network is used the device mobile network modem is put in hi power mode and stay in this mode for a while. If network is used regularly it has sever impact on the battery life. By batching the uploads together and delaying the upload the impact on the battery is significantly reduced.
In Swift it should be like:
FIRAnalytics.logEvent(withName: "SignUp", parameters: ["user_id": userid, "user_name": username])
To view this event in Firebase:
Go to Firebase console β†’ Analytics tab
Click on DebugView tab; your Events are shown there
To view this event in Xcode:
In Xcode, select Product β†’ Scheme β†’ EditScheme
Select Run from left Menu
Select Arguments tab
In the Arguments Passed on Launch, add -FIRAnalyticsDebugEnabled
One dash only!!
Note that -FIRAnalyticsDebugEnabled has only ONE dash in front of it.
If you are not receiving events in console, it may be because you are not following naming convention, as I experienced if there is a space in event name it will never show up in the console like following:
mFirebaseAnalytics.logEvent("Add Camera", bundle);
But when you remove the space like following:
mFirebaseAnalytics.logEvent("Add_Camera", bundle);
Now you will see events in console, after approximately 3 hours.
Application will dispatch the data to console in following cases:
1- Data is more than an hours old
2- App goes into the background
You can watch this tutorial for more information:
Getting Started with Firebase Analytics on iOS: Events - Firecasts
Another thing to check is making sure your logging entries in the Arguments Passed on Launch are correct. They should start with a - e.g
-FIRAnalyticsDebugEnabled
and not
FIRAnalyticsDebugEnabled
I wasted an hour the other day wondering why nothing gets logged.
React-Native App (IOS/Android)
I had the same problem, debugView wasn't working, and streamView glitches a few times, the best way ive found to test my events was to logEvents with my createPageEvent() and then
the important thing is to put the app into background after logging the events, they will show up almost in realtime on firebase events or in streamView (check this article to see when events are sent to firebase)
events are only sent after 1 hour since they have been logged or immediately if you put your app in background.
import firebase, { RNFirebase } from 'react-native-firebase';
export default class AnalyticsService {
static async initialize() {
firebase.analytics().setAnalyticsCollectionEnabled(true);
}
static async createPageEvent(screen: string) {
firebase.analytics().setCurrentScreen(screen)
firebase.analytics().logEvent(`open_${screen}`)
}
}
the result is this in streamView almost realtime ->
Now you can start building funnels and stuff
first_open, session_start are listed by Firebase as Automatically collected events.
I can not help you with the extreme upload task delay you encounter on your custom events.. but Firebase Analytics is less than a week old and it may be just a bug on their side.
I found this StackOverflow question which mention the same debug lines but related to Google App Measurement or old Google Mobile Analytics SDK.
Also, be aware that Firebase Console won't show events in real-time (source):
You can view aggregrated statistics about your events in the Firebase console dashboards. These dashboards update periodically throughout the day. For immediate testing, use the logcat output as described in the previous section.
Just a simple note here: according to this little video https://www.youtube.com/watch?v=5pYdTgSkW5E after playing with your simulator you must press the home button on the Xcode, otherwise the data will not be sent to the server.
The most common problem most of the people are facing is the firebase is not logging events even though everything is working perfectly fine
This is what i found in there docs
If you need to deactivate Analytics collection permanently in a version of your app, set FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED to YES in your app's Info.plist file. Setting FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED to YES takes priority over any values for FIREBASE_ANALYTICS_COLLECTION_ENABLED in your app's Info.plist as well as any values set with setAnalyticsCollectionEnabled.
To re-enable collection, remove FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED from your Info.plist. Setting FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED to NO has no effect and results in the same behavior as not having FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED set in your Info.plist file.
So you have to remove FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED from your google-servicesinfo.plist file to make analytics work
Make sure your device is not set to battery save mode. In this mode events may be accumulated and sent only once in a while, even if you run firebase in debug mode as explained by others.
It takes too much time to update events in Firebase. Probably it is done once a day. See iOS or Android logging of Firebase events.
You can enable verbose logging to monitor logging of events by the SDK
to help verify that events are being logged properly. This includes
both automatically and manually logged events.
You can enable verbose logging as follows:
In Xcode, select Product > Scheme > Edit scheme...
Select Run from the left menu.
Select the Arguments tab.
In the Arguments Passed On Launch section, add
-FIRAnalyticsDebugEnabled.
The next time you run your app, your events will display in the Xcode
debug console, helping you immediately verify that events are being
sent.

Resources