vendredi 9 septembre 2016

How can I build a mocha suite of tests in my app, and run them?

I've got a bit of a problem. I'm trying to develop a test suite for my company's application. The problem is that it just makes a lot of sense to build out the tests using programming, rather than writing them all by hand.

Specifically, here's what's happening.

We have a list of reports: [reportA, reportB, reportC... ad nauseum] and there are about 120 of these.

For each report, we need to (asynchronously) grab a record from the server. Once we have that record, we then need to run a battery of tests on it (roughly ~200 or so per report.) Complicating the fact is that I'll have to do some if/then routing in order to make sure only the correct tests are run on the correct report, but that's a minor issue compared to running the tests in the first place.

My first thought was to grab the reports with a Promise, and the inside the .then() method, run those "describe()" and "it()" statements. No dice - Mocha will not run inside a .then() statement.

My second thought: create a "testmaker" function that returns a mocha test, and run them one after each other.

Again, no such luck, I'm getting a "describe is not defined" error.

ERROR: ReferenceError: describe is not defined

I can't really use the "before()" or "beforeEach()" functions, because the asynchronous task needs to be completed before describe() executes.

Here's what I've got... (it's pseudocode because I can't past the real work code.)

import {
  A_BUNCH_OF_REPORTS_TO_RUN,
  asyncReportGrabber,
} from './aBunchOfReportsToRun';

const noop = (done) => done();

let queue = []; 

const doNext = () => {
  if(queue.length === 0){
    console.log("All tests completed");
  } else {
    queue.shift()()
  }
}

const doneAndNext = (done) => {
  doNext();
  done();
}

const testFrame = (params) => {
  params = params || {};
  return {
   describe: params.describe || 'No description provided',
   timeout: params.timeout || 60000,
   before: params.before || noop,
   beforeEach: params.beforeEach || noop,
   tests: params.tests || [noop],
   afterEach: params.afterEach || noop,
   after: params.after || doneAndNext,
  }
}

const testMaker = (params) => () => {
  describe(params.describe, function() {
    before(function(done) {
      this.timeout(params.timeout || 30000)
      params.before(done)
    })
    beforeEach(function(done) {
      this.timeout(params.timeout || 30000)
      params.beforeEach(done)
    })
    params.tests.forEach(function(test){
      it(test.shouldStatement, function(done) {
        this.timeout(params.timeout || 30000)
        test.it(done)
      })
    })
    afterEach(function(done){
      this.timeout(params.timeout || 30000)
      params.afterEach(done);
    })
    after(function(done){
      this.timeout(params.timeout || 30000)
      params.after(done)
    })
  })
}

Promise.all(A_BUNCH_OF_REPORTS_TO_RUN.map((report) => asyncReportGrabber(report)))
  .then((records) => records.map((record) => testMaker(testFrame({
    describe: record.description,
    tests: record.tests.map((test) => ({
      shouldStatement: test.shouldStatement,
      it: function (done) {
        expect(test.testCase).to.equal(test.expected)
        done(); 
      },
    })
  })))))
  .then((testSuiteQueue) => {
    queue = testSuiteQueue;
    doNext(); 
  })
  .catch((err) => {
    console.log(err);
    throw err;
  })

Aucun commentaire:

Enregistrer un commentaire