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

BoxLang Jsoup: Powerful HTML Parsing, Cleaning and Fluent Navigation

BoxLang Jsoup: Powerful HTML Parsing, Cleaning and Fluent Navigation

We're excited to announce the release of bx-jsoup, a powerful new BoxLang module that brings enterprise-grade HTML parsing and cleaning capabilities to your applications. Built on top of the proven Jsoup library, this module provides developers with safe, flexible tools for handling HTML content while maintaining BoxLang's signature ease of use. It also enhances the core document classes to provide you with a fluent BoxDocument result that you can navigate, query, and even convert your HTML representation to XML or JSON.

Luis Majano
Luis Majano
July 15, 2025
CBWire: Smarter UIs, Simpler Development!

CBWire: Smarter UIs, Simpler Development!

CBWire isn’t just a productivity boost, it’s a shift in how we think about building modern web apps in CFML. It empowers developers to create rich, responsive interfaces while keeping development clean, fast, and focused on what matters.

If you’re building ColdBox applications and want to streamline your front-end work, CBWire is one of the most impactful tools you can add to your stack.

Maria Jose Herrera
Maria Jose Herrera
July 14, 2025
Ortus Monthly Digest: June 2025

Ortus Monthly Digest: June 2025

June was a transformative month at Ortus Solutions as we crossed the halfway point of the year. With major product updates, powerful community engagements, and continued improvements across the BoxLang ecosystem, our mission to modernize development and empower engineers took center stage. Whether you're a longtime member of the Ortus community or just joining us, here's everything we accomplished in June packed with announcements, tools, and opportunities to grow.

Victor Campos
Victor Campos
July 08, 2025