Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Michal Bryxí
Michal Bryxí

Posted on • Edited on

     

Shining some light on timing out tests

A couple of days ago we had an interesting case of our CI constantly failing on one particular branch pipeline. The code change was trivial. So trivial that we eventually replaced it with an empty commit. The pipeline was still failing.

Test suite timing out

We useember-exam to shuffle the test order with pseudorandom seed. The idea is:

branch_name=`git rev-parse--abbrev-ref HEAD`ember exam--random=${branch_name}
Enter fullscreen modeExit fullscreen mode

If you never encountered this, very good reasons for doing so are:

  • Tests running in always the same order willprobably not reveal potential race conditions.
  • Tests running in always the same order willprobably not reveal possible leaking state between test runs.
  • By using seed generated from a branch name, we canprobably replicate problematic scenarios locally.

Why did I emphasiseprobably so much? Because as one greatDilbert comics says:

👨🏼‍💻 Are you sure that's random?
😈 That's the problem with randomness, you can never be sure.
          -Scott Adams-

Situations like ours might signal that there isregistered test waiter that does not get cleaned up after thecomponent lifecycle ends.

This is hard to debug because the leak can originate inany tests that preceded the one that timed out. So how to find the offending code?

We had luck with usingChrome -> Dev Tools -> Performance tool. We simply let the tests run till they started timing out. At that point, we hit "record" for few seconds and tried to dig through the results. Few moments going through the stack tree and there is a hint pointing atember-test-waiters.

So we dig into thewaiter-manager::hasPendingWaiters code and found more details aboutwhich waiter, that was not expected, we were waiting for. After that, a careful examination of the relevant component revealed case when the waiter might not have been unregistered.

Dev Tools performance tab

I like this technique because it records history and allows you to quickly jump between the things that already happened without worrying too much that you will miss something important. It's a great first approximation.

Code example

From the perf tool, one can simply jump to the relevant code line, put a breakpoint and check what is the code complaining about. The code we found could be simplified to:

exportdefaultComponent.extend({actions:{buttonClicked(){this.animate();}}animate(){waitForPromise(newPromise((resolve)=>{AnimationLibrary.animate({onComplete:()=>{resolve();}});});}});
Enter fullscreen modeExit fullscreen mode

There might be multiple problems with this. But for simplicity let's say that one test callsclick('button') withoutawait and immediately after that the test ends. There is a chance that component gets torn down whileAnimationLibrary.animate is running. But since there is no DOM to interact with anymore, it will never callonComplete(). Thus leaving the next test hanging with a waiter that will never resolve.

Or there might be other situations happening. Does not matter. The important thing is that you make sure you cleaned up after yourself when your component lifecycle ends:

exportdefaultComponent.extend({// Register fake cancel function_cancel(){},actions:{buttonClicked(){this.animate();}}animate(){waitForPromise(newPromise((resolve)=>{// Override _cancel functionthis._cancel=resolve;AnimationLibrary.animate({onComplete:()=>{resolve();}});});}willDestroyElement(){// Make sure that the promise is resolvedthis._cancel();}});
Enter fullscreen modeExit fullscreen mode

Async is hard.
          -every developer ever-

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Cycle 🚴 , climb 🗻 , run 🏃 , travel 🌍 , enjoy life ♥.IT guy with the need to live fully.
  • Location
    Interlaken, Switzerland
  • Education
    University of West Bohemia
  • Pronouns
    he/him
  • Work
    Sandcastle Architect
  • Joined

More fromMichal Bryxí

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp