Storyteller 4.1.0


Data Conversion within Specifications



Cells Edit on GitHub

If you had a sentence grammar (explained below) with the template "Enter the user name ", the value username is a Cell used to collect information from a user. The template above would result in this bit of html in the specification editor:

Enter the user name

Cells can be either inputs (the "Arrange" or "Act" portion of a specification) or assertion values that will be verified as an expectation against an actual value (the "Assert" part of a specification). As discussed in the following sections, Cells can be customized to provide better usability in the user inferface tooling or html rendering.

Asserting Values

Smoke tests that simply prove that an operation does not blow up with exceptions can be useful, but sooner or later you will probably want to assert that some value or state in the system under test matches your expectation. In Storyteller, some Cells can act as assertions to compare the expected value input by the specification author against the actual value. Revisiting the Calculator problem domain from the tutorial, the html results for successful, failed, and invalid cell assertions are shown in the sample specification below:

In the case of invalid data, you can click on the yellow cell to see a popup modal with the full error message for the conversion failure.

See Asserting Values for more information.

Customizing Cells

You can customize Cell appearance and editing in a couple different ways:

  1. Header -- change the heading for Cell's within tabular grammars
  2. Editor -- change the editor control that Storyteller uses for the cell in the specification editor. This isn't terribly useful now as the only choices are the default textbox, select lists, and a checkbox for boolean values, but the plan is for more options in the future.
  3. Selection lists and values -- To guide the usage in the editor, you can force the user to provide Cell inputs from a selection list. See Selection Lists for much more information.
  4. Default Values -- You can supply a default value for a Cell as a string. The immediate benefit is to make specification editing quicker if you can live with the default values. Also see Tables for more information about using optional columns in table grammars.

Customizing via Attributes

For grammars that call a fixture method directly, you can use .Net attributes on the method parameters (including the return value using the return: prefix) like this example of a table grammar:

[ExposeAsTable("Table with lots of options")]
public void TableWithLotsOfOptions(
    [Header("Player Name")]string player,
    [Header("Position"), DefaultValue("Outfield")]
    [SelectionValues("Pitcher", "Outfield", "Catcher")]
    string position
    // Set up your roster

In the html rendering, a specification using that grammar looks like this:

The available attributes are:

  1. [DefaultValue(value)] to specify the default value for a cell
  2. [Header(the heading)] to specify the header value displayed in tables
  3. [return: AliasAs(cell alias)] to override the cell name for the return value of a method
  4. [Editor(editor type)] to override the editor selection for a cell
  5. [SelectionList(list name)] to specify a named list of selection values
  6. [SelectionValues(values)] to directly specify a list of selection values for this list

Customizing Cells Programmatically

For the grammars (set verifications, some kinds of tables, paragraphs) that are defined through some kind of fluent interface, Storyteller 3.0 introduces the ICellExpression syntax to customize cell properties:

public interface ICellExpression
    /// <summary>
    /// Override the header display for this cell within Tables
    /// </summary>
    /// <param name="header"></param>
    /// <returns></returns>
    ICellExpression Header(string header);

    /// <summary>
    /// Explicitly choose the editor control for this cell
    /// </summary>
    /// <param name="editor"></param>
    /// <returns></returns>
    ICellExpression Editor(string editor);

    /// <summary>
    /// Explicitly set a default value for this cell
    /// </summary>
    /// <param name="default"></param>
    /// <returns></returns>
    ICellExpression DefaultValue(string @default);

    /// <summary>
    /// Explicitly set the selection values by the raw values
    /// </summary>
    /// <param name="values"></param>
    /// <returns></returns>
    ICellExpression SelectionValues(params string[] values);

    /// <summary>
    /// Explicitly set the selection options for this cell
    /// </summary>
    /// <param name="options"></param>
    /// <returns></returns>
    ICellExpression SelectionOptions(params Option[] options);

    /// <summary>
    /// Use a named selection list for this cell
    /// </summary>
    /// <param name="listName"></param>
    /// <returns></returns>
    ICellExpression SelectionList(string listName);

In usage, the cell expression is used as part of a fluent interface like this example from a set verification grammar:

public IGrammar OrderedDetailsAre()
    return VerifySetOf(getDetails)
        .Titled("The Ordered details should be")

        // Use this syntax if you want to customize
        // the cells in this SetVerification grammar
        .Comparisons(_ =>
            _.Compare(o => o.Amount).DefaultValue("100").Header("The Amount");

            _.Compare(o => o.Date)

                // Adding a selection list by display/value
                    new Option("Today", "TODAY"), 
                    new Option("Yesterday", "TODAY-1"), 
                    new Option("Tomorrow", "TODAY+1")

            _.Compare(o => o.Name)
                .Header("The Name")

                // Simple value list
                .SelectionValues("Hank", "Tom", "Alice");

            // Simply refer to a selection list 
            // defined elsewhere by name
            _.Compare(o => o.Part)

Because the usage was so common on a big project, there are now DefaultIsEmpty() and DefaultIsNull() extension methods for setting default cell values.

Default Editor Rules

There are only a couple built in rules (for now) for how Storyteller selects an editor for a cell:

  • If a cell type is an enumeration type, use a select editor with all the possible values for that enumeration. (This was a very common request for 3.0).
  • If a cell type is a boolean, use a checkbox as the editor
  • If a cell has either a named selection list or selection values, use a select box
  • Otherwise, use a textbox that grows or shrinks to the size of the cell value (a big improvement for 3.0 in the opinion of this author).

Big Text Editor

If you need to use a string cell in your specifications that would be more easily edited and displayed with a larger, multi-line textbox, you can use the bigtext editor like this:

[Header("The City")]
[Default("Cedar Park")]
public string City { get; set; }

Display Only Cells

This is admittedly an oddball feature, but you can also mark cells as display-only such that they are not editable in the specification editor:

public int Number { get; set; }

We added this feature at the request of one of our project teams that generated Storyteller specification files programmatically. I'm not entirely sure how useful this editor feature will be outside of that one project.