Extended variable syntax
Extended variable syntax allows accessing attributes of an object assigned to a variable (for example, ${}
) and even calling its methods (for example,${()}
). It works both with scalar and list variables, but is mainly useful with the former
Extended variable syntax is a powerful feature, but it should be used with care. Accessing attributes is normally not a problem, on the contrary, because one variable containing an object with several attributes is often better than having several variables. On the other hand, calling methods, especially when they are used with arguments, can make the test data pretty complicated to understand. If that happens, it is recommended to move the code into a test library.
The most common usages of extended variable syntax are illustrated in the example below. First assume that we have the following variable file and test case:
class MyObject: def __init__(self, name): self.name = name def eat(self, what): return '%s eats %s' % (self.name, what) def __str__(self): return self.nameOBJECT = MyObject('Robot')DICTIONARY = {1: 'one', 2: 'two', 3: 'three'}
*** Test Cases ***Example KW 1 ${} KW 2 ${('Cucumber')} KW 3 ${DICTIONARY[2]}
When this test data is executed, the keywords get the arguments as explained below:
- KW 1 gets string
Robot
- KW 2 gets string
Robot eats Cucumber
- KW 3 gets string
two
The extended variable syntax is evaluated in the following order:
- The variable is searched using the full variable name. The extended variable syntax is evaluated only if no matching variable is found.
- The name of the base variable is created. The body of the name consists of all the characters after the opening
{
until the first occurrence of a character that is not an alphanumeric character or a space. For example, base variables of${}
and${DICTIONARY[2]}
) areOBJECT
andDICTIONARY
, respectively. - A variable matching the body is searched. If there is no match, an exception is raised and the test case fails.
- The expression inside the curly brackets is evaluated as a Python expression, so that the base variable name is replaced with its value. If the evaluation fails because of an invalid syntax or that the queried attribute does not exist, an exception is raised and the test fails.
- The whole extended variable is replaced with the value returned from the evaluation.
If the object that is used is implemented with Java, the extended variable syntax allows you to access attributes using so-called bean properties. In essence, this means that if you have an object with the getName
method set into a variable ${OBJ}
, then the syntax ${}
is equivalent to but clearer than ${()}
. The Python object used in the previous example could thus be replaced with the following Java implementation:
public class MyObject: private String name; public MyObject(String name) { name = name; } public String getName() { return name; } public String eat(String what) { return name + " eats " + what; } public String toString() { return name; }}
Many standard Python objects, including strings and numbers, have methods that can be used with the extended variable syntax either explicitly or implicitly. Sometimes this can be really useful and reduce the need for setting temporary variables, but it is also easy to overuse it and create really cryptic test data. Following examples show few pretty good usages.
*** Test Cases ***String ${string} = Set Variable abc Log ${()} # Logs 'ABC' Log ${string * 2} # Logs 'abcabc'Number ${number} = Set Variable ${-2} Log ${number * 10} # Logs -20 Log ${number.__abs__()} # Logs 2
Note that even though abs(number)
is recommended over number.__abs__()
in normal Python code, using ${abs(number)}
does not work. This is because the variable name must be in the beginning of the extended syntax. Using __xxx__
methods in the test data like this is already a bit questionable, and it is normally better to move this kind of logic into test libraries.
Extended variable syntax works also in list variable context. If, for example, an object assigned to a variable ${EXTENDED}
has an attribute attribute
that contains a list as a value, it can be used as a list variable @{}
.