Skip to content
This repository was archived by the owner on Jun 3, 2023. It is now read-only.

DarrelASandbox/testing-test-me

Repository files navigation

About The Project

  • The Modern Javascript Bootcamp Course (2022)
  • The most up-to-date JS resource online! Master Javascript by building a beautiful portfolio of projects!
  • Tutorial for tme (Building a Testing Framework From Scratch)
  • Colt Steele
  • Stephen Grider

 

Notes

  • Command to search for .test.js from any directory.
tme

Testing Framework Requirements

  1. Must be a Node-based CLI framework
  2. Must be able to test browser-based JS apps
  3. Must require very, very little setup
  4. Must be able to test a whole application, not just one little widget
  5. CLI must have a 'watch mode' so we don't have to keep restarting it over and over
  6. CLI must automatically find and run all files in our project that have a name of '*.test.js'

JSDOM

<style>table,th,td {text-align: center; width: 500px}</style>
Mocha in the Browser
createAutoComplete Email Validation
We had a function to run as manay times as we wanted Form logic executes instantly with 'index.js' being loaded
We could create a new autocomplete for each test No easy ability to bind to a second form
Direct handle onto the function we want to test Effectively, can only run one test

Implementation Plan

  1. File Collection
    • Find all files ending in '*test.js' recursively through a folder
    • Store a reference to each file we find
    • After getting a full list of the rest files, execute them one by one
  2. Test environment setup
  3. Test file execution
  4. Report results

 

Notes taken from An Incorrectly Passing Test comment section:

Alireza: Adding async await to it function definition

At 4:10 we add async and await keywords to the function definition of global.it so that node waits for DOM to fully load before testing it. This seems to break the reporting if our tests do not require asynchronous operation - for example if we run the tme command on the sampleproject folder with forEach.test.js and forEachCopy.test.js.

See the report below:

Before Adding async - await

---- test/forEach.test.js
        OK - should sum an array
        OK - beforeEach is ran each time
---- test/forEachCopy.test.js
        OK - should sum an arrays
        OK - beforeEach is ran each times

After adding async await

---- test/forEach.test.js
---- test/forEachCopy.test.js
        OK - should sum an array
        OK - beforeEach is ran each time
        OK - should sum an arrays
        OK - beforeEach is ran each times

Is there a way to rectify the reporting issue?

Stephen: Great catch, I did not see this previously. We could fix this by storing a reference to each 'it' function then invoking them all in a row. Fixed code:

async runTests() {
    for (let file of this.testFiles) {
      console.log(chalk.gray(`---- ${file.shortName}`));
      const beforeEaches = [];
      const its = [];

      global.render = render;
      global.beforeEach = fn => {
        beforeEaches.push(fn);
      };
      global.it = async (desc, fn) => {
        its.push({ desc, fn });
      };

      try {
        require(file.name);
        for (let _it of its) {
          const { desc, fn } = _it;
          for (let _before of beforeEaches) {
            _before();
          }
          try {
            await fn();
            console.log(chalk.green(`\tOK - ${desc}`));
          } catch (err) {
            const message = err.message.replace(/\n/g, '\n\t\t');
            console.log(chalk.red(`\tX - ${desc}`));
            console.log(chalk.red('\t', message));
          }
        }
      } catch (err) {
        console.log(chalk.red(err));
      }
    }
  }

Alireza: Nice one - It's quite a change then to fix this issue. So, we need to implement a queuing system with arrays to make sure tests and console logs are executed in order. One last question - Does global.it function definition need to be async?

global.it = async (desc, fn) => {
  its.push({ desc, fn });
};

I don't see any await keywords within its definition now.

Stephen: You're correct, the 'async' keyword could be dropped with that rewrite Yes, the system gets a bit more complicated by adding in the 'it' queue. However - trust me - this is still a lot simpler than what other testing libraries like Mocha do :)

Alireza: Awesome! Oh yes this is by far way better than Jasmine and Mocha! I think I will try to re-write tme in Python too for my data science applications! I'll post a link to my repo when I do. Thanks for showing us how to create this framework - this is super useful.

One thing I still haven't understood from these testing libs are concepts like spies and hooks, etc. Do you think you can create/extend the course in the future to implement our own spies and hooks? Amazing course and project section again! Thanks a lot Stephen.

Stephen: Spy implementations can be really straightforward, here's a sample:

module.exports = class Spy {
  constructor(target, key) {
    this.target = target;
    this.key = key;
    this.calls = [];

    this._func = target[key];
    target[key] = (...args) => this.exec(...args);
  }

  exec(args) {
    this.calls.push(args);
  }

  reset() {
    this.target[this.key] = this._func;
  }
};

You can modify the 'exec' function to also 'call through' to the original method. This one just stores the provided arguments.

To use this in the TME project, add in the following to the runner.js file:

const Spy = require('./spy');
global.Spy = Spy;
That assumes you created the spy in a 'spy.js' file.

Finally, to use it in a test:

const assert = require('assert');

class Counter {
  constructor() {
    this.count = 0;
  }

  add(value) {
    for (let i = 0; i < value; i++) {
      this.incrementByOne();
    }
  }

  incrementByOne() {
    this.count++;
  }
}

it('can add many values at once', () => {
  const counter = new Counter();
  const spy = new Spy(counter, 'incrementByOne');

  counter.add(10);

  assert.equal(spy.calls.length, 10);
});

 

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published