async run() {
    const suite = this
    let agent = null

    /**
     * Function that calculates CPU usage after a test, and calls any defined after/callback
     * @param {Object} test Object defining the current test configuration
     * @param {function} next anonymous function defined in the `startTest` for loop;
     *   its second parameter is the delta between the current CPU usage and the previous CPU usage.
     * @param {?function} [executeCb] If the test is run in a transaction, `executeCb` is defined,
     *   and will run after any user-defined `after` function. If `executeCb` is defined, the result of
     *   that is the `after` function's return value.
     * @param {{user: number, system: number}} prevCpu Output of process.cpuUsage() in the previous test
     * @returns {function} an invocation of `executeCb`, if defined, or `next(null, delta)`
     */
    const after = async (test, next, executeCb, prevCpu) => {
      // The cpu delta is reported in microseconds, so we turn them into
      // milliseconds
      const delta = process.cpuUsage(prevCpu).user / 1000
      // Despite an effort to reduce callbacks in this test class, some remain, like this one:
      const afterCallback = () => next(null, delta)

      if (typeof test.after === 'function') {
        test.after()
      }

      if (typeof executeCb === 'function') {
        return executeCb(afterCallback)
      }

      return afterCallback()
    }

    /**
     * `execute` gets the CPU usage prior to the test and runs the test.
     * @param {Object} test configuration for the test, including the function to be tested
     * @param {function} next anonymous function defined in the `startTest` for loop;
     *   its second parameter is the delta between the current CPU usage and the previous CPU usage.
     * @param {function} [executeCb] If the test is run in a transaction, `executeCb` is defined,
     *   and will run after any user-defined `after` function. If `executeCb` is defined, the result of
     *   that is the `after` function's return value.
     * @returns {function} an invocation of the `after` function
     */
    const execute = async (test, next, executeCb) => {
      const prevCpu = process.cpuUsage()
      const testFn = test.fn

      await testFn(agent)
      return after(test, next, executeCb, prevCpu)
    }

    /**
     * `runTest` performs one execution of a benchmark test
     * @param {number} n Index of the test in the sequence of tests to be run
     * @param {object} test Test configuration as defined in the *.bench.js file for this suite
     * @param {function} next anonymous function defined in the `startTest` for loop;
     *   its second parameter is the delta between the current CPU usage and the previous CPU usage.
     * @returns {function} If this test is run in a transaction, this returns an invocation of
     *    helper.runInTransaction. Otherwise, this returns an invocation of `execute`.
     */
    const runTest = async (n, test, next) => {
      if (global.gc && test.runGC) {
        global.gc()
      }

      if (typeof test.before === 'function') {
        test.before(agent)
      }

      if (agent && test.runInTransaction) {
        const inTransaction = (txn) => {
          const afterExecute = (execCallback) => {
            txn.end()
            return execCallback(txn)
          }
          return execute(test, next, afterExecute)
        }

        return helper.runInTransaction(agent, inTransaction)
      }

      return execute(test, next)
    }

    /**
     *
     * @param {function} initiator Function to begin the test process--`startTest`
     * @param {number} idx Index of the current test run
     * @returns {Promise<*|boolean>} resolves to the return value of the recursive chain of
     *   initiators (`startTest`) and returned functions (`afterTestRuns`)
     */
    const testIterator = async (initiator, idx) => {
      if (idx >= suite.tests.length) {
        return true
      }
      return await initiator(initiator, suite.tests[idx], idx)
    }

    /**
     *
     * @param {function} initiator The test runner `startTest`
     * @param {object} test configuration for the test
     * @param {Array} samples Array of the CPU deltas from this test
     * @param {number} idx Index of the current test run
     * @returns {function} The next instance in the recursive chain of initiators (`startTest`)
     *   and returned functions (`afterTestRuns`)
     */
    const afterTestRuns = (initiator, test, samples, idx) => {
      const testName = test.name

      if (agent) {
        helper.unloadAgent(agent)
      }

      if (typeof test.teardown === 'function') {
        test.teardown()
      }

      suite.samples[testName] = samples
      return testIterator(initiator, idx + 1)
    }

    /**
     * `startTest` begins the suite of tests, passing its initiator argument to subsequent tests.
     * @param {function} initiator Sets up and executes tests, and is passed to the
     *   afterTestRuns function to be passed on to subsequent tests
     * @param {object} test Configuration object for this suite's test
     * @param {number} idx Integer for tracking progress through the recursive tests
     * @returns {function} invocation of `afterTestRuns`, which continues the chain of recursion.
     */
    const startTest = async (initiator, test, idx) => {
      if (test.agent) {
        agent = helper.instrumentMockedAgent(test.agent.config)
      }

      if (typeof test.initialize === 'function') {
        await test.initialize(agent)
      }

      const samples = []
      for (let i = 0; i < test.runs; i++) {
        await runTest(i, test, (_, delta) => {
          samples.push(delta)
        }) // reliant on callback; should refactor test simply to return delta
      }

      return afterTestRuns(initiator, test, samples, idx)
    }

    await testIterator(startTest, 0) // passing startTest as initiator to avoid circular dependency
    const onSuiteFinish = () => suite.print()
    onSuiteFinish()
  }
This function is called from the /test/benchmark/*.bench.js test files.
Once a suite is created and tests added, `suite.run()` begins the test