Blog

Luis Majano

October 15, 2013

Spread the word


Share your thoughts

We are so pleased to bring you another addition to our Box collection of products: TestBox.  TestBox is a next generation testing framework for ColdFusion that is based on BDD (Behavior Driven Development) for providing a clean obvious syntax for writing tests. It contains not only a testing framework, runner, assertions and expectations library but also integrates with MockBox for mocking and stubbing. It also supports xUnit style of testing and MXUnit compatibilities.  At this point TestBox has been released as a 1.0.0 Alpha and can be downloaded from our main downloads page and it has been also integrated into our "development" branch for the ColdBox platform as well.  As you will see, TestBox also leverages Closures extensively to provide nice clear syntaxes in your tests.

Features At A Glance

  • Here are a simple listing of features TestBox brings to the table:
  • BDD style testing
  • xUnit style testing
  • Testing life-cycle methods
  • MockBox integration for mocking and stubbing
  • Ability to extend and create custom test runners
  • Ability to extend and create custom test reporters
  • Extensible reporters, bundled with tons of them:
  •     JSON
  •     XML
  •     JUnit 4 XML
  •     Text (80's style)
  •     Console
  •     TAP (Test Anything Protocol)
  •     Simple HTML
  •     Min - Minimalistic Heaven
  •     Raw
  • Asynchronous testing
  • Multi-suite capabilities
  • Test skipping
  • Suite skipping
  • Dynamic skipping support via runtime executions
  • Test one or more suites exclusively
  • Test one or more tests/specs exclusively
  • Test labels and tagging
  • Clickable suite titles to filter test execution
  • Direct MXUnit replacement
  • Much more!

Like with anything we do, it is completely documented in three separate guides:

  1. TestBox Complete Docs
  2. TestBox BDD Primer
  3. TestBox xUnit Primer

Finally, TestBox is also a direct drop-replacement for MXUnit as well.  We have fully documented how you can re-use your tests within TestBox and also migrate them if you need to.  Check out some cool BDD action you will be able to do with TestBox:

describe("Some Included TestBox Matchers:", function() {

     describe("The 'toBe' matcher", function() {
          it("works for simple values", function() {
               coldbox = 1;
               expect( coldbox ).toBe( 1 );
               expect( coldbox ).notToBe( 5 );
          });

          it("works for complex values too (arrays,structs,queries,objects)", function() {
               expect( [1,2] ).toBe( [1,2] );
               expect( { name="luis", awesome=true} ).toBe( { awesome=true, name="luis" } );
               expect( this ).toBe( this );
               expect( queryNew("") ).toBe( queryNew("") );
          });
     });

     it("The 'toBeWithCase' matches strings with case equality", function() {
          expect( 'hello' ).toBeWithCase( 'hello' );
          expect( 'hello' ).notToBeWithCase( 'HELLO' );
     });

     it("The 'toBeTrue' and 'toBeFalse' matchers are used for boolean operations", function() {
          coldbox_rocks = true;
          expect( coldbox_rocks ).toBeTrue();
          expect( !coldbox_rocks ).toBeFalse();
     });

     it("The 'toBeNull' expects null values", function() {
          foo = "bar";
          expect( javaCast("null", "") ).toBeNull();
          expect( foo ).notToBeNull();
     });

     it("The 'toBeInstanceOf' expects the object to be of the same class or inheritance or implementation", function() {
          expect( new coldbox.system.testing.Assertions ).toBeInstanceOf( 'coldbox.system.testing.Assertions' );
          expect( this ).notToBeInstanceOf( 'coldbox.system.testing.MockBox' );
     });

     it("The 'toMatch' matcher is for regular expressions with case sensitivity", function() {
          message = 'foo man choo';

          expect( message ).toMatch( '^foo' );
          expect( message ).toMatch( '(man)' );
          expect( message ).notToMatch( 'superman' );
     });

     it("The 'toMatchNoCase' matcher is for regular expressions with no case sensitivity", function() {
          message = 'foo man choo';

          expect( message ).toMatch( '^FOO' );
          expect( message ).toMatch( '(MAN)' );
          expect( message ).notToMatch( 'SuperMan' );
     });

     describe("The 'toBeTypeOf' matcher evaluates using the CF isValid() function", function() {
          it("works with direct calls", function() {
               expect( [1,2] ).toBeTypeOf( 'Array' );
               expect( { name="luis", awesome=true} ).toBeTypeOf( 'struct' );
               expect( this ).toBeTypeOf( 'component' );
               expect( '03/01/1990' ).toBeTypeOf( 'usdate' );
          });

          it("works with dynamic calls as well", function() {
               expect( [1,2] ).toBeArray();
               expect( { name="luis", awesome=true} ).toBeStruct();
               expect( this ).toBeComponent();
               expect( '03/01/1990' ).toBeUsDate();
          });
     });

     it("The 'toBeEmpty' checks emptyness of simple or complex values", function() {
          expect( [] ).toBeEmpty();
          expect( { name="luis", awesome=true} ).notToBeEmpty();
          expect( '' ).toBeEmpty();
     });

     it("The 'toHaveLength' checks size of simple or complex values", function() {
          expect( [] ).toHaveLength( 0 );
          expect( { name="luis", awesome=true} ).toHaveLength( 2 );
          expect( 'Hello' ).toHaveLength( 5 );
     });

     it("The 'toHaveKey' checks for existence of keys in structs", function() {
          expect( { name="luis", awesome=true} ).toHaveKey( 'name' );
     });

     it("The 'toHaveDeepKey' checks for existence of keys anywhere in structs", function() {
          expect( { name="luis", { age=35, awesome=true } } ).toHaveKey( 'age' );
     });

     it("The 'toThrow' checks if the actual call fails", function() {
          expect( function(){
               new calculator().divide( 40, 0 );
          }).toThrow();

          expect( function(){
               new calculator().divide( 40, 0 );
          }).toThrow( regex="zero" );
     });

});

What's to come

TestBox is being actively developed and we need your feedback in order to do a full release.  We still have some issues pending with MXUnit compatibility, asynchronous testing, NodeJS and GruntJS integration (Tha'ts Right!), and much more.  So subscribe to our mailing list to stay on top of things or this blog's RSS feed.

Add Your Comment

Recent Entries

Why Migrate from ColdFusion to BoxLang? 10 Reasons to Modernize Your CFML Applications

Why Migrate from ColdFusion to BoxLang? 10 Reasons to Modernize Your CFML Applications

For organizations running applications built with ColdFusion or CFML, modernization often comes with an uncomfortable question:

“Do we keep investing in the platform we already have, or do we rewrite everything in another language?”

That choice is not as binary as it may seem.

At Into the Box 2026, Ortus Solutions Senior Architect and BoxLang core developer Jon Clausen presented a session titled “Top Ten Reasons to Migrate to Bo...

Cristobal Escobar
Cristobal Escobar
September 04, 2026
Be a rebel, but trust us on this: use ColdBox. You'll thank us later!

Be a rebel, but trust us on this: use ColdBox. You'll thank us later!

CFML developers have always had a bit of a rebellious streak.

That's part of what makes CFML great. It gives you enormous freedom to build applications quickly and structure them almost any way you want.

So yes, you can build a successful ColdFusion application without a framework. Many developers have, and some of those applications have been running for decades.

But trust us on this one:

Use a framework.

And if you're building or maintaini...

Cristobal Escobar
Cristobal Escobar
September 03, 2026