now test.js is require-able...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2020-06-01 04:09:40 +03:00
parent 22d09831d0
commit 00711e5557
2 changed files with 90 additions and 18 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "ig-object", "name": "ig-object",
"version": "5.0.4", "version": "5.0.5",
"description": "", "description": "",
"main": "object.js", "main": "object.js",
"scripts": { "scripts": {

106
test.js
View File

@ -1,5 +1,38 @@
/********************************************************************** /**********************************************************************
* *
* This is an experimental test framework...
*
* The idea is that we can split the tests into:
* - setups
* Construct as set of testable things.
* On this stage the construction process can be tested.
* - modifiers
* Take a set of testable things as returned by a setup/modifier and
* modify them or produce new things based on the old ones.
* Here the modification process can be tested.
* - tests
* Take a set of things as returned by a setup/modifier and run a
* set of tests on them.
* This stage tests a specific state and interactions within it.
* - specific cases
* A specific manual construction of a thing, its modification and
* test.
*
* Testing is done by building/running a number chains, starting with a
* setup, then chaining the results through zero or more modifiers and
* finally into a test.
*
* The actual testing is dune via assert(..) functions and is not
* restricted to the test stage.
*
*
* NOTE: tests can be used as modifiers if they modify state and return
* the modified input.
*
*
* XXX thins to simplify:
* - would be nice if the actual code could be readable...
* - can we automate assert callas?
* *
* *
* *
@ -20,7 +53,7 @@ var object = require('./object')
// $ export VERBOSE=1 && node test.js // $ export VERBOSE=1 && node test.js
// or set this manually after require('./test') but before running // or set this manually after require('./test') but before running
// the runner(..) // the runner(..)
// XXX this may change in the future... // NOTE: this may change in the future...
module.VERBOSE = process ? module.VERBOSE = process ?
process.env.VERBOSE process.env.VERBOSE
: false : false
@ -67,7 +100,8 @@ var makeAssert = function(pre, stats){
//--------------------------------------------------------------------- //---------------------------------------------------------------------
var setups = { var setups =
module.setups = {
// basic constructor and inheritance... // basic constructor and inheritance...
basic: function(assert){ basic: function(assert){
var X, Y, A, B, C var X, Y, A, B, C
@ -176,6 +210,11 @@ var setups = {
return res return res
}, {}) }, }, {}) },
/*/ XXX methods (instance/constructor)...
methods: function(assert){
return {} },
//*/
/*/ XXX mixins... /*/ XXX mixins...
mixin: function(assert){ mixin: function(assert){
return { return {
@ -184,7 +223,9 @@ var setups = {
//*/ //*/
} }
var modifiers = {
var modifiers =
module.modifiers = {
// default... // default...
'as-is': function(assert, setup){ 'as-is': function(assert, setup){
return setup }, return setup },
@ -229,11 +270,20 @@ var modifiers = {
e, e,
{__created_raw: true}) }) {__created_raw: true}) })
return res }, return res },
// sanity checks...
// NOTE: these should have no side-effects but since we can run
// them why not run them ;)
get methods(){ return tests.methods },
get constructor_methods(){ return tests.constructor_methods },
get callables(){ return tests.callables },
} }
var tests = { var tests =
module.tests = {
// instance creation... // instance creation...
instance: modifiers.instance, instance: modifiers.instance,
instance_no_new: modifiers.instance_no_new, instance_no_new: modifiers.instance_no_new,
@ -244,6 +294,7 @@ var tests = {
return {} }, return {} },
//*/ //*/
// methods...
methods: function(assert, setup){ methods: function(assert, setup){
instances(setup) instances(setup)
.forEach(function([k, o]){ .forEach(function([k, o]){
@ -253,7 +304,7 @@ var tests = {
// skip special methods... // skip special methods...
&& !m.startsWith('__') && !m.startsWith('__')
&& o[m]() }) }) && o[m]() }) })
return {} }, return setup },
constructor_methods: function(assert, setup){ constructor_methods: function(assert, setup){
constructors(setup) constructors(setup)
.forEach(function([k, O]){ .forEach(function([k, O]){
@ -263,17 +314,20 @@ var tests = {
// skip special methods... // skip special methods...
&& !m.startsWith('__') && !m.startsWith('__')
&& O[m]() }) }) && O[m]() }) })
return {} }, return setup },
// callables...
callables: function(assert, setup){ callables: function(assert, setup){
return instances(setup) instances(setup)
.map(function([k, o]){ .forEach(function([k, o]){
// NOTE: not all callables are instances of Function... // NOTE: not all callables are instances of Function...
typeof(o) == 'function' typeof(o) == 'function'
&& (o.__non_function ? && (o.__non_function ?
assert(!(o instanceof Function), 'non-instanceof Function', k) assert(!(o instanceof Function), 'non-instanceof Function', k)
: assert(o instanceof Function, 'instanceof Function', k)) : assert(o instanceof Function, 'instanceof Function', k))
return typeof(o) == 'function' typeof(o) == 'function'
&& assert(o(), 'call', k) }) }, && assert(o(), 'call', k) })
return setup },
} }
@ -281,7 +335,8 @@ var tests = {
// //
// NOTE: it is a good idea to migrate tests from here into the main // NOTE: it is a good idea to migrate tests from here into the main
// framework so as to be able to use them on more setups... // framework so as to be able to use them on more setups...
var cases = { var cases =
module.cases = {
'example': function(assert){ 'example': function(assert){
assert(true, 'example.') assert(true, 'example.')
}, },
@ -301,11 +356,15 @@ var cases = {
// case() // case()
// for each case in cases // for each case in cases
// //
var runner = function(){ var runner =
module.runner =
function(){
var started = Date.now()
var stats = { var stats = {
tests: 0, tests: 0,
assertions: 0, assertions: 0,
failures: 0, failures: 0,
time: 0,
} }
// tests... // tests...
Object.keys(tests) Object.keys(tests)
@ -329,23 +388,36 @@ var runner = function(){
.forEach(function(c){ .forEach(function(c){
stats.tests += 1 stats.tests += 1
cases[c]( makeAssert(`case:${c}:`, stats) ) }) cases[c]( makeAssert(`case:${c}:`, stats) ) })
// runtime...
stats.time = Date.now() - started
// stats... // stats...
console.log('Tests run:', stats.tests, console.log('Tests run:', stats.tests,
'Assertions:', stats.assertions, 'Assertions:', stats.assertions,
'Failures:', stats.failures) 'Failures:', stats.failures,
` (${stats.time}ms)`)
return stats } return stats }
//--------------------------------------------------------------------- //---------------------------------------------------------------------
var stats = runner() // test if we are run from command line...
//
// NOTE: normally this would be require.main === module but we are
// overriding module in the compatibility wrapper so we have to do
// things differently...
//
// XXX update wrapper to make this simpler...
if(typeof(__filename) != 'undefined'
&& __filename == (require.main || {}).filename){
var stats = module.stats = runner()
// report error status to the OS... // report error status to the OS...
process process
&& process.exit(stats.failures) && process.exit(stats.failures)
}