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

Make unit tests less flaky on Travis CI #1329

Merged
merged 2 commits into from
Apr 21, 2017

Conversation

islemaster
Copy link
Contributor

@islemaster islemaster commented Apr 20, 2017

I believe I've identified and fixed the two top causes of flaky failures in the Travis CI builds. I've provided inline comments for each fix.

Existing failure rate

For a baseline, I looked at the last five builds on master: 2574, 2573, 2569, 2568, and 2567.

  • Total jobs: 50 (10 per build)
  • Failures: 4 jobs / 8%

I've seen both of these on my own pull requests recently too - they seem to be fairly common.

New failure rate

Considering builds: 2578 (PR), 2579 (PR), 2580 (PR), 41, 42, and 43.

  • Total jobs: 60 (10 per build)
  • Failures: None!

// Don't allow time to advance in this test. Otherwise it's possible for
// the animation to progress between setup and the assertion, causing flaky
// failures.
this.sandbox.useFakeTimers();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On a separate branch I added a bunch of logging in this test, and I found that when it fails, the animation's progress value has advanced slightly from 0.9 between calling this.animation.enqueue(segment) and capturing the return value of this.animation.calculateProgress(this.animation.playLoop.calledAt). For example, this run reports progress of 0.902.

I eventually realized that this test assumes no significant time will pass in that space - that's why we're manually starting the progress at 0.9 - but on very slow machines that might not be true. The solution is to use sinon's fake clocks to effectively stop time during this test. The fake timers are implicitly cleaned up by the sandbox when the test is done.

@@ -260,7 +263,8 @@ exports["Animation -- Servo"] = {
var indices = this.animation.findIndices(progress);
var val = this.animation.tweenedValue(indices, progress);

test.ok(Math.abs(val - 74.843 < 0.01));
test.ok(Math.abs(val - 74.843) < 0.01,
"Expected " + val + " to be within 0.01 of 74.843");
Copy link
Contributor Author

@islemaster islemaster Apr 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised that the original assertion here ever worked, due to the misplaced paren; turns out

Math.abs(true) === 1;
Math.abs(false) === 0;

I figured it wouldn't hurt to leave a nicer assertion behind. 😁

if (!calledTestDone) {
calledTestDone = true;
test.done();
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a little harder to track down, but my first clue was this issue on the nodeunit repo, followed by this issue that is still open and summarizes the problem well; nodeunit raises this really opaque error if you happen to call test.done() twice in a single test.

I scoured rgb.collection.js for places where this might happen but eventually noticed that it always failed right at the top of that file... So I checked the test file before it, and sure enough, there's some tricky and system-dependent callback stuff going on here. I did some more extra logging on a separate branch and discovered that the "reallyExit" stub was getting called twice in failure cases (examples here and here). I'm not sure how - that doesn't seem possible, since we restore the stub when it's called - but I figured a second guard against calling test.done() twice might be in order.

If anyone has a better idea of how the reallyExit stub is getting called a second time, I'm all ears. Maybe something in the previous test?

@islemaster islemaster changed the title [WIP] Make unit tests less flaky on Travis CI Make unit tests less flaky on Travis CI Apr 21, 2017
@rwaldron
Copy link
Owner

👏 Nice!

@rwaldron rwaldron merged commit 6d8b4a3 into rwaldron:master Apr 21, 2017
@islemaster islemaster deleted the stabilize-tests branch April 21, 2017 17:07
@dtex
Copy link
Collaborator

dtex commented Apr 21, 2017

Thank you so much @islemaster !!!

There are not enough emojis and smileys in the world to convey how happy (and relieved) this makes me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants