SWELL - An English-Like DSL for Swing Testing Blog

Version 2

    This article describes an English-Like domain-specific language for testing Swing applications. If you are a potential SWELL user, proceed to the SWELL User Guide. But if you would like to underst and the design of the tool to possibly create your own DSL-based tools, read on.

    The Wikipedia's entry for domain-specific language (or DSL) explains that "a domain-specific language (DSL) is a programming l anguage or specification language dedicated to a particular problem domain, a particular problem representation technique, and/or a particular solution technique ... Creating a domain-specific language (with software to support it) can be worthwhile if the language allows a particular type of p roblem or solution to be expressed more clearly than an existing languages would allow and the type of problem in question reappears sufficiently often."

    The authors interpreted this as a license to createSWELL—An English-Like DSL forSwing Testing. SWELL has the following features:

    • English-like in the words used and the sentence construction
    • uses familiar Swing terms and English words in sentences typically used by human testers
    • allows Swing Componentsto be identified and referenced using natural language
    • can express the idea of any Swing action using a mouse, keyboard, etc. using natural language
    • allows structuring of test cases (like JUnit) to facilitate test classification and management

    Specific details can be found in SWELL Language Manual and SWELL Grammar below.

    SWELL Internals - Anatomy of an Interpreter details the construction of the interpreterthat executes SWELL scripts. This part is also a generic blueprint for DSL processors using VisualLangLab as the parser-generator.

    A periodically updated version of this article that stays compliant with the current versions of the software used will be available at SWELL Article Update.

    SWELL "Hello world"

    All of our examples will target VisualLangLab (a convenient Swing application we will be using for parser development anyway). So, if you are not at all familiar with VisualLangLab, take a quick look at the Grammar without Tears article. The following code is a SWELL script for testing two of VisualLangLab's built-in sample grammars:ArithExpr and SimpleJSON.

    Suite SampleGrammars begins with - Launch vll.gui.VllGui.main() - Wait for frame "VisualLangLab/S" - clearLogButton is the button with ToolTipText = "Clear log" - parseInputButton is the button with ToolTipText = "Parse input" - parserInputArea is the 3rd textcomponent - logTextPane is the 4th textcomponent 
    Before each test
    - clear text in ${logTextPane}
    - clear text in ${parserInputArea}
    After each test
    - delay 500 ms
    Test ArithExpr "Check ArithExpr" is - select "Help" -> "Sample grammars" -> "ArithExpr" from the menubar - Wait for frame "VisualLangLab sample.*" - delay 1 second - click the "OK" button of the "VisualLangLab sample.*" dialog - key "3 * 5" into ${parserInputArea} - click ${parseInputButton} - fail the test with message "Bad parse result" unless ${logTextPane} contains "Array(Array(Pair(0, 3), List(Pair(0, Pair(0, 5)))), List())" within 1 s Test SimpleJSON "Check SimpleJSON" is - select "Help" -> "Sample grammars" -> "SimpleJSON" from the menubar - Wait for frame "VisualLangLab sample.*" - delay 1 second - click the "OK" button of the "VisualLangLab sample.*" dialog - key "{\"name\":\"Centurion\"}" into ${parserInputArea} - click ${parseInputButton} - fail the test with message "Bad parse result" unless ${logTextPane} contains "Pair(0, Array({, List(Array(\"name\", :, Pair(2, \"Centurion\"))), }))" within 2 seconds Suite SampleGrammars ends with - pause "We're done! Please click the \"OK\" button to exit."

    The colored (blue, cyan, and red) lines are the structuring constructs. Every SWELL script contains a single test suitedelimited by a test header and trailer (the blue lines). The header and trailer include the suite's name (SampleGrammars), which exists for documentation purposes only. The header and trailer can both be optionally followed by one or more SWELL statements that are executed at the start and end of the suite respectively.

    A suite contains one or more tests, each starting with atest header (the red lines). Each test header (the red lines) includes the test's name (ArithExpr,SimpleJSON, etc.) and a string containing a more verbose description of the test. Each test-header is followed by one or more SWELL statements that are executed as part of the test. Like JUnit (and other test frameworks) SWELL also has ways of reporting the outcome of a test (e.g. the fail the test ... in these examples).

    Optional before and after sections (headed by the cyan lines) list actions to be performed before and after each test respectively.

    Figure 1 below shows this script in action. It loads the two sample grammars one by one, provides grammar-specific test input for each (in the Parser Test Input area), runs the parser and verifies that the expected output appears (in the Parser Log area) within one second. A failure is reported if the verification fails.

    SWELL in action!
    Figure 1. SWELL in action!

    Running the Examples below has instructions on how to run this script. Most readers should have no problem deciphering this SWELL script, but if you need help use theSWELL Language Manual below.

    SWELL User Guide

    This brief User Guide introduces the available resources, and explains how they can be used to run the examples in this article or to run your own SWELL scripts. All of the resources required to support the descriptions in this article can be found in theswell-article-resources.zip file listed in the Resources section at the bottom of this article.


    Apart from the contents of the swell-article-resources.zip file, you will need to get the latest download from the Abbot Java GUI Test Framework, and to have a 6.0+ JRE installed. Both, SWELL itself and VisualLangLab, are written in Scala, but you do not need a Scala installation to use SWELL or VisualLangLab as described here.

    Running the Examples

    To run the examples shown, proceed as follows (this runs the Hello world script above):

    • download the swell-article-resources.zip file, and unzip the contents into a directory (calledswell-article-resources)
    • obtain the latest download from the Abbot Java GUI Test Framework, and copy all its jar files into the jarssubdirectory of the swell-article-resources directory
    • on Windows: open a CMD window, cd into theswell-article-resources directory, and run the command "launch.bat test-SampleGrammars.txt"
    • on Linux/Mac OS/*NIX: at a shell prompt, cd into theswell-article-resources directory, and run the command "chmod +x launch". Then run the command "launch test-SampleGrammars.txt"
    • after completion of the OS-specific actions described in the previous two points, there is a delay of 10-30 seconds before any activity is visible. Do not touch the mouse till the end of the tests
    • at the end of the test, a dialog is displayed (as in Figure 1 above), click the "OK" button to exit the test environment
    • a detailed test log can be found in the file namedtest-SampleGrammars.log

    Running your own SWELL Tests

    The swell-article-resources.zip file contains everything you need to use SWELL for your own test. To create a new SWELL test script proceed as follows:

    • download and unzip swell-article-resources.zip into theswell-article-resources directory, and add jar files from the Abbot Java GUI Test Framework as usual (see above)
    • modify the launch.bat or launch script (depending on your host OS) to add directories and jar/zip files required for the system-under-test to the classpath. Save the modified launcher script with a different name (e.g. launch-test.bat orlaunch-test)
    • using a text editor program, create one or more SWELL script files (equivalent to the test-SampleGrammars.txt file). Use the SWELL Language Manual for help with SWELL statements
    • run the test by using the new launcher script using the OS-specific directions provided in the previous section. For example, if a new SWELL script file is named edit-rates.txt, you can start it by entering the command "launch-test edit-rates.txt"

    Users should be aware that the parser's error-reporting capability is currently rudimentary, and the error messages are sometimes not very helpful. However we expect to improve this aspect progressively, and improved resources and SWELL documentation will be made available at the The SWELL Project.

    The SWELL Project

    The resources in the swell-article-resources.zip file as well as additional documentation are being published as an open-source project hosted at http://swell.java.net/. The project is expected to be available online by the time (or soon after) this article is published.

    SWELL Grammar

    We won't be reinventing the wheel here, so just extract the SWELL grammar file swell.vll from the swell-article-resources.zip file listed in the Resources section. You will need the grammar-file to follow the descriptions and examples below.

    Introducing VisualLangLab

    Our DSL interpreter will need a parser to analyze SWELL scripts, and since the SWELL grammar is quite elaborate we must use a proper parser-generator. However, we would like to avoid the theory and formalisms (as much as possible) and use the simplest tools and approach. So, while there are many good parser generators, our choice for the job is the simple, user-friendly, and easy to learn VisualLangLab. To save space, we won't say much about the tool here, but refer interested readers to the Grammar without Tears article.

    Open Grammar in VisualLangLab

    The SWELL grammar was developed using VisualLangLab, and you can use the same tool to inspect and review the grammar. You can also test-run the grammar by feeding it snippets of SWELL. Within VisualLangLab, grammars are like gentle herbivores in an open zoo, and they don't bite your hand if you offer them the wrong kind of leaf or straw. You can also modify the grammar, and see how that changes its behavior, and the ASTproduced.

    If you haven't downloaded VisualLangLab yet, get the VLLS-All.jarfile now. Start VisualLangLab by double-clicking this file (Linux, Mac OS, and UNIX users will need to chmod +x VisualLangLab.jar). Select File -> Open from the VisualLangLab main menu, choose script.vll in the file-chooser dialog, and click the "Open" button. You should see the grammar-tree for the top-level parser-rule, Suite, displayed as in Figure 2 below.

    Initial grammar view
    Figure 2. Initial grammar view

    The GUI's menus, toolbars, and displays, and the grammar-tree's icons and annotations are explained in the Grammar without Tears article, but if you need additional help take a look at The GUI. And if you need help with the icons or any other part of the grammar-tree, take a look at Editing the Grammar Tree. A somewhat more complex (but unfortunately essential) concept is the VisualLangLab AST. The rest of the article requires a good understanding of these concepts, so you should revisit the resources listed above if required.

    Grammar Structure

    A VisualLangLab grammar contains many separate grammar-trees (or parser-rules). You can display any grammar-rule by selecting its name in the toolbar's drop-down list (in the box near the red "A" in Figure 2 above). All these apparently independent grammar-trees actually constitute one large tree rooted at the top-level rule (Suite in this case). You can navigate up any branch of the tree by right-clicking any Referencenode and selecting Go to from the grammar-tree's context-menu as shown in Figure 3 below.

    Navigating up the singleTest branch
    Figure 3. Navigating up the singleTest branch

    This process (right-clicking a Reference node and selecting Go to) can be repeated till you reach a grammar-tree that has no Reference nodes. The grammar-trees in Figure 4 below trace the path from Suite (the root) through singleTest, runStatements,stmtEnterText, and swingQuery to treePath.

    Navigating grammar-tree references
    Figure 4. Navigating grammar-tree references

    Later in the article, when we discuss SWELL Internals, the grammar-trees in Figure 4 will be used to illustrate how application code (in the SWELL interpreter) is interfaced to the parser. To follow that discussion an understanding of each grammar-tree's AST will be required. The AST is displayed in the text area to the right of the grammar tree (see red box marked with a "B" in Figure 2 above). The information shown is the AST of the currently selected node, so to see the AST of the entire grammar-tree select (click on) the grammar-tree's root node. Also, the radio button marked with a "§" (for Depth, near the red "C" in Figure 2 above) should be selected. More details can be found in AST Structure.

    Test-Running a Grammar-Tree

    Actually running a parser-rule with different inputs gives you greater insight into the grammar, and we recommend trying to run some of the grammar-trees in Figure 4 above. Figure 5 below shows the simple steps required to test-run the selected grammar tree. Type the input text into the Parser Test Input area (the red box marked "A"), click the Parse input button (near the red "B"), then validate the parser's output (after the words result follows: in the red box marked "C"). If you see any error messages in red in place of the parser's result, the input did not match the grammar.

    Testing the treePath grammar-tree
    Figure 5. Testing the treePath grammar-tree

    Figure 6 below shows the stmtEnterText parser-rule (middle of Figure 4 above) being tested. Observe that to parse the input provided, stmtEnterTextneeds to invoke swingQuery as well, but does not requiretreePath.

    Testing the stmtEnterText grammar-tree
    Figure 6. Testing the stmtEnterText grammar-tree

    Testing Parsers has more detailed information about approaches to testing within the VisualLangLab GUI.

    SWELL Internals - Anatomy of an Interpreter

    The code described below is obviously SWELL-specific, but the overall organization is a generic blueprint (see Figure 7 below) for any DSL interpreter that uses VisualLangLab.

    Interpreter blueprint
    Figure 7. Interpreter blueprint

    Disclaimer: Figure 7 just describes the dependencies between the various components. It does not imply that SWELL embeds any of the other components in any way.

    As Figure 7 shows, the internal structure is very simple, just bundle your own code together with any required libraries and the VisualLangLab API. In the case of SWELL, it depends on the ABBOT (http://abbot.sourceforge.net/) framework for Swing GUI testing, so those jars are required. All interpreters using the VisualLangLab API must perform the following steps:

    • Locate the grammar (XML) file
    • Regenerate the parser
    • Parse the given input, and obtain AST
    • Interpret the AST

    The following sections show and explain the essential code that handles these functions. The first three steps (up to obtaining the AST) are handled in one block of code, and are explained under Locate Grammar ... Obtain the AST below. Interpretation of the AST is explained under Application-Code AST Interaction.

    Locate Grammar ... Obtain AST

    A parser developed with VisualLangLab is saved as XML in agrammar-file with a .vll type. A program that uses such a parser (like the SWELL interpreter) uses the VisualLangLabAPI to turn this XML into an instance of the Scala Parserstype. But it must first obtain the contents of the grammar file. In the case of the SWELL interpreter, the grammar file is included as a resource in the jar file, and is retrieved using the system classloader's getResourceAsStream(String) method. This approach is convenient for programs that use large grammar-files. Smaller grammar-files can be embedded as a string within the interpreter program itself. To examine the code that performs these functions, look around the def main(...) {...}function.

    Application-Code AST Interaction

    The SWELL interpreter is written in Scala, and exploits Scala'spattern matching capability to analyze and unravel the AST. The description below uses snippets of code from SWELL that show how the AST is unraveled in steps strongly reminiscent of the oft-quoted onion skin metaphor. The following function marks the beginning of the onion's odyssey. The expression res.get returns the AST (the entire onion), which is passed to theSuite_handler().

    Those interested in reviewing the full code should visit thesrc directory of the swell-article-resources.zip file.

     def main(args: Array[String]) {
    ... lines removed for clarity ... val res = parser(input) if (res.successful) { ... lines removed for clarity ... Suite_handler(res.get) ... lines removed for clarity ... }

    The function Suite_handler() shown below processes the AST from the top-level parser-rule Suite, (the entire onion). The structure of Suite's AST is shown on the left below, and notice how the code uses pattern matching to separate the onion's layers. The part of the onion containing the tests is passed to the function handleTests().

    ASTHandler Code
    | @stmtSuitBegins,
    | List(@groupDefinition),
    | Option(@stmtBeforeEachTest),
    | Option(@stmtAfterEachTest),
    | List(
    | | Choice(
    | | | Pair(0, @singleTest),
    | | | Pair(1, @runCommand)
    | | )
    | )
    | @stmtSuitEnds
     private def Suite_handler(pTree: Any) {
    pTree match {
    case Array(suiteBegins, groups, beforeEachTest,
    afterEachTest, tests, suiteEnds) =>
    ... lines removed for clarity ... handleTests( tests)
    ... lines removed for clarity ... }

    The structure of the part of the AST passed tohandleTests() is shown below left, and a part ofhandleTests()'s code is shown on the right. Notice the use of a cast and pattern-matching to locate the list of statements in each test. Each statement is passed off (one at a time) to handleRunStatements().

    ASTHandler Code
    | @testHeader,
    | List(@runStatements) )
     private def handleTests(tests: Any) {
    tests.asInstanceOf[List[_]].foreach(_ match {
    case Pair(0, Array(Array(testHeader: String, descrExprRes),
    statements: List[_])) =>
    ... lines removed for clarity ... handleRunStatements( statements)

    An abbreviated version of handleRunStatements()'s AST and code are shown below. Notice how pattern-matching is used to recognize each statement, and then a part of the sub-onion received is passed off to the appropriate handler function.

    ASTHandler Code
    | Pair(0, @stmtClearText),
    ... lines removed ... | Pair(6, @stmtEnterText),
    ... lines removed ... | Pair(18, @stmtMoveMouse),
    ... lines removed ... )
     private def handleRunStatements(stmts: List[_]) {
    ... lines removed for clarity ... sz._1 match { case Pair(0, c2) => currentStatementName = "Clear Text"; gd(); as(traceAll); stmtClearText( c2)
    ... lines removed for clarity ... case Pair(6, txt) => currentStatementName = "Enter Text"; gd(); as(traceAll); stmtEnterText( txt)
    ... lines removed for clarity ... case Pair(18, pos) => currentStatementName = "Move Mouse"; gd(); as(traceAll); stmtMoveMouse( pos)
    ... lines removed for clarity ... }

    The code below illustrates how the enter text statement is executed. The code seems to rely on java.awt.Components having anactionEnterText(String) method! To understand this, check out SWELL Document Object Model below.

    An important part of the SWELL grammar is the SwingQuery, a construct that enables any GUI component to be referred using natural-English phrases.

    ASTHandler Code
    | Choice(
    | | Pair(0, [STRING]),
    | | Pair(1, [VAR])
    | ),
    | @swingQuery
     private def stmtEnterText(txt: Any) = {
    txt match {
    case Array(value: Pair[Int, _], compChoice) =>
    Utils.swingQuery(compChoice) match {
    case c: Component => value match {
    case Pair(0, strStr: String) =>
    ... lines removed for clarity ... } case x => throw new NotAwtComponent(Utils.scalaTypeOf(x)) } } }

    Because Swing components are central to the purpose of SWELL, its parser-rules are peppered with references toswingQuery (see Swing-Query Syntax below). The article will not go into the details of the SwingQuery grammar, but readers are encouraged to analyze and test the grammar within the VisualLangLab IDE.

    ASTHandler Code
    | Choice(
    | | Pair(0, @treePath),
    | | Pair(1,
    | | | Array(
    | | | | [INT],
    | | | | [INT]
    | | | )
    | | ),
    | | Pair(2, @uniqueComponentSelector),
    | | Pair(3, @methodCall),
    | | Pair(4, [INLINE_CODE]),
    | | Pair(5, @componentSelector),
    | | Pair(6, [VAR])
    | )
     def swingQuery(mc: Any) = mc match {
    case tPath: List[Pair[Int, _]] =>
    var expr: Any = null
    tPath.reverse.foreach(x => x match {
    case Pair(0, tp: List[_]) => expr match {
    case jt: JTree => expr = treePath(jt, tp).last
    ... lines removed for clarity ... } ... lines removed for clarity ... case Pair(1, Array(r, c)) => ... lines removed for clarity ... case Pair(2, ucs) => ... lines removed for clarity ... }) expr }

    The AST and code below illustrate the last step in the rule chain in Figure 4 above.

    ASTHandler Code
    | Choice(
    | | Pair(0, [STRING]),
    | | Pair(1, [INT]),
    | | Pair(2, [INLINE_CODE])
    | )
     def treePath(jt: JTree, path: List[_]) = {
    path.foreach(p => p match {
    case Pair(0, strStr: String) =>
    ... lines removed for clarity ... case Pair(1, strInt: String) => ... lines removed for clarity ... case Pair(2, code: String) => ... lines removed for clarity ... }) ... lines removed for clarity ... }

    SWELL has DOM and SQL (Swing Query Language) Too!

    The term DOM is used here in a sense similar to the web-browserusage. The SWELL DOM is a conceptual tree that contains all of the GUI's visual java.awt.Components. The DOM is implemented by the RichComponent class in the SWELL sources (see the src directory inside swell-article-resources.zip).RichComponent and its companion object leverage pimp my library (also see this paper from SigBovik 2010) to magically endow the lowly java.awt.Componentwith interesting methods and properties.

    As explained above, a SwingQuery is a parser-rule (see Figure 8 below) that enables SWELL scripts to refer any GUI component using natural-English (Swing Query Language or SQL) phrases. SWELL's SQL is, in every sense, the heart of SWELL. The English-like character of SWELL scripts comes entirely from SQL. The power of the DOM would be completely wasted if the SWELL user wasn't able to identify a GUI element using an English-like phrase.

    SwingQuery syntax
    Figure 8. The Swing-Query syntax

    The SQL grammar is based on the premise that the DOM is rooted at the top-level window. Any GUI Component can be uniquely identified by any one of the following:

    • a set of attribute values that uniquely identify the component in the local context
    • a path from the root to the Component of interest, where each intermediate step is a uniquely identified component

    We give a few real examples here to clarify the concepts described above. The graphics in these examples are slightly modified versions of screens captured during tests on the CIIMSmessaging-framework for airports from Unisys.

    The following SWELL statements illustrate the use of SQL to work with the login dialog panel shown in Figure 9 below. In each SWELL statement, the underlined part is the SQL.

     - key "USER01" into 
    the first textfield of the "Login" dialog - key "pass123" into 
    the passwordfield of the "Login" dialog - key "FATS01" into 
    the 2nd textfield of the "Login" dialog # the following 3 lines are equivalents, and any one may be used - click 
    the 1st button of the "Login" dialog - click 
    the first button of the "Login" dialog - click 
    the "Login" button of the "Login" dialog - click 
    the button with text = "Login" of the "Login" dialog

    In all of the above SWELL statements, [... of the"Login" dialog] would have worked as well since there is only one visible dialog, and the type (dialog) itself identifies the component uniquely.

    Locator syntax for GUI Components
    Figure 9. Locator syntax for GUI Components

    SQL can also be used with more complex GUI structures. The following two examples show how the syntax is used to access nodes of a JTree and cells of a JTablerespectively.

    Locator syntax for JTree elements
    Figure 10. Locator syntax for JTree elements

    Figure 10 above shows a JFrame main window containing a JInternalFrame that in turn contains aJTree. Parts of the figure are annotated with alphabetic markers to facilitate referencing from the following explanation.

    1. the JInternalFrame itself (A) is located with:
      the "Flow" internalframe
    2. the JTree (B) is located with:
      the tree of the "Flow" internalframe
    3. the "Events" node (C) of the JTree is located with:
      node / "Events" of the tree of the "Flow" internalframe
    4. the "TESTEVENT" node (D) of the JTree is located with:
      node / "Events" / "TESTEVENT" of the tree of the "Flow" internalframe
    5. the "TESTEVENT" node may also be located with:
      node / 2 / "TESTEVENT" of the tree of the "Flow" internalframe, or
      node / "Events" / 0 of the tree of the "Flow" internalframe, or
      node / 2 / 0 of the tree of the "Flow" internalframe

    The JFrame main window in Figure 11 below contains a JInternalFrame that in turn contains aJTable. The alphabetic markers facilitate referencing from the following explanation.

    Locator syntax for JTable elements
    Figure 11. Locator syntax for JTable elements

    1. the JInternalFrame itself (A) is located with:
      the "Statistics" internalframe
    2. the Start button (B) is located with:
      the "Start" button of the "Statistics" internalframe
    3. the JTable (C) is located with:
      the table of the "Statistics" internalframe
    4. the outlined cell (D) of the JTable is located with:
      cell 17 1 of the table of the "Statistics" internalframe

    SWELL Language Manual

    This is a short guide to the SWELL language. More details can be found at the SWELL project site.

    SWELL Statements

    The following table lists all SWELL statements.

    StatementDescriptionGrammar-Tree Name
    After-Each-TestIntroduces a list of statements that are executed after the completion of each and every test (irrespective of the test outcome)stmtAfterEachTest
    Before-Each-TestIntroduces a list of statements that are executed before eachstmtBeforeEachTest
    Clear-TextClears the text in the specified ComponentstmtClearText
    ClickPerforms a simple mouse-click over the middle of the specified Component. Left Click and Right Click are also available.stmtClick
    CollapseCollapses the specified tree nodestmtCollapse
    DelayCauses the test execution to be delayed by the specified durationstmtDelay
    DisplayDisplays the specified string in the test log (same as print)stmtDisplay
    EndEnds either the current test or the entire test suite and prints the specified message to the test logstmtEnd
    Enter-TextEnters the supplied string into the specified ComponentstmtEnterText
    ExecExectues the specified SWELL file as a sub-processstmtExec
    ExpandRecursively expands the specified tree nodestmtExpand
    Fail-IfSpecifies a condition (and associated message) for a negative test outcomestmtFailIf
    FocusMoves focus to the specified ComponentstmtFocus
    IfA conditional control flow statementstmtIf
    Key-TextKeys the supplied text into the specified ComponentstmtKeyText
    Launch-GUILaunches the specified GUI programstmtLaunchGui
    List-ComponentsLists (on the test log) one or more Components selectedstmtListComponents
    Locate-ComponentsHelps to locate one or more Components by coloring themstmtLocate
    MaximizeMaximizes the specified internal framestmtMaximize
    MinimizeMinimizes the specified internal framestmtMinimize
    Move-MouseMoves the mouse over the middle of the specified componentstmtMoveMouse
    PausePops up a blocking dialog with the specified messagestmtPause
    PerformExecutes a previously declared group or some embedded-codestmtPerform
    PrintPrints the supplied string (with variable substitutions) to the test logstmtPrint
    Reference (or Assignment)Assigns a value to a variablestmtReference
    SelectExecutes a GUI operation involving one or more selections from menus or listsstmtSelect
    SetObsolete, do not usestmtSet
    Suite-BeginsThe suite header linestmtSuitBegins
    Suite-EndsThe suite trailer linestmtSuitEnds
    TraceStarts or ends tracingstmtTrace
    UnlessThe unless statement is an inverse if statementstmtUnless
    WaitCauses execution to be delayed till the specified event occursstmtWait
    WarnIfCauses a warning to be issued to the test log if the specified condition occursstmtWarnIf
    WhileThe usual procedural control flow statementstmtWhile

    Embedded Code

    Several SWELL statements allow the use of embedded Scala code. Embedded Scala code must be enclosed within doubled curly-braces, like this: {{your code here}}. Check the tokenINLINE_CODE for details.


    Time durations in SWELL may be expressed either as seconds or milli-seconds. The unit specification (which follows the magnitude) may be any of the following: s, second, seconds, milli second, milli seconds, ms. Review the parser-rule timeDuration for details.


    Several SWELL statements require (or optionally permit) the use of variables. Variable names are user-chosen following the usual conventions of contemporary programming languages. Variable references are given using the form ${variable name}. Check the token called VAR


    The article introduces the SWELL domain-specific language for testing Swing GUIs. The SWELL interpreter uses the completely visual parser-generator VisualLangLab, so the design of SWELL described in the article is also a generic framework for DSLs that use VisualLangLab as their parser-generator.

    The SWELL interpreter (being developed at the SWELL Project) is already usable and reliable enough to be valuable in real-world development projects. The authors plan to continue improving upon this early code base to improve the tool further.


    We would like to thank the following folks at TwoPiRadian Infotech (2PiRad): Prodipta Golder, Debopam Ghoshal, and Ramanendu Chatterjee for the numerous discussions and great ideas that helped to shape the DSL, and Jishnu Ray for editorial comments and guidance on the article contents. The DSL was analyzed, reviewed and refined in lively discussions with many others, and the world's population of DSLs would be one less without 2PiRad's amazing people and environment.

    TwoPiRadian Infotech is a boutique software solutions developer, specializing in developing dynamic web applications, rich internet applications, collaboration and content management systems. They have in-depth experience in the new generation software technology platforms covering key business domains (airports, airlines, travel & hospitality, and financial services)