UNPKG

jupyter-js-auto-test

Version:

Auto scan files under the directory and run test in them

233 lines (208 loc) 8.74 kB
/** * This project could scan files under the specific directory and run tests in them. The test * report could be print to the terminal or pass to the caller via Callback. * * It Requires package of parse-commandline-arguments * * How to write test: * 1. write test in other files and export all tests * 2. this file will scan this directory to find all tests and test them and * 3. print out test report if these are all reports, if not, callback the test results * * How to run test * There are two ways to run test: * 1. Run all test: node ./ --local * 2. Run all test in one specific file: node ./ --only filename --local * 3. Run specific test in one specific file: node ./ --only filename:functions[,function2,function3,...] --local * or it could be call as a node module. * const { setAndRun } = require('jupyter-js-auto-test') * setAndRun(path[, filename, [function1, function2,...]]) * * To exclude files, add the filename in the excludeFiles. * Do not delete 'index.js' as it should always be excluded. * or requrie('jupyter-js-auto-test).setExcludeFiles(file1, file2, file3,...) * * todo: * 1. in the final test report, failed messages should be formate in a proper way * Done 2. accept --path to find test in other directory * 3. output test report to a file as an option * Done 4. make it as a node module and a node runnable file, should be able to be called by commandline and node require() * 5. pre-testFuncs could accept functions other than test config */ const chalk = require('chalk') const Promise = require('bluebird') const { splitFilename, consolePrintTestResultsReportAndCallbackIfNeeded, TestResults } = require('./helpers') const excludeFiles = ['index.js', 'config.js', 'helpers.js'] let testResultsCallback = null let isOnlyMode = false let only = { filename: '', functions: [] } let path = '' let acceptedArguments = { only: '', path: '', local: '', } module.exports = { registerTestResultsCallback, setAndRun, setExcludeFiles, TestFunctionConfig: require('./helpers').TestFunctionConfig, readConfigAndRun: require('./helpers').readConfigAndRun, } // --only filename:function1,function2 const cmdargs = require('jupyter-parse-commandline-arguments').parseCommandlineArguments(process.argv, acceptedArguments) if (cmdargs.local) { runLocal() } function setExcludeFiles(...filenames) { excludeFiles = filenames } function setAndRun(path_v, filename, functions) { path = path_v.endsWith('/') ? path_v : path_v + '/' if (filename) { isOnlyMode = true only.filename = filename only.functions = functions || [] } if (cmdargs && cmdargs.local) { } else { startTest() } } function runLocal() { if (cmdargs.only && cmdargs.only !== true) { params = cmdargs.only.split(':') isOnlyMode = true only.filename = params[0] only.functions = params[1] ? params[1].split(',') : [] console.log(chalk.bgYellow.black("Only mode is on")) console.log("Only test file", chalk.bgCyan(only.filename), "for ", only.functions.length === 0 ? "all test functions" : "functions:" + JSON.stringify(only.functions)) } if ((cmdargs.path && cmdargs.path === true) || !cmdargs.path) { path = './' } else { path = cmdargs.path } startTest() } function startTest() { console.log("Starting scanning test files in ", path) require('fs').readdir(path, (error, items) => { if (!error) { let tests = {} let testResults = new TestResults() items.forEach(item => { if (excludeFiles.indexOf(item) < 0) { const { filename, extension } = splitFilename(item) if (extension === 'js') { if ((isOnlyMode && (only.filename === filename || only.filename === filename + '.js')) || !isOnlyMode) { tests[filename] = require(path + filename) testResults.totalTest += Object.keys(tests[filename]).length } } } }) if (!isOnlyMode) { console.log(chalk.cyan("Totally have " + testResults.totalTest + ' tests')) } else { console.log(chalk.cyan("Totally have no more than " + only.functions.length + ' tests')) } testResults.totalTest = 0 // totalTest should be count as the test running console.log("Start testing...") let promises = [] Object.keys(tests).forEach(key => { promises.push(new Promise((resolve, reject) => { performTest(key, tests[key], (passed, failed, failedMessages) => { if (isOnlyMode) { // remove tested functions from the only.functions to know which one in only.functions does not test passed.forEach(aPassed => { only.functions.splice(only.functions.indexOf(aPassed), 1) }) failed.forEach(aFailed => { only.functions.splice(only.functions.indexOf(aFailed), 1) }) } testResults.passed[key] = passed testResults.failed[key] = failed testResults.passedCount += passed.length testResults.failedCount += failed.length testResults.totalTest += passed.length + failed.length testResults.failedMessages[key] = failedMessages resolve() }) })) }) Promise.all(promises).then(() => { if (only.functions.length > 0) { console.log(chalk.yellow('Cannot find these functions '), only.functions) } consolePrintTestResultsReportAndCallbackIfNeeded(testResults, testResultsCallback) }) } else { console.log(chalk.red(JSON.stringify(error))) } }) } function setPath(path) { cmdargs.path = path return this } function performTest(testname, tests, callback) { const keys = Object.keys(tests) if (!isOnlyMode) { console.log("Start to test", testname , chalk.bgCyan(" having " + keys.length + " tests")) } else { console.log("Start to test", testname , chalk.bgCyan(" having no more than " + only.functions.length + " tests")) } let testResults = {} let promises = [] keys.forEach(key => { if ((isOnlyMode && ((only.functions.length > 0 && only.functions.indexOf(key) >=0) || (only.functions.length <= 0))) || (!isOnlyMode)) { promises.push(new Promise((resolve, rejct) => { tests[key]((res, failedMessage) => { testResults[key] = {res, failedMessage} resolve() }) })) } }) Promise.all(promises).then(() => { let passed = [] let failed = [] let failedMessages = {} Object.keys(testResults).forEach((key) => { if (testResults[key].res) { passed.push(key) } else { failed.push(key) if (testResults[key].failedMessage) { failedMessages[key] = testResults[key].failedMessage } } }) if (passed.length > 0) { console.log(chalk.green(testname + " passed:")) console.log(passed) } if (failed.length > 0) { console.log(chalk.red(testname + " failed:")) console.log(failed) } if (passed.length > 0) { console.log(chalk.green(testname + " subtotal " + passed.length + " passed")) } if (failed.length > 0) { console.log(chalk.red(testname + " subtotal " + failed.length + " failed")) } callback ? callback(passed, failed, failedMessages) : '' }) } function registerTestResultsCallback(callback) { testResultsCallback = callback return this }