Skip to main content

SWELL - An English-Like DSL for Swing Testing

November 17, 2011

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 understand 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 language 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 problem 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 create SWELL—An English-Like DSL for Swing 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 Components to 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 interpreter that 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 suite delimited 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 a test 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 the SWELL 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 the file listed in the Resources section at the bottom of this article.


Apart from the contents of the 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 file, and unzip the contents into a directory (called swell-article-resources)
  • obtain the latest download from the Abbot Java GUI Test Framework, and copy all its jar files into the jars subdirectory of the swell-article-resources directory
  • on Windows: open a CMD window, cd into the swell-article-resources directory, and run the command "launch.bat test-SampleGrammars.txt"
  • on Linux/Mac OS/*NIX: at a shell prompt, cd into the swell-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 named test-SampleGrammars.log

Running your own SWELL Tests

The 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 into the swell-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 or launch-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 file as well as additional documentation are being published as an open-source project hosted at 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 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 AST produced.

If you haven't downloaded VisualLangLab yet, get the VLLS-All.jar file 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 Reference node 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, stmtEnterText needs to invoke swingQuery as well, but does not require treePath.

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 ( 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 a grammar-file with a .vll type. A program that uses such a parser (like the SWELL interpreter) uses the VisualLangLab API to turn this XML into an instance of the Scala Parsers type. 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's pattern 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 the Suite_handler().

Those interested in reviewing the full code should visit the src directory of the 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().

AST Handler 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 to handleTests() is shown below left, and a part of handleTests()'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().

AST Handler 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.

AST Handler 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 an actionEnterText(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.

AST Handler 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 to swingQuery (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.

AST Handler 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.

AST Handler 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-browser usage. 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 RichComponent and its companion object leverage pimp my library (also see this paper from SigBovik 2010) to magically endow the lowly java.awt.Component with 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 CIIMS messaging-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 JTable respectively.

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 a JTree. 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 a JTable. 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.

Statement Description Grammar-Tree Name
After-Each-Test Introduces a list of statements that are executed after the completion of each and every test (irrespective of the test outcome) stmtAfterEachTest
Before-Each-Test Introduces a list of statements that are executed before each stmtBeforeEachTest
Clear-Text Clears the text in the specified Component stmtClearText
Click Performs a simple mouse-click over the middle of the specified Component. Left Click and Right Click are also available. stmtClick
Collapse Collapses the specified tree node stmtCollapse
Delay Causes the test execution to be delayed by the specified duration stmtDelay
Display Displays the specified string in the test log (same as print) stmtDisplay
End Ends either the current test or the entire test suite and prints the specified message to the test log stmtEnd
Enter-Text Enters the supplied string into the specified Component stmtEnterText
Exec Exectues the specified SWELL file as a sub-process stmtExec
Expand Recursively expands the specified tree node stmtExpand
Fail-If Specifies a condition (and associated message) for a negative test outcome stmtFailIf
Focus Moves focus to the specified Component stmtFocus
If A conditional control flow statement stmtIf
Key-Text Keys the supplied text into the specified Component stmtKeyText
Launch-GUI Launches the specified GUI program stmtLaunchGui
List-Components Lists (on the test log) one or more Components selected stmtListComponents
Locate-Components Helps to locate one or more Components by coloring them stmtLocate
Maximize Maximizes the specified internal frame stmtMaximize
Minimize Minimizes the specified internal frame stmtMinimize
Move-Mouse Moves the mouse over the middle of the specified component stmtMoveMouse
Pause Pops up a blocking dialog with the specified message stmtPause
Perform Executes a previously declared group or some embedded-code stmtPerform
Print Prints the supplied string (with variable substitutions) to the test log stmtPrint
Reference (or Assignment) Assigns a value to a variable stmtReference
Select Executes a GUI operation involving one or more selections from menus or lists stmtSelect
Set Obsolete, do not use stmtSet
Suite-Begins The suite header line stmtSuitBegins
Suite-Ends The suite trailer line stmtSuitEnds
Trace Starts or ends tracing stmtTrace
Unless The unless statement is an inverse if statement stmtUnless
Wait Causes execution to be delayed till the specified event occurs stmtWait
WarnIf Causes a warning to be issued to the test log if the specified condition occurs stmtWarnIf
While The usual procedural control flow statement stmtWhile

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 token INLINE_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)



Sanjay Dasgupta has been using Java for telecom applications since 1996 (after many years of using many different languages in many industries).
Chirantan Kundu is Analytics Principal at TwoPiRadian Infotech ( He has been designing and developing software, and managing software projects for over 15 years
SWELL_FirstVLLTest.png33.12 KB
SWELL_initial-grammar-view.png26.07 KB
SWELL_locators-dialog.png10.54 KB
SWELL_locators-table.png33.8 KB
SWELL_locators-tree.png22.15 KB
SWELL_navigatingGrammarCompressed.png24.82 KB
SWELL_singleTest-goto.png22.58 KB
SWELL_SWELL-Structure.png7.36 KB
SWELL_SwingQuery.png29.56 KB
SWELL_testing-stmtEnterText.png33.18 KB
SWELL_testing-treePath.png27.25 KB
Related Topics >> Swing   |   Testing   |   Tools   |   Featured Article   |