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()');
    }
  }
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 (part === 'takedown') {
      
      o.takedown.status = false;
      if (( isSuite ) && (! o.abortOnFail)) {
        
        run('setup', o.next);
      } else {
        
        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('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') {
      
      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()');
    }
  }
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()' ) ; } }
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]
test object is passed here when it fails the test setup or takedown . handles printing the result and updating the objects status .