Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
TestBox is a xUnit style and behavior-driven development (BDD) testing framework for CFML (ColdFusion). It does not depend on any other framework for operation and it has a clean and descriptive syntax that will make you giggle when writing your tests. It ships with not only the xUnit and BDD testing capabilities, but also an assertions and expectations library, several different runners, reporters and MockBox, for mocking and stubbing capabilities.
Info Note: This article is a primer to get you started with the xUnit capabilities of TestBox, if you would like to explore the BDD style capabilities of TestBox we recommend you visit the BDD primer chapter.
The xUnit functionalities of TestBox will require Railo 4.1+, Lucee 4.5+ or ColdFusion 9.01+.
TestBox relies on the fact of creating testing bundles which are basically CFCs. A bundle CFC will hold all the tests the TestBox runner will execute and produce reports on. Thus, sometimes this test bundle is referred to as a test suite in xUnit terms.
This bundle can contain 2 life-cycle methods, the beforeTests()
and afterTests()
methods will execute once before ALL your tests run and then after ALL your tests run. This is a great way to do any kind of global setup or teardown in your tests. It also contains a displayName
argument in the component declaration which gives you a way to name your testing suite. We will see later the other annotations you can add to the component declaration further in the primer.
TestBox not only provides you with global life-cycle methods but also with localized test methods. This is a great way to keep your tests DRY (Do not repeat yourself)! TestBox provides the setup( currentMethod ) and teardown( currentMethod ) methods that each receives the name of the test method in question. which as their names indicate, they execute before a test and after a test in a test bundle.
Assertions are self-concatenated strings that evaluate an actual value to an expected value or condition. These are initiated by the global TestBox variable called $assert which contains tons of included assertion methods so you can evaluate your tests.
Each assertion evaluator will compare the actual value and an expected value or condition. It is responsible for either passing or failing this evaluation and reporting it to TestBox. Each evaluator also has a negative counterpart assertion by just prefixing the call to the method with a not expression.
TestBox has a plethora (That's Right! I said Plethora) of evaluators that are included in the release. The best way to see all the latest evaluator methods is to visit our API and digest the coldbox.system.Assertion class. There is also the ability to register and write custom assertion evaluators in TestBox via our addAssertions() function.
You can also register custom assertions within the $assert object. You will do this by reading our Custom Assertions section of our TestBox docs.
TestBox discovers test methods in your bundle CFC by applying the following discovery rules:
Any method that has a test annotation on it
Any public method that starts or ends with the word test
Each test method will test the state of the SUT (software under test) or sometimes referred to as code under test. It will do so by asserting that actual values from an execution match an expected value or condition. TestBox offers an assertion library that you have available in your bundle via the injected variable $assert. You can also use our expectations library if you so desire, but that is mostly used in our BDD approach.
Each test function can also have some cool annotations attached to it.
Please refer to our section to take advantage of all the mocking and stubbing you can do. However, every BDD TestBundle has the following functions available to you for mocking and stubbing purposes:
makePublic( target, method, newName )
- Exposes private methods from objects as public methods
querySim( queryData )
- Simulate a query
getMockBox( [generationPath] )
- Get a reference to MockBox
createEmptyMock( [className], [object], [callLogging=true])
- Create an empty mock from a class or object
createMock( [className], [object], [clearMethods=false], [callLogging=true])
- Create a spy from an instance or class with call logging
prepareMock( object, [callLogging=true])
- Prepare an instance of an object for method spies with call logging
createStub( [callLogging=true], [extends], [implements])
- Create stub objects with call logging and optional inheritance trees and implementation methods
getProperty( target, name, [scope=variables], [defaultValue] )
- Get a property from an object in any scope
Tests and suites can be tagged with TestBox labels. Labels allows you to further categorize different tests or suites so that when a runner executes with labels attached, only those tests and suites will be executed, the rest will be skipped. Labels can be applied globally to the component declaration of the test bundle suite or granularly at the test method declaration.
TestBox comes also with a nice plethora of reporters:
ANTJunit : A specific variant of JUnit XML that works with the ANT junitreport task
Codexwiki : Produces MediaWiki syntax for usage in Codex Wiki
Console : Sends report to console
Doc : Builds semantic HTML to produce nice documentation
Dot : Builds an awesome dot report
JSON : Builds a report into JSON
JUnit : Builds a JUnit compliant report
Raw : Returns the raw structure representation of the testing results
Simple : A basic HTML reporter
Text : Back to the 80's with an awesome text report
XML : Builds yet another XML testing report
Tap : A test anything protocol reporter
Min : A minimalistic view of your test reports
MinText : A minimalistic view of your test reports for consoles
NodeJS : User-contributed:
Tests and suites can be skipped from execution by using the skip annotation in the component or function declaration. The reporters will show that these suites or tests where skipped from execution. The value of the skip annotation can be a simple true or false or it can be the name of a UDF that exists in the same bundle CFC. This UDF must return a boolean value and it is evaluated at runtime.
You can tag a bundle component declaration with the boolean asyncAll
annotation and TestBox will execute all specs in separate threads for you concurrently.
Caution Once you delve into the asynchronous world you will have to make sure your tests are also thread safe (var-scoped) and provide any necessary locking.
TestBox ships with several test runners internally but we have tried to simplify and abstract it with our TestBox object which can be found in the testbox.system package. The TestBox object allows you to execute tests from a CFC, CFM, HTTP, NodeJS, SOAP or REST. You can also make your CFC's extend from our BaseSpec
class so you can execute it directly via the URL. The main execution methods are:
Info We encourage you to read the API docs included in the distribution for the complete parameters for each method.
run()
ArgumentsHere are the arguments you can use for initializing TestBox or executing the run()
method
runRemote()
argumentsHere are the arguments you can use for executing the runRemote()
method:
The bundles argument which can be a single CFC path or an array of CFC paths or a directory argument so it can go and discover the test bundles from that directory. The reporter argument can be a core reporter name like: json,xml,junit,raw,simple,dots,tap,min,etc or it can be an instance of a reporter CFC. You can execute the runners from any cfm template or any CFC or any URL, that is up to you.
TestBox ships with a global runner that can be used to run pretty much anything. You can customize it or place it wherever you need it:
TestBox ships with a test browser that is highly configurable to whatever URL accessible path you want. It will then show you a test browser where you can navigate and execute not only individual tests, but also directory suites as well.
In our test samples and templates we include an ANT runner that will be able to execute your tests via ANT. It can also leverage our ANTJunit reporter to use the junitreport task to produce JUnit compliant reports as well. You can find this runner in the test samples and runner template directory.
You can run tests via SOAP by leveraging the runRemote() method. The WSDL URL will be
HTTP/REST Runner You can run tests via HTTP/REST by leveraging the runRemote() endpoint. The URL will be
There is a user-contributed NodeJS Runner that looks fantastic and can be downloaded here:
Just use node to install:
If you make your test bundle CFC inherit from our testbox.system.BaseSpec class, you will be able to execute the CFC directly via the URL: ```javascript ``` You can also pass the following arguments to the method via the URL: * **testSuites** : A list or array of suite names that are the ones that will be executed ONLY! * **testSpecs** : A list or array of test names that are the ones that will be executed ONLY! * **reporter** : The type of reporter to run the test with ```javascript ```
Argument
Required
Default
Type
Description
labels
false
---
string/list
The list of labels this test belongs to
skip
false
false
boolean/udf
A boolean flag that makes the runners skip the test for execution. It can also be the name of a UDF in the same CFC that will be executed and MUST return a boolean value.
Argument | Required | Default | Type | Description |
bundles | true | --- | string | The path, list of paths or array of paths of the spec bundle CFCs to run and test |
directory | false | --- | string | The directory mapping to test: directory = the path to the directory using dot notation (myapp.testing.specs) |
recurse | false | true | boolean | Recurse the directory mapping or not, by default it does |
reporter | false | simple | string/path | The type of reporter to use for the results, by default is uses our 'simple' report. You can pass in a core reporter string type or a class path to the reporter to use. |
reporterOptions | false | {} | JSON | A JSON struct literal of options to pass into the reporter |
labels | false | false | string | The string array of labels the runner will use to execute suites and specs with. |
excludes | false | --- | string/array | The string or array of labels to exclude from running |
options | false | {} | JSON | A JSON struct literal of configuration options that are optionally used to configure a runner. |
testBundles | false | --- | string/array | A list or array of bundle names that are the ones that will be executed ONLY! |
testSuites | false | --- | string | A list of suite names that are the ones that will be executed ONLY! |
testSpecs | false | --- | string | A list of test names that are the ones that will be executed ONLY |
Argument | Required | Default | Type | Description |
bundles | true | --- | string/array | The path, list of paths or array of paths of the spec bundle CFCs to run and test |
directory | false | --- | struct | The directory mapping path or a struct: [ mapping = the path to the directory using dot notation (myapp.testing.specs), recurse = boolean, filter = closure that receives the path of the CFC found, it must return true to process or false to continue process ] |
reporter | false | simple | string/struct/instance | The type of reporter to use for the results, by default is uses our 'simple' report. You can pass in a core reporter string type or an instance of a coldbox.system.reports.IReporter. You can also pass a struct with [type="string or classpath", options={}] if a reporter expects options. |
labels | false | false | string/array | The string or array of labels the runner will use to execute suites and specs with. |
excludes | false | --- | string/array | The string or array of labels to exclude from running |
options | false | {} | struct | A structure of property name-value pairs that each runner can implement and use at its discretion. |
testBundles | false | --- | string/array | A list or array of bundle names that are the ones that will be executed ONLY! |
testSuites | false | --- | string/array | A list or array of suite names that are the ones that will be executed ONLY! |
testSpecs | false | --- | string/array | A list or array of test names that are the ones that will be executed ONLY |