Last active
February 7, 2016 23:57
-
-
Save azz/6dadf730b724326eec88 to your computer and use it in GitHub Desktop.
Typescript Test Runner
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class TestUtils { | |
// A factory function | |
static makeTestDecorator(prop: string, modifierFn?: (...fnArgs) => any) { | |
// Apply modifierFn if it exists, and | |
// Flatten single-element arrays to a value | |
const handle = (...values) => { | |
if (modifierFn) | |
return modifierFn(...values); | |
if (values.length === 1) | |
return values[0]; | |
return values; | |
} | |
// A function that produces our decorator | |
return (...decorations: any[]) => { | |
// The actual decorator function | |
return (target, key?) => { | |
if (key) { // Target is a method | |
_.extend(target[key], {[prop]: handle(...decorations)}) | |
} else { // Target is a class | |
// This __test prop is applied to the class object, | |
// not the instance object. | |
target.__test = { | |
[prop]: handle(...decorations) | |
}; | |
} | |
} | |
} | |
} | |
} | |
const TestDecorators = { | |
bugs: TestUtils.makeTestDecorator('bugs'), | |
pull: TestUtils.makeTestDecorator('pull'), | |
it: TestUtils.makeTestDecorator('it'), | |
describe: TestUtils.makeTestDecorator('describes'), | |
repro: TestUtils.makeTestDecorator('repro', (steps) => { | |
return steps | |
.split('\n') | |
.map(l => l.trim()) | |
.filter(l => !!l.length) | |
.join('\n') | |
}) | |
} | |
abstract class TestBase { | |
test: { describes?: string }; | |
constructor() { | |
// Copy the __test prop from the class to the instance | |
this.test = this.constructor['__test']; | |
} | |
isTest(name: string) { | |
return /^test/.test(name) && typeof this[name] === "function"; | |
} | |
} | |
// a source file | |
function add(x, y) { | |
return x - y; // intentional error | |
} | |
// in a test file... | |
const {bugs, pull, repro, it, describe} = TestDecorators; | |
@describe("add function") | |
class TestClass extends TestBase { | |
// ... | |
@it("should evaluate 0+0 === 0") | |
public testZeroPlusZero() { | |
return add(0, 0) === 0; | |
} | |
@repro(` | |
Call add. | |
Pass two non-zero numbers. | |
`) | |
@bugs(1235, 3444) | |
@pull(343) | |
@it("should evaluate 1+1 === 2") | |
public testICanAdd() { | |
return add(1, 1) === 2; | |
} | |
} | |
// in the test runner... | |
class TestRunner { | |
runTests(testInstance: TestBase) { | |
console.info('* ', testInstance.test.describes); | |
for (let testName in testInstance) { | |
if (!testInstance.isTest(testName)) | |
continue; | |
// run test | |
let success = !!testInstance[testName](); | |
// collect metadata | |
let results = _.extend({}, testInstance[testName].test, { | |
testName, success, parent: testInstance.parent | |
}); | |
console[success ? 'log' : 'warn']('\t- ', results.it, results); | |
} | |
} | |
} | |
// Main | |
(() => { | |
let instance = new TestClass; | |
let runner = new TestRunner; | |
console.log('Running tests...'); | |
runner.runTests(instance); | |
})(); |
Author
azz
commented
Feb 6, 2016
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment