The Chicago Boss API is mostly stable, but still might change before 1.0.

Jump to: boss_web_test   boss_assert

Chicago Boss ships with a unique functional test framework, where tests are structured as trees of continuations. All assertions are performed in callbacks, and additional tests are also performed in callbacks. For more information on the design of Boss's functional tests, see “Functional Tests As A Tree Of Continuations”.

To create a test suite, create a module in the src/test/functional/ directory. Your test module should export a start/0 function, which should invoke a function from the boss_web_test module. This function will in turn invoke functions in the boss_assert module (to run assertions) and the boss_web_test module (to run further tests). A simple example of a test module with included start/0 function would be:

-module(my_app_test).

-export([start/0]).

start() ->
    boss_web_test:get_request("/", [],
        [fun boss_assert:http_ok/1], []).

The above test issues a GET request to the root URL, asserts that the response is 200 OK, and quits.

When you are ready to run your test suite, type "./rebar boss c=test_functional" in your project directory.

boss_web_test

Functions in the boss_web_test issue HTTP requests to your web application (or check for emails sent by it). All functions in the boss_web_test module take the same two final arguments.

Second to last, Assertions is a list of funs that must return a tuple {Passed, ErrorMessage}, where:

Each fun in Assertions takes a single argument, which is the response object of the current test. The response object will usually by an HTTP response, but in boss_web_test:read_email/4, it's an email.

Most assertions will take the form of calls to boss_assert, which is documented below.

The last argument to any boss_web_test function is called Continuations. Continuations is a list of additional tests — funs that take the HTTP response value as their only argument, and use it to invoke additional tests from the boss_web_test module. Funs in Continuations should be preceded by a string label, e.g.:

boss_web_test:get_request("/", [], [],
   [ "Click the register link", fun(Res) -> ... end,
     "Click the copyright link", fun(Res) -> ... end, 
      ... ]).

The key thing to understand about Continuations is that they are performed in parallel. Any database manipulations that occur in one continuation cannot affect sibling continuations.

Functions available in the boss_web_test module include:

get_request(Url, Headers, Assertions, Continuations) -> [{NumPassed, ErrorMessages}]

This test issues an HTTP GET request to Url (a path such as "/" -- no "http://" or domain name), passing in RequestHeaders to the server.

post_request(Url, Headers, Contents, Assertions, Continuations) -> [{NumPassed, ErrorMessages}]

This test issues an HTTP POST request to Url (a path such as "/" -- no "http://" or domain name), passing in RequestHeaders to the server, and Contents as the request body.

follow_link(LinkName, Response, Assertions, Continuations) -> [{NumPassed, ErrorMessages}]

This test looks for a link labeled LinkName in Response and issues an HTTP GET request to the associated URL. The label may be an "alt" attribute of a hyperlinked <img> tag.

follow_redirect(Response, Assertions, Continuations) -> [{NumPassed, ErrorMessages}]

This test follows an HTTP redirect; that is, it issues a GET request to the URL specified by the "Location" header in Response

follow_redirect(Response, Hdrs, Assertions, Continuations) -> [{NumPassed, ErrorMessages}]

This test follows an HTTP redirect; that is, it issues a GET request to the URL specified by the "Location" header in Response, while passing Hdrs out as outbound headers.

submit_form(FormName, FormValues::proplist(), Response, Assertions, Continuations) -> [{NumPassed, ErrorMessages}]

This test inspects Response for an HTML form with a "name" attribute equal to FormName, and submits it using FormValues, a proplist with keys equal to the labels of form fields. (So all visible form fields should be labeled with a <label> HTML tag!) If a particular value is not specified, the form's default value is used.

read_email(ToAddress, Subject, Assertions, Continuations) -> [{NumPassed, ErrorMessages}]

This test retrieves the most recent email sent by the application to ToAddress with subject equal to Subject.

boss_assert

The Assertions list in a boss_web_test invocation will usually refer to functions in the boss_assert module. Available functions include:

http_ok(Response) -> {Passed, ErrorMessage}

Compares the HTTP status code in Response to 200 (HTTP OK).

http_partial_content(Response) -> {Passed, ErrorMessage}

Compares the HTTP status code in Response to 206 (HTTP Partial Content)

http_redirect(Response) -> {Passed, ErrorMessage}

Compares the HTTP status code in Response to 302 (HTTP Found).

http_not_modified(Response) -> {Passed, ErrorMessage}

Compares the HTTP status code in Response to 304 (HTTP Not Modified).

http_bad_request(Response) -> {Passed, ErrorMessage}

Compares the HTTP status code in Response to 400 (HTTP Bad Request).

http_not_found(Response) -> {Passed, ErrorMessage}

Compares the HTTP status code in Response to 404 (HTTP Not Found).

link_with_text(Text, Response) -> {Passed, ErrorMessage}

Looks in Response for a link with text equal to Text. The text may be the inner text of an <a> tag, or the "alt" attribute of a hyperlinked <img> tag. Response may be an HTTP response, or an email.

tag_with_text(Tag, Text, Response) -> {Passed, ErrorMessage}

Looks in Response for an HTML tag of type Tag with inner text equal to Text. Response may be an HTTP response, or an email.

header(Key, Value, Response) -> {Passed, ErrorMessage}

Compares the Key header in Response (HTTP or email) to Value.

location_header(Url, Response) -> {Passed, ErrorMessage}

Compares Url to the Location: header of Response.

content_language_header(ContentLanguage, Response) -> {Passed, ErrorMessage}

Compares ContentLanguage to the Content-Language: header of Response

content_type_header(ContentType, Response) -> {Passed, ErrorMessage}

Compares ContentType to the Content-Type: header of Response

from_header(FromAddress, Email) -> {Passed, ErrorMessage}

Compares FromAddress to the From: header field in Email

email_has_text(Email) -> {Passed, ErrorMessage}

Checks whether Email contains a plain-text body.

email_has_html(Email) -> {Passed, ErrorMessage}

Checks whether Email contains an HTML body.

email_is_text_only(Email) -> {Passed, ErrorMessage}

Checks whether Email contains a plain-text body and not an HTML body.

email_is_html_only(Email) -> {Passed, ErrorMessage}

Checks whether Email contains an HTML body and not a plain-text body.

email_is_multipart(Email) -> {Passed, ErrorMessage}

Checks whether Email contains alternative text and HTML representations.

email_received(Email) -> {Passed, ErrorMessage}

Checks whether Email exists

email_not_received(Email) -> {Passed, ErrorMessage}

Checks whether Email is undefined