Unit testing iOS app with Realm and initial app database

956 views
Skip to first unread message

Javier Julio

unread,
Oct 13, 2014, 2:32:48 PM10/13/14
to realm...@googlegroups.com
I have an iOS app I'm building using Realm in Swift. The app contains an initial database (English dictionary). When I run tests I notice that the RLMRealm.defaultRealm() is using the initial database from my app. The problem I'm running into is that I don't want to modify the database my app comes packaged with but I'm using RLMRealm.defaultRealm() in my code to save data. Any suggestions on best practices on how to setup an app with tests that contains a separate database? If I add an extension to RLMRealm that overrides defaultRealm() that is only in my Test target then no matter what I do I always get "ambiguous use of defaultRealm()" errors. I have a base TestCase class that is modeled after the base class in Realm's tests.

extension RLMRealm {

 class func defaultRealm() -> RLMRealm! {

   return RLMRealm.realmWithPath(testRealmPath(), readOnly: false, error: nil)

 }

}




Sean Zehnder

unread,
Nov 1, 2014, 11:45:05 AM11/1/14
to realm...@googlegroups.com
Did you figure out how to do this yet? -- would really save me some time as well...

thx,
sean

JP Simard

unread,
Nov 2, 2014, 7:26:15 PM11/2/14
to Sean Zehnder, realm...@googlegroups.com
One way to do this is to have any method that touches Realm to take in an RLMRealm as an argument, so you can use a different realm for testing.

This does mean that you can't use any of the convenience methods. If using those convenience methods is important to you, the only thing you lose is the ability to have a realm in a different location for your tests.

Another approach, totally unrelated to Realm, is to test using a different bundle ID. Many app developers I know do this, which allows them to have different logic for testing builds (i.e. integrate TestFlight or special debugging features), without affecting the production version of the app on the same phone, as they're separate apps as far as iOS is concerned.

--
You received this message because you are subscribed to the Google Groups "Realm" group.
To unsubscribe from this group and stop receiving emails from it, send an email to realm-cocoa...@googlegroups.com.
To post to this group, send email to realm...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/realm-cocoa/9279bea0-1436-4eec-963c-d47a1f0a38f4%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Javier Julio

unread,
Nov 10, 2014, 1:49:41 PM11/10/14
to realm...@googlegroups.com
Hey Sean, yes I was able to figure this out. Are you still having trouble? Essentially what I did is create my own static helper. That's your best choice, don't rely on Realm.defaultRealm(). I have my on RealmManager class that is a singleton. I'm not crazy about this but I really needed to have something in place to run tests. It has 2 class methods, setupRealm and setupTestRealm. In my app delegate if I detect I'm running tests I call setupTestRealm and cut out early from the didFinishLaunching method. Otherwise if I run the app normally then it calls setupRealm. They do the same thing except that setupTestRealm changes the instance to point to my test.realm database file. This way when running tests anytime I do RealmManager.realm() it returns a realm to that test.realm file rather than the app's database file (db.realm). Let me know if you have questions or trouble. Happy to help out.

Probably the most important part is this: if you are writing your app in Swift and want to run tests against code that uses Realm, do NOT, do NOT put those files in both the app and test targets. Leave it only in the app target but that means you *must* use access control (specifying public, private, etc.) to do testing and then import the app target in your tests (if app is called MyApp, then "import MyApp"). I ran into a lot of pain because Realm is really pushing the limits of Swift. With the approach of setting my files to be in both targets and being access control-less I would get sporadic dynamic casting errors (https://github.com/realm/realm-cocoa/issues/1044). Apple is aware that there are frustrations to testing when using Swift. Essentially two approaches, but if you want to test against Realm backed code make sure to use this approach: http://blog.diogot.com/blog/2014/08/23/swift_access_control_and_testing/ (what I outlined above).

JP Simard

unread,
Nov 10, 2014, 2:07:54 PM11/10/14
to Javier Julio, realm...@googlegroups.com
Thanks for sharing your findings, Javier! That sounds like a decent approach to me.

On Mon, Nov 10, 2014 at 10:49 AM, Javier Julio <jjfu...@gmail.com> wrote:
Hey Sean, yes I was able to figure this out. Are you still having trouble? Essentially what I did is create my own static helper. That's your best choice, don't rely on Realm.defaultRealm(). I have my on RealmManager class that is a singleton. I'm not crazy about this but I really needed to have something in place to run tests. It has 2 class methods, setupRealm and setupTestRealm. In my app delegate if I detect I'm running tests I call setupTestRealm and cut out early from the didFinishLaunching method. Otherwise if I run the app normally then it calls setupRealm. They do the same thing except that setupTestRealm changes the instance to point to my test.realm database file. This way when running tests anytime I do RealmManager.realm() it returns a realm to that test.realm file rather than the app's database file (db.realm). Let me know if you have questions or trouble. Happy to help out.

Probably the most important part is this: if you are writing your app in Swift and want to run tests against code that uses Realm, do NOT, do NOT put those files in both the app and test targets. Leave it only in the app target but that means you *must* use access control (specifying public, private, etc.) to do testing and then import the app target in your tests (if app is called MyApp, then "import MyApp"). I ran into a lot of pain because Realm is really pushing the limits of Swift. With the approach of setting my files to be in both targets and being access control-less I would get sporadic dynamic casting errors (https://github.com/realm/realm-cocoa/issues/1044). Apple is aware that there are frustrations to testing when using Swift. Essentially two approaches, but if you want to test against Realm backed code make sure to use this approach: http://blog.diogot.com/blog/2014/08/23/swift_access_control_and_testing/ (what I outlined above).

--
You received this message because you are subscribed to the Google Groups "Realm" group.
To unsubscribe from this group and stop receiving emails from it, send an email to realm-cocoa...@googlegroups.com.
To post to this group, send email to realm...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages