test object is passed here when it fails the test, setup or takedown.
handles printing the result, and updating the objects status.

@param  {string}  part       - indicates the portion of test just run
@param  {number}  suiteIndex - the index number of the test run
@param  {number}  testIndex  - the index number of the test run [optional]
@param  {string}  msg        - any special failure message [optional]
function fail(part, suiteIndex, testIndex, msg) {
    if (typeof testIndex === 'string') {
      msg = testIndex;
      testIndex = undefined;
    }

    var o;
    var isSuite = false;

    if (typeof testIndex === 'number') {
      o = suites[suiteIndex].tests[testIndex];
      if (typeof msg === 'string') {
        suites[suiteIndex].tests[testIndex][part].failmsg = msg;
      }
      display.details('test', o);
    } else {
      isSuite = true;
      o = suites[suiteIndex];
      if (typeof msg === 'string') {
        suites[suiteIndex][part].failmsg = msg;
      }
      display.details('suite', o);
    }

    display.fail(part, o);

    // if we've failed, we always perform the takedown.
    if (part === 'takedown') {
      // takedown has been done
      o.takedown.status = false;
      if (( isSuite ) && (! o.abortOnFail)) {
        // run next suite
        run('setup', o.next);
      } else {
        // run afterEach for this test
        run('afterEach', suiteIndex, testIndex);
      }
    } else if (part === 'afterEach') {
      o.afterEach.status = false;
      if (typeof o.parent.tests[o.parent.testIndex] === 'object') {
        if (! o.parent.abortOnFail) {
          var ti = o.parent.testIndex;
          o.parent.testIndex = o.parent.testIndex + 1;
          run('beforeEach', suiteIndex, ti);
        }
      } else {
        // run suites takedown
        run('takedown', suiteIndex);
      }
    } else if (part === 'beforeEach') {
      o.beforeEach.status = false;
      run('afterEach', suiteIndex, testIndex);
    } else if (part === 'setup') {
      o.setup.status = false;
      run('takedown', suiteIndex, testIndex);
    } else if (part === 'actual') {
      // the actual test
      o.status = false;
      if (o.parent.abortOnFail) {
        display.print('test failed with abortOnFail set... aborting.');
        showSummary();
      }
      run('takedown', suiteIndex, testIndex);
    } else {
      throw new Error('no part specified in run()');
    }
  }