How to implement time based tests? - ios

I have an app that communicates with a server and receives XML data. The app moves between internal states based upon some dates in the XML.
I would like to write some test code for the app but are there any mechanisms for setting the system time when setting things up for the test, and then to alter the system time while the tests are running?
I know the APIs for setting the system time are private, but that is for apps, this is not for an app its test code therefore is there some existing mechanism within SenTestCaseCase for doing something like this?

Difficult at best.
Of course, ideal would be some sort of Mac hack that would reflect a different time base into the iOS simulator, but I've never heard of anything like that.
Failing that, you'd have to "hook" your app. First (easy part) find all uses of [NSDate date] and the related "since now" uses and replace with references to MyNSDate. This version of NSDate would hook the "timeIntervalSinceReferenceDate" class method and "feed" it bogus time values.
The hard part is to somehow booger up all the timers that your app is sensitive to. I have no idea how you'd go about that.

Related

How to set UserDefaults with XCUItest

I am doing iOS UI testing with XCUITest.
Since we do not have access to the app, how do we set defaults to the app?
You can pass all the required data using launch arguments.
Please read documentation
https://developer.apple.com/documentation/xctest/xcuiapplication/1500477-launcharguments
The other (and a bit slower) option is to use deep links.
This sounds much more complex than it is, but a technique that has worked for me is to set up an HTTP server in the testing suite that you can use to fetch mock data in your test code. I have had success with Embassy and Ambassador.
So you'd pass in a launch argument telling your app code to fetch from the server. For the case of UserDefaults a helper class for making these specific requests to the local endpoint works well. This unfortunately means your app code has to be doing some setup for testing, but depending on your needs it could be a good compromise.
Another possible solution to crossing the process boundary:
If you are not doing on device testing, you can access "SIMULATOR_SHARED_RESOURCES_DIRECTORY" and provide the data in a file for your test to consume.
On a real device this would be more difficult because you would need to use a shared Group container.
You probably can use "Application Data Package". It's when you save your app state into a container and then run tests with the saved environment.
There are many guides how to do it, that's just one of them:
https://www.codementor.io/paulzabelin/xcode-app-data-suni6p4ma
It might me a more powerful and overcomplicated thing that you need, but opens a big world of possibilities ;)

How to schedule a piece of code to run at a specific time, and repeat daily?

I'm new to WatchKit development. I've been wanting to create a simple app that requires the ability to display a message at a certain time of day, and repeat this process daily.
I've tried to use NSTimer but once I open another app, the message is no longer shown. I don't know if this is the correct way to do it.
I would like some general insight on what ways I can approach this.
Edit: If possible, I prefer that it can work without relying on the iPhone's notification architecture. I wonder how the built-in Timer app works.
Edit 2: NSTimer seems like the way to go, the reason the message wasn't shown has more to do with the user interface system.

Global Settings iOS Auto time

It´s possible, detect with Swift or Objective-C if in the settings Date & Time, "Set Automatically" is enabled ???
In android there is "Settings.Global.AUTO_TIME_ZONE", I am looking a equivalent in Swift/Objective-C
No, there is no way to do this given the standard SDK. There are jailbroken/private API methods, but I would not recommend relying on them.
If your goal is to keep someone from going back in the past (to circumvent some kind of timed trial) you could store the most recent date you've seen (maybe at startup) in the NSUserDefaults, and if at any time you notice that the current time is more than one hour earlier than the most recently stored time, you can probably safely assume the user has manually changed their time.
But without knowing why you want to do this, it's difficult to offer better suggestions.

Is MobileServiceSQLiteStore.DefineTable<T> necessary on every run and if so why?

I'm trying to improve app launch performance for subsequent logins (every login after the first) with my mobile app and after putting some stop watch diagnostics I can see that defining my 8 tables with MobileServiceSQLiteStore.DefineTable<T> takes on average 2.5 seconds. Every time.
On an iPhone 4 running iOS 7 the loading time would be less than a second if it weren't for having to define these tables every time. I would expect them to only need to be defined the first run of the app when the SQLite database is setup. I've tried removing the definitions on subsequent logins and try to just get the sync tables but it fails with "Table is not defined".
So, it seems this is the intended behavior. Can you explain why they need to be defined each time and/or if there is any workaround for this? It could be negligible considering my phone is pretty old now.. but it still is something I would like to remove if possible.
Yes, it is required to be called every time because SDK uses it to know how to deserialize data if you read it via untyped interface i.e. IMobileServiceSyncTable instead of IMobileServiceSyncTable<T>.
As of now there is no work around to avoid calling it each time. I'm surprised however that it is taking 2.5 seconds for you because DefineTable does not do any database operations. It merely inspects the members on your type/JObject and maintains an in memory dictionary for later re-use.
I would recommend you to download and compile the SDK and debug your way through to figure out where the time is actually spent.

Automated sleep log

I would like to create a device that will log when a person falls asleep. Of course, someone can't just open a software application and make an entry say "fall asleep, 10:13pm" and be asleep a few seconds later. Instead, I was thinking about hacking a blackberry to log whenever a person powers it on to check the current time. The specific algorithm is not important, but is it possible to write a piece of code be written to intercept the power on button and write the current time/date to a file? If so, how is it done?
Also, if anyone has a simpler idea, please share.
I haven't tested it, but since you're asking for ideas:
You have your application running in background (or even an app which doesn't extend UIapplication) and have a Task (using Timer and TimerTask) that repeatedly checks if Backlight.isEnabled() returns true. If it does - somebody is using the phone. You can even incorporate an AlertListener class to check when the user has been woken up ;)
The downside of this solution (if it works) is that it is something of a 'busy waiting loop', so intercepting some event would be much better.
As far as writing down the current time is concerned - it's possible and sample code snippets are everywhere, you can of course use the persistent store or an SQLite table to aggregate the results in an interesting way.
Funny thing is I've been thinking about an app like this lately - it might be an good idea.

Resources