|script|login dialog driver|Bob|xyzzy|
|login with username|Bob|and password|xyzzy|
|check|login message|Bob logged in.|
|reject|login with username|Bob|and password|bad password|
|check|login message|Bob not logged in.|
|ensure|login with username|Bob|and password|xyzzy|
|note|this is a comment|
|show|number of login attempts|
|$symbol=|login message|

The fixture for this table is:
{{{public class LoginDialogDriver {
  private String userName;
  private String password;
  private String message;
  private int loginAttempts;

  public LoginDialogDriver(String userName, String password) {
    this.userName = userName;
    this.password = password;
  }

  public boolean loginWithUsernameAndPassword(String userName, String password) {
    loginAttempts++;
    boolean result = this.userName.equals(userName) && this.password.equals(password);
    if (result)
      message = String.format("%s logged in.", this.userName);
    else
      message = String.format("%s not logged in.", this.userName);
    return result;
  }

  public String loginMessage() {
    return message;
  }

  public int numberOfLoginAttempts() {
    return loginAttempts;
  }
} }}}

This should be pretty clear.  Each row is a single instruction in the script.
 * The first row is simply the word "Script" followed by the name and constructor arguments of the fixture (known as the "actor") that will be used by the rest of the table.  If there is no actor specified then the previous script table's actor on this test page will be used.

 * Most instructions involve some kind of function call.  By default, the name of the function is assembled from tokens in ''every other'' cell.  The arguments of the function are the intervening cells. Appending ";" to the end of a function name in a cell invokes sequential argument processing, which means that the arguments to the function are all subsequent cells.

''Interposing Function Call (Default)''
|login with username|Bob|and password|xyzzy|

''Sequential Argument Processing Function Call''
|login with username and password;|Bob|xyzzy|

 * A function alone in a row will turn red or green if it returns a boolean.  Otherwise it will simply remain uncolored.

 * If the word ''check'' is in the first cell of a row, then a function call follows it.  The last cell of the table is the expression we expect to be matched by what the function actually returns.

 * If the word ''check not'' is in the first cell of a row, then a function call follows it.  The last cell of the table is the expression we expect !style_red(''not'') to be matched by what the function actually returns.

 * If the word ''ensure'' is in the first cell, then it should be followed by a function that should return a boolean true for green and false for red.

 * If the word ''reject'' is in the first cell, then it should be followed by a function that should return a boolean false for green and true for red.

 * If the word ''note'' is in the first cell, all other cells in that row will be ignored.
  * Or if the first cell is blank.
  * Or if the first cell begins with # or *.

 * If the word ''show'' is in the first cell, then it should be followed by a function.  A new cell will be added when the test is run, and it will contain the return value of the function.

 * If a symbol assignment is in the first cell, then it should be followed by a functions.  The symbol is assigned the value returned by that function.

 * If the word ''start'' appears in the first cell, then the rest of the row is the name and constructor arguments for a new actor, which replaces the existing actor.



