Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expected at least one assertion, but none were run - Bounty Available #844

Closed
mattparlane opened this issue Aug 6, 2015 · 9 comments
Closed

Comments

@mattparlane
Copy link

This is one of those annoying intermittent issues... I have a test which has two async calls in series, and I'm getting this error around 30% of the time:

screen shot 2015-08-07 at 8 17 54 am

This is the test:

QUnit.test 'Backbone save - new object has attributes', (assert) ->
    done = assert.async()
    search = new Search
    search.save(Description: 'My test').done ->
        testSearch = new Search(id: search.id)
        testSearch.fetch().done ->
            assert.equal(testSearch.get('Description'), 'My test')
            done()

Unfortunately the save/fetch calls depend on a server so it's not easily reproducible. I've tried creating a reproducible test by using setTimeout instead of the save/fetch calls but it works as expected.

What I've found is that I can make the problem go away by increasing the 13ms timeout in resumeProcessing(), the errors get fewer and fewer as the timeout gets higher, until they seem to completely stop at around 100ms.

Any ideas?

@leobalter
Copy link
Member

I don't know if this code is CoffeeScript or anything else different from JS, but this line doesn't look right:

search.save(Description: 'My test').done ->

As you told, I've also failed trying to reproduce it with setTimeout: http://jsbin.com/suxuka/edit?js,output

Maybe these .done functions are not being triggered.

@mattparlane
Copy link
Author

They are definitely being triggered -- I've added console.log statements inside them and they are there. I used console.logs to get the timing in my attempt to reproduce it with setTimeout, but that didn't work.

Is there any chance that the 13ms value is incorrect? I don't really understand what that code is doing, but like I said, raising it to 100 fixes my problem. Perhaps it could be made an overridable setting?

@mattparlane
Copy link
Author

Also, the CoffeeScript code is correct, search.save() is a Backbone method which returns a jQuery XHR, so .done() is the same function you'd call if you were doing $.get(...).done(...).

Also, there's no confusion between the local variable done and the method name done, that was just bad naming on my part -- I tried changing the variable name even though I knew it was nothing to do with it, but still no joy.

@mattparlane
Copy link
Author

I now have a reproducible test! It still depends on a server but should be trivial to set up. I have it visible here:

https://admin.wb.gs/test.html

The HTML file loads the bare minimum, just QUnit and jQuery, plus the test file itself (Ajax.test.js). It's no longer dependent on Backbone or any of my code -- it's all just QUnit and jQuery now. It GETs /test.json, just contains the JSON response which you should be able to see in your network inspector.

I can't figure out why it works with one request but doesn't work with two requests. Both requests are now exactly the same.

The test will almost certainly fail -- once again, increasing the 13ms in core.js will increase the chance the test will succeed, except now that it's on a remote server I needed to set it to about 200ms before it's reliable. Please let me know if you want to test it with an increased limit.

Bounty available, let me know and we can discuss.

@mattparlane mattparlane changed the title Expected at least one assertion, but none were run Expected at least one assertion, but none were run - Bounty Available Aug 7, 2015
@leobalter
Copy link
Member

Ok, I found the issue.

I've made some changes but my local server was unable to reproduce, so I pushed to a gh-pages: http://leobalter.github.io/temp-test/

QUnit tests has a support for promises if you return them. And your test is returning the $.ajax operation, which works as a promise.

The workaround was returning anything else than a promise.

@jzaefferer @JamesMGreene we need to figure out what to do from here.

@gibson042
Copy link
Member

Actually, returning the promise is fine (if unnecessary); it just calls QUnit.stop() which increments the config.current.semaphore count. The problem is that resolvePromise uses QUnit.start as a then callback, which means it will get the promise fulfillment value as an argument where it expects a count, setting semaphore to NaN.

@leobalter
Copy link
Member

thanks, @gibson042!

@gibson042
Copy link
Member

PR forthcoming. :)

@mattparlane
Copy link
Author

Ah... the perils of implicit return! Thanks so much guys.

robertknight added a commit to robertknight/passcards that referenced this issue Sep 6, 2015
The 'createVault() fails if directory exists' test
return a promise which resolved to [null], this triggered
a bug in QUnitJS when handling tests that return a promise.

See qunitjs/qunit#844 (comment)
robertknight added a commit to robertknight/passcards that referenced this issue Sep 20, 2015
The 'createVault() fails if directory exists' test
return a promise which resolved to [null], this triggered
a bug in QUnitJS when handling tests that return a promise.

See qunitjs/qunit#844 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants