Created
February 18, 2012 14:20
Revisions
-
VoQn revised this gist
Feb 18, 2012 . 1 changed file with 68 additions and 2 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -153,7 +153,9 @@ var Arbitrary = (function( env ){ } function fromGen( generator ) { return { arbitrary: generator }; } })( TestEnvironment ); @@ -173,7 +175,29 @@ function elements_of( list ){ } function one_of( generators ) { var len = generators.length; return Arbitrary.create( function(){ return generators[ genIndex() ].arbitrary(); }); function genIndex() { var i = Math.floor( Math.random() * len ); return Math.min( i, len - 1 ); } } function frequency( weighted ) { return one_of( expand( weighted )); function expand( wg ){ var gs = []; for (var i = 0, l = wg.length; i < l; i++){ var j = 0; while( j < wg[i][0] ){ gs.push(wg[i][1]); j++; } } return gs; } } function where( before, proc ) { @@ -236,6 +260,45 @@ function runTest( tests ) { } } function listOf1( generator ){ var E = TestEnvironment; return Arbitrary.create(function(){ var vs = []; var i = 0; var l = Math.ceil( Math.random() * E.seed * 2 ) + 1; while(i < l){ vs[i] = generator.arbitrary(); i++; } return vs; }); } function fmap( f, g ){ if ( !g.arbitrary ) { throw new NotImplementException('Arbitrary', 'generator'); } return Arbitrary.create( function(){ var generated = g.arbitrary(); return f( generated ); }); } var genPathInfo = (function(){ var alphabet = elements_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); var ascii = elements_of("/#.:-_?="); function concat( cs ){ var str = ''; for( var i = 0, l = cs.length; i < l; i++){ str += cs[i]; } return str; } return fmap( concat, listOf1(frequency( [[7, alphabet], [1, ascii]] ))); })(); /** * Test */ @@ -257,4 +320,7 @@ function runTest( tests ) { })) ]) ); // Example: valid PATH INFO String Generator // (Include XSS, SQL Injection Security risk) // C.verboseCheck( C.forAll( genPathInfo, function( p ){ return true; })); })(); -
VoQn revised this gist
Feb 18, 2012 . 1 changed file with 52 additions and 21 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,4 @@ var TestEnvironment = (function(){ return { seed: 1, @@ -75,16 +76,15 @@ var TestEnvironment = (function(){ return Math.pow( 2, Math.round( this.seed / 2 ) ); }, check: function( prop, verbose ) { var i = 0, result, msg; while ( i++ < this.count ) { prop(); this.current.evaluate( verbose, this.result ); this.seed++; } result = this.result.get(); this.clean(); return result; } }; @@ -109,9 +109,9 @@ var JsCheck = (function(){ function check( prop, supplier, verbose ){ if ( !supplier ) { // call forAll return E.check( prop, verbose ); } else { // prop is simple function, supplier is apply generated args for prop return E.check( supplier( prop ), verbose ); } } @@ -125,8 +125,12 @@ var JsCheck = (function(){ E.current.set( args, prop ); }; }, quickCheck: function( test, supplier ) { return check( test, supplier ); }, verboseCheck: function( test, supplier ) { return check( test, supplier, true ); } }; })(); @@ -207,23 +211,50 @@ function types(/* Arbitrary types */){ } } function testGroup( label, tests ) { return function(){ var disc = [label + ':']; for( var i = 0, l = tests.length; i < l; i++ ) { disc[i+1] = ' ' + tests[i](); } return disc; } } function testProperty( label, testable, type ){ return function(){ var result = JsCheck.quickCheck( testable, type ); var disc = label + ': [' + result.msg + ']'; return disc; } } function runTest( tests ) { var item = tests(); for( var i = 0, l = item.length; i < l; i ++){ console.log( item[i] ); } } /** * Test */ (function() { var C = JsCheck, A = Arbitrary, list, tests; list = "abcdefghijklmnopqrstuvwxyz"; runTest( testGroup('example quickcheck tests', [ testProperty( 'if x != y, x - y != y - x', function( x, y ) { return where( x != y, function(){ return x - y != y - x; }); }, types(A.Integer, A.Integer)) , testProperty( 'any char one of [a-z] is include [a-z]', C.forAll( elements_of( list ), function( x ) { return -1 < list.indexOf( x ); })) ]) ); })(); -
VoQn revised this gist
Feb 18, 2012 . 1 changed file with 0 additions and 9 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,13 +1,4 @@ var TestEnvironment = (function(){ return { seed: 1, count: 100, -
VoQn revised this gist
Feb 18, 2012 . 1 changed file with 46 additions and 14 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,4 @@ var TestEnvironment = (function(){ function createArgs( generator, prop ){ var as = []; @@ -17,8 +15,7 @@ var TestEnvironment = (function(){ args: [], isPassed: false, isSkipped: false, set: function( args, prop ){ var result = prop.apply( this, args ); this.args = args; if ( !!result.wasSkip ) { @@ -111,17 +108,34 @@ var NotImplementException = function( _interface, _identifier ){ var JsCheck = (function(){ var E = TestEnvironment; function createArgs( generator, prop ){ var as = []; for ( var i = 0, l = prop.length; i < l; i++ ) { as[i] = generator.arbitrary(); } return as; }; function check( prop, supplier, verbose ){ if ( !supplier ) { // call forAll E.check( prop, verbose ); } else { // prop is simple function, supplier is apply generated args for prop E.check( supplier( prop ), verbose ); } } return { forAll: function( generator, prop ){ if ( !generator.arbitrary ){ throw new NotImplementException('Arbitrary', 'generator'); } return function(){ var args = createArgs( generator, prop ); E.current.set( args, prop ); }; }, quickCheck: function( test, supplier ) { check( test, supplier ); }, verboseCheck: function( test, supplier ) { check( test, supplier, true ); } }; })(); @@ -187,20 +201,38 @@ function where( before, proc ) { } } function types(/* Arbitrary types */){ var arbs = arguments, args = [], E = TestEnvironment; return function( prop ){ return function() { for (var i = 0, l = arbs.length; i < l; i++) { if ( !arbs[i].arbitrary ) { throw new NotImplementException('Arbitrary', 'Type hinting'); } args[i] = arbs[i].arbitrary(); } E.current.set( args, prop ); } } } /** * Test */ (function() { var C = JsCheck, A = Arbitrary; C.quickCheck( function( x, y ) { return where( x != y, function(){ return x - y != y - x; }); }, types(A.Integer, A.Integer)); var list = "abcdefghijklmnopqrstuvwxyz"; C.quickCheck( C.forAll( elements_of( list ), function( x ) { return -1 < list.indexOf( x ); })); })(); -
VoQn created this gist
Feb 18, 2012 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,206 @@ /* * quickcheck.js Prototyping */ var TestEnvironment = (function(){ function createArgs( generator, prop ){ var as = []; for ( var i = 0, l = prop.length; i < l; i++ ) { as[i] = generator.arbitrary(); } return as; }; return { seed: 1, count: 100, current: { args: [], isPassed: false, isSkipped: false, set: function( generator, prop ){ var args = createArgs( generator, prop ); var result = prop.apply( this, args ); this.args = args; if ( !!result.wasSkip ) { this.isSkipped = result.wasSkip; } else { this.isSkipped = false; this.isPassed = result; } }, evaluate: function( verbose, score ){ var mark = '', shouldView = !( this.isSkipped || this.isPassed ); if ( this.isSkipped ) { mark = 'Skipped:'; score.skipped++; } else if ( this.isPassed ) { mark = 'Passed:'; score.passed++; } else { mark = 'Faild:'; score.failure++; } if ( verbose || shouldView ) { console.log( mark ); for( var i = 0, l = this.args.length; i < l; i++ ){ console.log( this.args[i] ); } } } }, result: { passed: 0, failure: 0, skipped: 0, get: function() { var _ = this, total = _.passed + _.skipped + _.failure, msg = '', mark = '+++', isPassed = true; if ( total == _.passed ) { msg = 'OK, passed ' + _.passed + ' tests.'; } else if ( total == _.passed + _.skipped ) { msg = 'OK, passed ' + _.passed + ' tests (skipped ' + _.skipped + ' tests)'; } else { mark = '***' msg = 'Faild! ' + _.fail + ' test case.' + '(passed ' + _.passed + (_.skipped ? ' )' : ', skipped ' + _.skipped + ' )'); } return { score: _, mark: mark, msg: msg, isPassed: isPassed } } }, clean: function(){ this.seed = 0; this.current.args = []; this.result.passed = 0; this.result.failure = 0; this.result.skipped = 0; }, getRange: function(){ return Math.pow( 2, Math.round( this.seed / 2 ) ); }, check: function( prop, verbose ) { var i = 0, result;// _ = this; while ( i++ < this.count ) { prop(); this.current.evaluate( verbose, this.result ); this.seed++; } result = this.result.get(); console.log( result.mark + ' ' + result.msg ); this.clean(); } }; })(); var NotImplementException = function( _interface, _identifier ){ var error = new Error(); error.name = 'NotImplementException'; error.message = _identifier + ' is not instance of ' + _interface; return error; }; var JsCheck = (function(){ var E = TestEnvironment; return { forAll: function( generator, prop ){ if ( !generator.arbitrary ){ throw new NotImplementException('Arbitrary', 'generator'); } return function(){ E.current.set( generator, prop ); }; }, quickCheck: function( test ) { E.check( test ); }, verboseCheck: function( test ) { E.check( test, true ); } }; })(); var Arbitrary = (function( env ){ return { Integer: fromGen( genInt ), Double: fromGen( genNumber ), create: fromGen }; function genNumber(){ var sign = Math.random() < 0.5 ? (-1) : 1, seed = Math.random(), width = env.getRange(); return sign * seed * width; } function genInt(){ return Math.round( genNumber() ); } function fromGen( generator ) { return { arbitrary: generator }; } })( TestEnvironment ); Arbitrary.Bool = elements_of([false, true]); function elements_of( list ){ var len = list.length; return Arbitrary.create( function(){ return list[ genIndex() ]; }); function genIndex() { var i = Math.floor( Math.random() * len ); return Math.min( i, len - 1 ); } } function one_of( generators ) { return elements_of( generators ); } function where( before, proc ) { if ( shouldSkip( before ) ) { return { wasSkip: true } } return proc(); function shouldSkip( cond ) { if ( cond instanceof Array ) { for (var i = 0, l = cond.length; i < l; i ++){ if ( !cond[i] ) { return true; } } } else { return !cond; } return false; } } /** * Test */ (function() { var jc = JsCheck; jc.quickCheck( jc.forAll( Arbitrary.Integer, function( x, y ) { return where( x != y, function(){ return x - y != y - x; }); })); var list = "abcdefghijklmnopqrstuvwxyz"; jc.quickCheck( jc.forAll( elements_of( list ), function( x ) { return -1 < list.indexOf( x ); })); })();