Test Runner

by Marc Malignan

HTML

<div id="runner"></div>

SCSS

.TestRunner {
  width: 400px;
  margin: 0 auto;
  padding: 20px;
  text-align: center;
  font-family: Arial;
  font-size: 14px;
  
  &-res {
    width: 60%;
    margin: 20px auto 0;
    text-align: left;
    border: 1px solid #777;
    border-collapse: collapse;
    
    th {
      background: #777;
      color: white;
    }
    
    th, td {
      padding: 6px 8px;
    }
    
    th:nth-child(2),
    td:nth-child(2){
      text-align: right;
    }
    
    tr:nth-child(2n) {
      background: #eee;
    }
  }
}

JavaScript

class TestRunner {
	constructor(options) {
  	Object.assign(this, options);
  	
    this.nb = options.nb || 1;
    this.methods = options.methods || [];
    
    this.render();
    this.clear();
    
    $(this.el).on('change', '.TestRunner-nb', this.updateNb.bind(this));
  	$(this.el).on('click', '.TestRunner-run', this.run.bind(this));
    $(this.el).on('click', '.TestRunner-clear', this.clear.bind(this));
  }
  
  updateNb() {
  	const val = $(this.el).find('.TestRunner-nb').val() || 0;
  	this.nb = Number(val);
  }
  
  test({ fn, options, fnOptions }) {
  	let opts = (fnOptions ? fnOptions(this) : options) || {};
    const start = Date.now();
    fn(opts);
    this.res(fn.name, start);
  }
  
  res(title, start) {
  	const res = `
    	<tr>
      	<td>${title}</td>
        <td>${Date.now()-start}ms</td>
			</tr>
    `;
    $(this.el).find('.TestRunner-res')
    	.show()
    	.find('tbody').append(res);
  }

  clear() {
    $(this.el).find('.TestRunner-res')
    	.hide()
    	.find('tbody').empty();
  }

  run() {
    this.clear();
    this.methods.forEach(this.test.bind(this));
  }
  
  render() {
  	$(this.el).append(`
    	<div class="TestRunner">
        <input class="TestRunner-nb" type="number" value="${this.nb}" />
        <button class="TestRunner-run">RUN</button>
        <button class="TestRunner-clear">CLEAR</button>
        <table class="TestRunner-res">
        	<thead>
          	<th>Method</th>
            <th>Time</th>
          </thead>
          <tbody></tbody>
        </table>
			</div>
    `);
  }
};

// tested methods
const indexOf = ({ arr }) => arr.indexOf(2);
const find = ({ arr }) => arr.find(el => el.id === 2);
const mapIndexOf = ({ arr }) => arr.map(el => el.id).indexOf(2);

// option methods
const buildArr = ({nb}) => ({ arr: Array(nb).fill(1) });
const buildArrObj = ({nb}) => ({ arr: Array(nb).fill({ id: 1 }) });

// init runner
const runner = new TestRunner({
	el: '#runner',
  nb: 1000000,
  methods: [
    { fn: indexOf,...