The environment editor is used to create and edit variables in the environment of a test suite, a test plan or a compound block. In imported suites/libraries, a readonly version of this editor is shown. The view slightly differs when either the testsuite's or a compound block's environment is edited. It can be found on the "Environment" tab after selecting the test suite or a compound block in the navigation tree.
Environment variables can be used as input to a step by setting an input pin's input value (freeze value) to "Read from Environment" via the pin's menu. The standard library also contains a number of blocks to dynamically add, remove, read or modify environment variables.
Environments are arranged as a hierarchy of local environments (lexical scope), so that an inner block's variable may hide an outer block's variable, up to the containing test plan and finally the test suite's environment. By default, an inner variable (i.e. from a deeper nesting) shadows a corresponding outer variable, but this behavior may be reversed for special situations, where an inner variable is used to provide a fallback value for testing.
- This field is a text input field that holds the variable name, which must meet the rules for variable naming (alphanumeric or underline character, no embedded spaces). Click it once to give it the input focus.
- NET (visible in expecco ALM)
- This checkbox determines whether the variable will be visible in expeccoNET or in exported parameter sets. Such externally visible variables can later be provided by whoever initiated the automatic test run (i.e. expecco ALM, another QM platform, an external parameter file or provided as command line argument). This option/column is only shown in the project's variable environment.
- MON (monitor variable)
- This option is only useful if expecco is used in conjunction with certain versions of expecco ALM. It defines the variable as a monitored variable. Such variables send out change notifications in realtime, which can be monitored by the QA platform (currently: only expecco ALM supports this).
- OW (overwrite)
- This check box determines whether the variable hides (overwrites) an inherited variable from an outer scope, or not. This option/column is only shown for compound blocks. The default mode is "overwrite", so variables behave as if defined in a lexical scoped fashion: variables can be redefined in a compound block to overwrite any outer definition of the same named variable.
The non-overwrite mode is useful if a block wants to define a variable's fall back or default value, to be used if no outer definition exists.
For example, an interface block which needs a port number (for example: HTTP Port) might define the variable as a non-overwriting local variable, with a value of "80". If an outer block or the test suite needs a different parameter, it is free to define HTTP Port with another value (see also "Hints & Tricks" below).
- R/W (read/write)
- This field is a check box that determines whether the variable can be modified during initialization, or not. Parameter values should be set to read only, which is the default for new variables.
- This drop down list provides a list of available data types. Choose the type of the variable here (typically, most likely a String- or Integer type is used)
- This drop down list provides a list of possible initialization methods for the variable's value. Most common are Constant and New Instance, but it is also possible to assign a value during initialization by evaluating a programmatic expression, or to request values from the user via a dialog. See list below.
- Initial Value/Expression
- Use this text field to enter the initial value (if the initialization method is Constant).
- Current Value
- This field shows a variable's current value. This information is useful for writable variables (for example: counters or other measurements as gathered during execution) or for user-entered variables. Notice, that the top-level test suite environment is initialized one, when the suite is loaded, so you may have to manually reset modified counters if stored in the global environment, if the suite is executed multiple times.
Notice that variables are only initialized once, when the environment itself is instantiated. The instantiation happens at load time for the top-level project environment, or with every execution for the test suite, test case and action environments.
The concrete behavior, depending on the init-type, is:
- a constant value, such as a port number, counter values, host name or other simple (unstructured) values. This value is used "as is". You may refer to other variables by name or the operating system's shell environment variables using a $-prefix: use "$(Name)" to refer to the value of the variable named "Name". The parenthesis are required. Thus if your environment contains a variable "Foo", with value "Hello", the value "$(Foo)World" will expand to "HelloWorld" whereas "$Foo World" remains as is.
Be careful when referring to variables from within the same environment, because they are initialized top-to-bottom, and the values of variables further down the list will not yet be setup. In addition to the shell's variables, such as "$(USERNAME)" and "$(PATH)", a few additional pseudo variables are accessible:
- $(AttachmentsDirectory) - the directory where all of project's attachment files are located (by ID, not by name)
- $(ProjectDirectory) - the temporary directory where all of the project's files are located. This directory will be removed when another project is loaded, or expecco is terminated.
- $(ExecutionDirectory) - the temporary directory where temporary files during a single test execution are located. This directory will be removed after the execution.
- $(ExpeccoInstallationDirectory) - the directory where expecco is installed.
- $(ExpeccoPluginDirectory) - the directory where expecco plugins are installed.
- like above, but its value is not shown in the variable-environment; useful for passwords. Notice: the algorithm for password storage is not secure. It will be easy for any experienced user/programmer to extract these values from either the saved test-suite or via an inspector from the running test-suite. Also, the value might also be visible in the execution log, if it is passed as String through input/output pins.
- New Instance
- creates a new (empty) instance of the data type.
- New Instance of Size
- given its size in the environment, create a vector (collection-like) instance.
- Ask for Size
- will ask the user for the size of an instance to create.
- Request from User
- opens a dialog to ask for the variable's value, when the project is loaded. You can define the dialog box's question title in the comment.
- Request from User when first used
- opens a dialog to ask for the variable's value, when the variable's value is needed for the very first time during the session. If the value is never needed (because the block(s) which need this value are not executed), no question dialog will be shown during execution. You can define the dialog box's question title in the comment.
- Secret from User
- like "Request from User", but hides the password in the dialog, and only displays '*'s in the value fields.
- Secret from User when first used
- like "Request from User when first used", but hides the password in the dialog.
- Smalltalk Expression
- the text is evaluated as a Smalltalk expression and the resulting value used to initialize the variable.
- a special type used with GUI blocks.
- a special type used with GUI blocks.
The "when first used" initialization-type is useful for passwords of dynamically alternative execution paths - for example, if your test suite needs either an FTP- or an HTTP password, depending on which communication path is chosen dynamically.
- Initialize the environment with the given values (only shown in the project's environment). This is done automatically, when a test suite is loaded initially, but may also be needed to reset read/write variables which have been modified by a test run back to their initial state, or to have computed values be recomputed.
- Move the selected variable upwards in the list. As variables are initialized in the order of appearance, this may affect the order of execution of any computed values
- Move the selected variable downwards in the list
Popup Menu Functions (Right-Button-Menu)
The right mouse button shows the following popup menu items:
- undo the last cut/paste operation (inside the variable editor)
- Add Variable
- add another variable
- Cut Variable
- remove the selected variable(s). These are put into the clipboard and can bbe pasted at another place.
- Copy Variable
- copy the selected variables to the clipboard
- Paste Variable
- paste the variables in the clipboard
- Move Variable To..
- to move the selected variables into another environment
- Rename Variable...
- rename a variable. Searches for uses of the selected variable and renames those references, too. However, if the name is constructed somewhere, it may not be found. So use with care.
- Load Entries from File...
- to load a file containing a set of values. The file can be in expecco's native XML format, in JSON or in CSV (i.e. imported from excel). For details, read the chapter on file formats below.
- Save all Entries to File
- to save all variables into a file. Specify XML (expecco's native format), JSON or CSV. For details, read the chapter on file formats below.
- Save Selected Entries to File
- like above, but only the selected variables are saved. For details, read the chapter on file formats below.
- search for references to this variable in the suite
- Inspect Current Value
- opens an inspector window on the selected value.
- additional, less frequently used menu items
- Move Up / Down
- to move the selected variable(s) up/down in the list
External File Formats
Parameters can be stored separately from a suite in a so called "parameter file". These can be generated by expecco itself (via the above described "Save As.." menu functions, or created manually in a text editor, or generated by another program.
Multiple formats are supported directly:
this is expecco's native and preferred format for parameter files.
a JSON file should contain a single object which is an array of structure (dictionary) objects. Each should contain the name and value of a single parameter.
two formats are supported: one describes each variable in a separate row as name-value pair (a vertical structure). The other contains exactly two rows, where the first contains all names, and the second contains all values (horizontal format). Both can easily be imported to or exported from excel and other table oriented calculators.
Other formats can be used by creating a reader-action block, which reads any custom format and sets the variables using environment-setter actions from the standard library.
Hints and Tricks
Environment variables are your most powerful feature to ensure flexibility of your test suite and to minimize future maintenance efforts. Be reminded, that these variables can be preset individually via the command line or by providing a separate parameter file, which can also be specified via the command line.
By placing configuration values (host names, port numbers, URLs, paths, version numbers etc.) into top-level environment variables, these make sure that:
- magic constants are not spread all over your suite, making it hard to change such values later
- the search functions can be used to find places in your suite, where a particular value is used
- any test execution can later be customized, by providing either an individual variable's value or a complete set of values via the command line
- if used with expecco ALM, these values can be define in that central management tool, and will be passed down to the suite with every execution
Overwritable Default Values
It is often useful to define a variable in an inner block (a compound block), so that the test-developer can run individual actions during test development. Typical scenarios involve host names or test-URLs, which may be different for the test-developer and the final (automated) test execution. In this case, the test-developer wants to see his own (private) values when he runs individual action blocks, whereas for automation, these values should be overwritten by providing values for the top-level environment. With normal scoping rules (i.e. inner definitions overwrite outer scopes), this would not be possible. However, the "OW" (Overwrite) flag allows for the scoping rules of an individual variable to be reversed, so that the inner scope value (on the block level) is only used iff no value is present on the outer (the suite) level.
Multiple Executions with Different Variable Values
Be reminded, that test plans can be nested, and offer a separate variable scope during their execution. You can wrap a whole testplan into another (master-) testplan, which simply executes the wrapped actions with different variable settings. For this, create one wrapper test plan for each run, providing different variable values as per run. Then place all those wrappers into a "master" testplan, which runs them in sequence. Of course, this can also be done with compound actions, by wrapping one action into another compound, which simple sets up a different variable scope for the inner action.