Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 4867

Show
Ignore:
Timestamp:
08/30/06 06:57:38 (2 years ago)
Author:
madrobby
Message:

script.aculo.us: add more flesh to bdd-style JavaScript testing

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • spinoffs/scriptaculous/src/unittest.js

    r4864 r4867  
    159159        for(var testcase in testcases) { 
    160160          if(/^test/.test(testcase)) { 
    161             this.tests.push(new Test.Unit.Testcase(testcase, testcases[testcase], testcases["setup"], testcases["teardown"])); 
     161            this.tests.push( 
     162               new Test.Unit.Testcase( 
     163                 this.options.context ? ' -> ' + this.options.titles[testcase] : testcase,  
     164                 testcases[testcase], testcases["setup"], testcases["teardown"] 
     165               )); 
    162166          } 
    163167        } 
     
    230234    } 
    231235    return ( 
     236      (this.options.context ? this.options.context + ': ': '') +  
    232237      this.tests.length + " tests, " +  
    233238      assertions + " assertions, " +  
     
    333338    this.assert(object != null, message); 
    334339  }, 
     340  assertType: function(expected, actual) { 
     341    var message = arguments[2] || 'assertType'; 
     342    try {  
     343      (actual.constructor == expected) ? this.pass() :  
     344      this.fail(message + ': expected "' + Test.Unit.inspect(expected) +   
     345        '", actual "' + (actual.constructor) + '"'); } 
     346    catch(e) { this.error(e); } 
     347  }, 
     348  assertNotOfType: function(expected, actual) { 
     349    var message = arguments[2] || 'assertNotOfType'; 
     350    try {  
     351      (actual.constructor != expected) ? this.pass() :  
     352      this.fail(message + ': expected "' + Test.Unit.inspect(expected) +   
     353        '", actual "' + (actual.constructor) + '"'); } 
     354    catch(e) { this.error(e); } 
     355  }, 
    335356  assertInstanceOf: function(expected, actual) { 
    336357    var message = arguments[2] || 'assertInstanceOf'; 
     
    346367      this.fail(message + ": object was an instance of the not expected type"); } 
    347368    catch(e) { this.error(e); }  
     369  }, 
     370  assertReturnsTrue: function(method, obj) { 
     371    var message = arguments[2] || 'assertReturnsTrue'; 
     372    try { 
     373      var m = obj[method]; 
     374      if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)]; 
     375      m() ? this.pass() :  
     376      this.fail(message + ": method returned false"); } 
     377    catch(e) { this.error(e); } 
     378  }, 
     379  assertReturnsFalse: function(method, obj) { 
     380    var message = arguments[2] || 'assertReturnsFalse'; 
     381    try { 
     382      var m = obj[method]; 
     383      if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)]; 
     384      !m() ? this.pass() :  
     385      this.fail(message + ": method returned true"); } 
     386    catch(e) { this.error(e); } 
    348387  }, 
    349388  assertRaise: function(exceptionName, method) { 
     
    388427     
    389428    if(typeof test == 'string') { 
     429      test = test.gsub(/(\.should[^\(]+\()/,'#{0}this,'); 
     430      test = test.gsub(/(\.should[^\(]+)\(this,\)/,'#{1}(this)'); 
    390431      this.test = function() { 
    391432        eval('with(this){'+test+'}'); 
     
    421462}); 
    422463 
     464// *EXPERIMENTAL* BDD-style testing to please non-technical folk 
     465// This draws many ideas from RSpec http://rspec.rubyforge.org/ 
     466 
     467Test.setupBDDExtensionMethods = function(){ 
     468  var METHODMAP = { 
     469    shouldEqual:     'assertEqual', 
     470    shouldNotEqual:  'assertNotEqual', 
     471    shouldEqualEnum: 'assertEnumEqual', 
     472    shouldBeA:       'assertType', 
     473    shouldNotBeA:    'assertNotOfType', 
     474    shouldBeAn:      'assertType', 
     475    shouldNotBeAn:   'assertNotOfType', 
     476    shouldBeNull:    'assertNull', 
     477    shouldNotBeNull: 'assertNotNull', 
     478     
     479    shouldBe:        'assertReturnsTrue', 
     480    shouldNotBe:     'assertReturnsFalse' 
     481  }; 
     482  Test.BDDMethods = {}; 
     483  for(m in METHODMAP) { 
     484    Test.BDDMethods[m] = eval( 
     485      'function(){'+ 
     486      'var args = $A(arguments);'+ 
     487      'var scope = args.shift();'+ 
     488      'scope.'+METHODMAP[m]+'.apply(scope,(args || []).concat([this])); }'); 
     489  } 
     490  [Array.prototype, String.prototype, Number.prototype].each( 
     491    function(p){ Object.extend(p, Test.BDDMethods) } 
     492  ); 
     493} 
     494 
    423495Test.context = function(name, spec, log){ 
     496  Test.setupBDDExtensionMethods(); 
     497   
    424498  var compiledSpec = {}; 
     499  var titles = {}; 
    425500  for(specName in spec) { 
    426501    switch(specName){ 
     
    438513        }); 
    439514        compiledSpec[testName] = body.join('\n'); 
    440     } 
    441   } 
    442   new Test.Unit.Runner(compiledSpec, log || 'testlog'); 
     515        titles[testName] = specName; 
     516    } 
     517  } 
     518  new Test.Unit.Runner(compiledSpec, { titles: titles, testLog: log || 'testlog', context: name }); 
    443519}; 
  • spinoffs/scriptaculous/test/unit/bdd_test.html

    r4863 r4867  
    99  <script src="../../src/unittest.js" type="text/javascript"></script> 
    1010  <link rel="stylesheet" href="../test.css" type="text/css" /> 
    11   <style type="text/css" media="screen"> 
    12   /* <![CDATA[ */ 
    13     #testcss1 { font-size:11px; color: #f00; } 
    14     #testcss2 { font-size:12px; color: #0f0; display: none; } 
    15   /* ]]> */ 
    16   </style> 
    1711</head> 
    1812<body> 
    1913<h1>script.aculo.us Unit test file</h1> 
    20 <p> 
    21   Testing alternate BDD-style syntax for unit tests 
    22 </p> 
    2314 
    2415<!-- Log output --> 
     
    3223var moo = 0; 
    3324 
    34 Test.context("BDD functionality",{ 
     25var assertMethods = []; 
     26for(method in Test.Unit.Assertions.prototype) { 
     27  if(/^assert/.test(method)) assertMethods.push(method); 
     28
     29 
     30var testObj = { 
     31  isNice: function(){ 
     32    return true; 
     33  }, 
     34  isBroken: function(){ 
     35    return false; 
     36  } 
     37
     38 
     39Test.context("BDD-style testing",{ 
    3540   
    3641  setup: function() { 
     
    4348  }, 
    4449   
    45   'setup should run before each specification': function(){ 
     50  'should run setup before each specification': function(){ 
    4651    assert($('d').innerHTML == 'setup!'); 
    4752    assert(moo == 1); 
    4853  }, 
    4954   
    50   'teardown should run after each specification': function(){ 
     55  'should run teardown after each specification': function(){ 
    5156    assert(moo == 1); 
    5257  }, 
    5358   
    54   'assertEqual should pass on equality': function(){ 
     59  'should provide extensions to tie in isSomething object methods': function(){ 
     60    Object.extend(testObj, Test.BDDMethods); 
     61     
     62    testObj.shouldBe('nice'); 
     63    testObj.shouldNotBe('broken'); 
     64  }, 
     65   
     66  'should automatically add extensions to strings': function(){ 
     67    'a'.shouldEqual('a'); 
     68    'a'.shouldNotEqual('b'); 
     69    'a'.shouldNotBeNull(); 
     70    'a'.shouldBeA(String); 
     71     
     72    var aString = 'boo!'; 
     73    aString.shouldEqual('boo!'); 
     74    aString.shouldBeA(String); 
     75    aString.shouldNotBeA(Number); 
     76  }, 
     77   
     78  'should automatically add extensions to numbers': function(){ 
     79    var n = 123;     
     80    n.shouldEqual(123); 
     81    n.shouldNotEqual(4); 
     82     
     83    n.shouldBeA(Number); 
     84    n.shouldNotBeA(Test); 
     85  }, 
     86   
     87  'should automatically add extensions to arrays': function(){ 
     88    ['a'].shouldNotBeA(String); 
     89    [1,2,3].shouldBeAn(Array); 
     90    [1,2,3].shouldEqualEnum([1,2,3]); 
     91  }, 
     92   
     93  'should support the eval() method': function(){ 
     94    eval('2*2').shouldEqual(4); 
     95  }, 
     96   
     97  'should support equality assertion': function(){ 
    5598    assertEqual(1, 1); 
    5699    assertEqual('a', 'a'); 
     
    59102    var x = 1; 
    60103    var y = 1; 
     104    assertEqual(1, x) 
    61105    assertEqual(x, y); 
    62106  }, 
    63107   
    64   'wait should work': function(){ 
     108  'should provide all assertions': function(){ 
     109    assertMethods.each(function(m){ 
     110      assert(typeof this[m] == 'function'); 
     111    }.bind(this));  
     112  }, 
     113   
     114  'should support deferred execution': function(){ 
    65115    wait(10,function(){ 
    66       assertEqual(1,1); 
     116      'a'.shouldEqual('a'); 
    67117    }); 
    68118     
    69119    wait(10,function(){ 
    70       assertEqual(1,1); 
     120      'a'.shouldEqual('a'); 
    71121      wait(10,function(){ 
    72         assertEqual(1,1); 
     122        'a'.shouldEqual('a'); 
    73123        wait(10,function(){ 
    74           assertEqual(1,1); 
     124          'a'.shouldEqual('a'); 
    75125        }); 
    76126      }); 
  • spinoffs/scriptaculous/test/unit/unittest_test.html

    r4800 r4867  
    4545<script type="text/javascript" language="javascript" charset="utf-8"> 
    4646// <![CDATA[ 
     47 
     48  var testObj = { 
     49    isNice: function(){ 
     50      return true; 
     51    }, 
     52    isBroken: function(){ 
     53      return false; 
     54    } 
     55  } 
    4756 
    4857  new Test.Unit.Runner({ 
     
    105114      assertNotInstanceOf(Effect.Parallel, new Effect.Opacity('testcss1',{sync:true}), "(note: fails with firefox 1.0.X, fixed in Deer Park)");    
    106115    }}, 
     116     
     117    testAssertReturns: function() { with(this) { 
     118       
     119      assertReturnsTrue('isNice',testObj); 
     120      assertReturnsFalse('isBroken',testObj); 
     121       
     122      assertReturnsTrue('nice',testObj); 
     123      assertReturnsFalse('broken',testObj); 
     124       
     125    }}, 
    107126   
    108127    testAssertVisible: function() { with(this) {