code: function (fn, repeatTest = 0, args = []) {
      let result, error
  
      /**
       * if a new hook gets executed we can assume that all commands should have finised
       * with exception of timeouts where `commandIsRunning` will never be reset but here
       */
      // commandIsRunning = false
  
      try {
          result = fn.apply(this, args)
      } catch (e) {
          error = e
      }
  
      /**
       * handle errors that get thrown directly and are not cause by
       * rejected promises
       */
      if (error) {
          if (repeatTest) {
              return executeAsync(fn, --repeatTest, args)
          }
          return new Promise((resolve, reject) => reject(error))
      }
  
      /**
       * if we don't retry just return result
       */
      if (repeatTest === 0 || !result || typeof result.catch !== 'function') {
          return new Promise(resolve => resolve(result))
      }
  
      /**
       * handle promise response
       */
      return result.catch((e) => {
          if (repeatTest) {
              return executeAsync(fn, --repeatTest, args)
          }
  
          e.stack = e.stack.split('\n').filter(STACKTRACE_FILTER_FN).join('\n')
          return Promise.reject(e)
      })
  }
docs: execute test or hook asynchronously
  @param  {Function} fn         spec or hook method
  @param  {Number}   repeatTest number of retries
  @return {Promise}             that gets resolved once test/hook is done or was retried enough