test runner | | test runner | Search

This code defines a function testCells that executes JavaScript code within a Mocha testing framework, enabling the testing of code snippets or Jupyter notebook cells.

Run example

npm run import -- "test cells"

test cells

var importer = require('../Core');
var path = require('path');
var Module = require('module').Module;
var Mocha = require('mocha');

// call test runner
var mocha;
if(typeof mocha === 'undefined') {
    mocha = new Mocha({
        ui: 'bdd',
        reporter: 'list',
        timeout: 10000,
    });
}

function resetTests(suite) {
    suite.tests.forEach(function(t) {
        delete t.state;
        t.timedOut = false;
    });
    suite.suites.forEach(resetTests);
    suite.tests = [];
}

function testCells(cells, ctx = {}) {
    resetTests(mocha.suite);
    if(!cells) {
        cells = 'test test runner';
    }
    if(!cells[0].code) {
         cells = typeof cells === 'string'
            && (!cells.includes('.ipynb') || cells.includes('['))
             ? [importer.interpret(cells)]
             : importer.interpret(cells);
    }
    cells.forEach(r => {
        mocha.suite.emit('pre-require', ctx, r.id, mocha);
        Object.assign(ctx, Mocha);
        try {
            var required = r.runInNewContext(ctx, {useCache: false});
            Object.assign(ctx, required);
        } catch (e) {
            console.log(e);
        }
        mocha.suite.emit('require', required, r.id, mocha);
        mocha.suite.emit('post-require', ctx, r.id, mocha);    
    });
    return new Promise(resolve => mocha.run(function (failures) {
        resolve(failures);
    }));
}
module.exports = testCells;

What the code could have been:

// Import required modules
const importer = require('../Core');
const path = require('path');
const Module = require('module').Module;
const Mocha = require('mocha');

// Initialize Mocha test runner
const mocha = new Mocha({
  ui: 'bdd',
  reporter: 'list',
  timeout: 10000,
});

/**
 * Reset Mocha test suite to its initial state.
 *
 * @param {Mocha.Suite} suite Test suite to reset.
 */
function resetTests(suite) {
  suite.tests.forEach((test) => {
    test.state = undefined;
    test.timedOut = false;
  });

  suite.suites.forEach(resetTests);
  suite.tests = [];
}

/**
 * Run tests from given cells.
 *
 * @param {Array<any>|string} cells Test cells or a string.
 * @param {Object} [ctx={}] Context for test runs.
 * @returns {Promise<number>} Number of test failures.
 */
async function testCells(cells, ctx = {}) {
  // Reset Mocha test suite
  resetTests(mocha.suite);

  // Interpret cells if they are a string or an array of strings
  cells = Array.isArray(cells)? cells : [cells];

  // Interpret each cell and run its test
  for (const cell of cells) {
    if (typeof cell ==='string') {
      // Assume cell is a string if it's not an object with 'code' property
      if (!cell.includes('.ipynb') || cell.includes('[')) {
        cell = importer.interpret(cell);
      } else {
        // Assume cell is a string with code if it has '.ipynb' but not '['
        cell = [importer.interpret(cell)];
      }
    }

    // Run cell's test in a new context
    try {
      const { code, input, result, output } = cell;
      const ctxWithMocha = {...ctx,...Mocha };
      const required = await importer.interpretCode(code, ctxWithMocha);
      await required.runInNewContext({...ctxWithMocha });
    } catch (e) {
      console.error(e); // TODO: Improve error handling and logging
    }
  }

  // Run Mocha test suite and return number of test failures
  return new Promise((resolve) => {
    mocha.run((failures) => {
      resolve(failures);
    });
  });
}

module.exports = testCells;

This code defines a function testCells that executes JavaScript code within a Mocha test runner environment.

Here's a breakdown:

  1. Dependencies:

  2. Mocha Setup:

  3. Test Reset:

  4. testCells Function:

  5. Export:

In essence:

This code provides a way to execute JavaScript code cells within a Mocha test environment, allowing for testing of code snippets or Jupyter notebook cells. It handles code interpretation, test setup, and result handling.