> For the complete documentation index, see [llms.txt](https://testbox.ortusbooks.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://testbox.ortusbooks.com/getting-started/testbox-bdd-primer/specs.md).

# Specs

A spec is a declaration that will usually test your system with a requirement. They are defined by calling the TestBox `it()` global function, which takes in a `title` and a `body` function/closure. The `title` is the title of this spec you will write and the `body` function/closure is a block of code that represents the spec.

A spec will contain most likely one or more expectations that will test the state of the [SUT](http://en.wikipedia.org/wiki/System_under_test) (software under test) or sometimes referred to as code under test. In BDD style, your specifications are what is used to validate your requirements of a scenario which is your `describe()` block of your [story](http://en.wikipedia.org/wiki/User_story).

```javascript
function run(){

     describe("A suite", function(){
          it("contains spec with an awesome expectation", function(){
               expect( true ).toBeTrue();
          });

          it("contains a spec with more than 1 expectation", function(){
               expect( [1,2,3] ).toBeArray();
               expect( [1,2,3] ).toHaveLength( 3 );
          });
     });

}
```

An expectation is a nice assertion DSL that TestBox exposes so you can pretty much read what should happen in the testing scenario. A spec will pass if all expectations pass. A spec with one or more expectations that fail will fail the entire spec.

{% hint style="success" %}
The `it()` function is also aliased as `then()` - except `it()` has `title` when `then()` uses `then` instead
{% endhint %}

### Arguments

| Argument | Required | Default | Type         | Description                                                                                                                                                                            |
| -------- | -------- | ------- | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| title    | true     | ---     | string       | the title of the spec                                                                                                                                                                  |
| body     | true     | ---     | closure/udf  | The closure that represents the spec                                                                                                                                                   |
| labels   | false    | ---     | string/array | The list or array of labels this suite group belongs to                                                                                                                                |
| skip     | false    | false   | Boolean      | A flag or a closure that tells TestBox to skip this suite group from testing if true. If this is a closure it must return boolean.                                                     |
| data     | false    | `{}`    | struct       | A struct of data you can bind the spec with so you can use within the `body` closure                                                                                                   |
| retries  | false    | `0`     | numeric      | How many extra times to run the spec when it fails or errors. `0` inherits the bundle `retries` annotation or the global `retries` option. See [Retries](/browser-testing/retries.md). |

## Retrying Flaky Specs

A spec that depends on the outside world, such as a browser, a remote API or a slow server, can pass the `retries` argument to run again, up to that many extra times, before TestBox reports it. The `beforeEach()` and `afterEach()` closures run again on every attempt, and the spec stats record the `attempts`.

{% tabs %}
{% tab title="BoxLang" %}

```java
it( title = "charges a card in the sandbox", body = () => {
    expect( gateway.charge( 100 ).status ).toBe( "succeeded" )
}, retries = 2 )
```

{% endtab %}

{% tab title="CFML" %}

```cfscript
it( title = "charges a card in the sandbox", body = function(){
    expect( gateway.charge( 100 ).status ).toBe( "succeeded" );
}, retries = 2 );
```

{% endtab %}
{% endtabs %}

Retries can also be set for a whole bundle or run. See [Retries](/browser-testing/retries.md) for the precedence rules.

## Attaching Files

Call `attach( path, type, name )` inside a spec to attach a file, such as a screenshot or a log, to its result. Reporters list it under the spec. See [Attachments](/browser-testing/attachments.md).

## They are closures Ma!

Since the implementations of the `describe()` and `it()` functions are closures, they can contain executable code that is necessary to implement the test. All CFML rules of scoping apply to [closures](http://help.adobe.com/en_US/ColdFusion/10.0/Developing/WSe61e35da8d31851842acbba1353e848b35-8000.html), so please remember them. We recommend always using the `variables` scope for easy access and distinction.

```javascript
function run(){

     describe("A suite is a closure", function(){
          c = new Calculator();

          it("and so is a spec", function(){
               expect( c ).toBeTypeOf( 'component' );
          });
     });

}
```

## Spec Data Binding

The `data` argument can be used to pass in a structure of data into the spec so it can be used later within the body closure. This is great when doing looping and creating dynamic closure calls:

```javascript
// Simple Example
it( title="can handle binding", body=function( data ){
    expect(    data.keep ).toBeTrue();
}, data={ keep = true } );

// Complex Example. Let's iterate over a bunch of files and create dynamic specs
for( var filePath in files ){

  it( 
    title="#getFileFromPath( filePath )# should be valid JSON", 
    // pass in a struct of data to the spec for later evaluation
    data={ filePath = filePath },
    // the spec closure accepts the data for later evaluation
    body=function( data ) {
      var json = fileRead( data.filePath );
      var isItJson = isJSON( json );

      expect( json ).notToBeEmpty();
      expect( isItJson ).toBeTrue();

      if( isItJson ){
          var jsonData = deserializeJSON(json);
          if( getFileFromPath( filePath ) != "index.json"){
              expect( jsonData ).toHaveKey( "name" );
              expect( jsonData ).toHaveKey( "type" );
          }
      }

  });
}
```

{% hint style="warning" %}
When using the `then()` function instead of `it()` the title argument name is `then` instead of `title` for the `it()` function
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://testbox.ortusbooks.com/getting-started/testbox-bdd-primer/specs.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
