Sporadic results in XCTest #1350

Closed
bredfield opened this Issue Jan 16, 2015 · 15 comments

Projects

None yet

6 participants

@bredfield

Using Xcode 6.1.1, Swift, and Realm 0.88, I'm getting some weird results with testing RLMObjects.

When testing the success of a model's creation, tests will (in a seemingly random fashion) pass or fail. I'm assuming this relates to the race conditions, as described here: https://groups.google.com/d/msg/realm-cocoa/LZQou7g8or8/lSmoy5beTRIJ.

I'm using the SwiftTestCase as a base test class: https://groups.google.com/d/msg/realm-cocoa/LZQou7g8or8/lSmoy5beTRIJ. With one addition: since my models always use the defaultRealmPath, I set the path to the test path in setUp:

    override func setUp() {
        super.setUp()

        deleteRealmFilesAtPath(defaultRealmPath())
        deleteRealmFilesAtPath(testRealmPath())
        RLMRealm.setDefaultRealmPath(realmWithTestPath().path)
    }

When testing a model function that creates a user, something along the lines of this:

       ...
       let realm = RLMRealm.defaultRealm()
       realm.beginWriteTransaction()
       realm.addOrUpdateObject(user)
       realm.commitWriteTransaction()  
       return user

With a simple test such as:

        TestUser.createUserWithToken(token, email: testEmail)

        let predicate = NSPredicate(format: "token = %@", token)
        if let user = DCUser.objectsWithPredicate(predicate).firstObject() as? TestUser {
            XCTAssert(user.token == token, "User created with Token")
            XCTAssert(user.email == testEmail, "User created with email")
        }
        else {
            XCTFail("User didn't exist")
        }

The test will sporadically pass or fail.

Is there something else I should be doing to alleviate the issue?

@tgoyne
Member
tgoyne commented Jan 16, 2015

How is it failing? Is the object not being found, or is there stale data from previous tests resulting in the asserts failing?

@bredfield

Ah, I should have specified -- it always fails with the object being nil.

@tgoyne
Member
tgoyne commented Jan 16, 2015

Are there any uses of in-memory realms or other places where setDefaultRealmPath is called?

@segiddins segiddins added the pending label Jan 16, 2015
@bredfield

No in memory realms. I only set the default realm to the test one, in setUp().

Note - when I print out the defaultRealm's path from the TestUser class (where I'm creating the record), it's properly set to my test realm path.

@bredfield

I just tried doing the same without using the defaultRealm, but instead passing through the test realm to the createUser method, with the same sporadic result.

@tgoyne
Member
tgoyne commented Jan 17, 2015

Are any of your tests doing thing on multiple threads? If there's a background thing using Realm that sometimes finishes and is deallocated after setUp is called for the next test, that could cause issues similar to what you're seeing.

@bredfield

Nope, everything is on a single thread. Also, the above test example will fail even when run alone.

@jpsim jpsim self-assigned this Jan 19, 2015
@jpsim
Member
jpsim commented Jan 19, 2015

Hi @bredfield, I'm sorry this is causing you some problems. It doesn't look like you're doing anything wrong from what you've told us.

We'll need access to an Xcode project where we can reproduce this issue to troubleshoot further. Do you think you could send us anything? You can email us code privately at help@realm.io if you prefer.

@jpsim jpsim removed their assignment Jan 19, 2015
@bredfield

Hey @jpsim, thanks for looking into this. It's quite possible it is on my end. I've set up an example project that's exhibiting the symptoms: https://github.com/bredfield/RealmTest.

@tgoyne
Member
tgoyne commented Jan 20, 2015

The problem is the as? -- firstObject() is returning a non-nil object of the correct type, but for some reason the dynamic cast is failing.

@bredfield

Great find! Have you run into any similar dynamic casting issues previously? Is there a preferred way to cast to the object's class?

Note: TestUser.objectsWithPredicate(predicate).objectClassName is printing out the proper TestUser class name, but firstObject() is of type AnyObject!

Another Note: A forced downcast does cause a Swift dynamic cast failed sporadically.

let predicate = NSPredicate(format: "token = %@", token)
let userObject: AnyObject! = TestUser.objectsWithPredicate(predicate).firstObject()
let user: TestUser = (userObject as TestUser) //This will (seemingly) randomly cause the error
@dave-trudes

+1

@ghost
ghost commented Jan 27, 2015

+1

@AnthonyMDev

Do we have any idea if this has been solved, or is being looked at?

@jpsim jpsim self-assigned this Mar 3, 2015
@jpsim
Member
jpsim commented Mar 3, 2015

Hi all, thanks for your patience on this. The problem demonstrated in the example project created by @bredfield was caused by compiling an RLMObject subclass in both the app and test targets.

tl;dr; don't add your app's Swift files to your unit test targets.

Please read bredfield/RealmTest#1 for a more detailed explanation of what was happening and how it can be fixed.

@jpsim jpsim closed this Mar 3, 2015
@jpsim jpsim removed the pending label Mar 3, 2015
@dumoko dumoko referenced this issue in facebook/xctool Dec 22, 2015
Closed

Linking problems, Realm framework as casualty #649

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment