Pressing the play button will load a video from our external provider YouTube. Privacy Policy

Beyond Strings – How To Effectively Use Object Variables In QF-Test 9

Slides and Materials

Contents

00:00 Intro
02:08 Until QF-Test 8: All variables are Strings
02:50 Automatic Conversion
6:22 Since QF-Test 9: Variables store original object
12:32 Representation in run log and protocol
16:48 Replacement of variable values (expand)
19:08 Simplified access in scripts
22:31 Default values
31:10 Return value in procedures
31:33 Conversion if required
47:16 Additional information
51:30 Usage example: Configuration
56:40 Usage example: Process Parameters

Code examples and summaries

Until QF-Test 8: All variables are Strings

Simple Assignment: Name (String) -> Value (String)

Automatic Conversion

Write:

rc.setGlobal("Numbervalue", 23) // -> Converts into the String "23"
rc.setLocal("Booleanvalue", true) // -> Converts into the "true"
rc.setProperty("Object", new Object()) // -> Converts into the String "java.lang.Object@29f364c"

Read:

rc.getStr() // -> returns directly the variable value
rc.getBool() // -> Value in ("1","y","yes","true","True",…) ?
rc.getInt() // -> Integer.valueOf(Value) / new BigInteger(Value)

Since QF-Test 9: Variables store original object

New Assignment: Name (String) -> VariableData

With:

  • Value (any Object): .getObject()
  • String value (String): .toString()
  • Description (String): .getDescription()

No change “from the outside” during access:

  • Like before: $(name) and ${group:name}
  • Like before: rc.getStr(…), rc.getInt(…), rc.getBool(…), …
  • New: rc.getObj(name) and rc.getObj(group, name)

Representation in run log and protocol

Replacement of variable values (expand)

rc.setLocal('ext', 'TXT')
rc.setLocal('filename', 'qftest.$(ext)')
rc.getStr('filename', expand:true) // -> 'qftest.TXT'
rc.getStr('filename', expand:false) // -> 'qftest.$(ext)'
rc.getStr('filename') // ?
rc.getStr('filename', expand:null) // -> 'qftest.TXT'
rc.setLocal('regexp', Pattern.compile('abc$(ext)'))
rc.getStr('regexp', expand:true) // -> 'abcTXT'
rc.getStr('regexp', expand:false) // -> 'abc$(ext)'
rc.getStr('regexp') // -> 'abc$(ext)' – new!

Simplified access in scripts

obj1 = rc.getObj('varname')
rc.setLocal('answer', 42)
obj2 = rc.getObj('groupname','propname')
dir = rc.getObj('qftest','suite.dir')
xxx = rc.getObj('decrypt','C2094F52F62C0D7953E0CEFF81E269A7')
rc.setProperty('newGroup','newName','newValue')
obj1 = rc.vars.varname
rc.vars.answer = 42
obj2 = rc.groups.groupname['propname'] = rc.groups.groupname.propname
dir = rc.groups.qftest['suite.dir'] = rc.groups.qftest.suite.dir
xxx = rc.groups.decrypt['C2094F52F62C0D7953E0CEFF81E269A7']
rc.groups.newGroup.newName = newValue

Default values

dflt = rc.getObj('default','unknown:Standardvalue')
dflt = rc.groups.default['unknown:Standardvalue']
dflt = rc.withDefault('Standardvalue').vars.unknown
gd = rc.withDefault('Standardvalue').groups.unknowngrp.unknownprop
dflt = rc.withDefault('Standardvalue').getObj('unknown')
gd = rc.withDefault('Standardvalue').getObj('unknowngrp','unknownprop')

Return value in procedures

throw new ReturnException('NeuerValue')

rc.returnValue('NeuerValue')

rc.returnValue(myObject)

value = qf.wrapObject(myObject)
value = qf.wrapObject(myObject,'String value','Description')
rc.returnValue(value)

Conversion if required

  • Replacements in combinations: -> String
    • "Today I turn $(age)."
    • "${qftest:suite.dir}/test.png"
  • Complete replacement -> Object type is preserved!
    • "$(data)"
  • Still automatic:
    • rc.getInt(…), rc.getNum(…), rc.getStr(…), rc.getBool(…)
  • Explicitely with the special group “as”:
    • String expansion: ${as:int:23}, ${as:bool:$(is_available)}
rc.getObj('as','int:23')
rc.getObj('as','bool:$(is_available)')

Valid types:

  • str, bool, number, object, pattern, int, long, float, double, cmdline, json

Variable exchange QF-Test <-> SUT

  • QF-Test and the application under test run in different processes
  • Data exchange via (Java Remote Method Invocation)
  • Also objects in variables
  • Must be Serializable
  • The class definition has to be available in both processes
  • Works for example with standard classes:
    • String, Wrappers (Integer, Boolean, …), Pattern, Date
    • ArrayLists, HashSets (depending in the contents)
  • Falls back on the “String value” in the other process
  • In the original process still available as Object (+String)

Additional information

  • Decrypted flag
    • Is set automatically if ${decrypt:…} is expanded.
    • The “description” of the value (e.g. in the run log) is always “***”
    • rc.logMessage(rc.getStr("secret")) still logs the real value!
    • Is “inherited” during expansion.
  • AutoExpandable flag
    • Avoids replacing variables in Strings “by incident”
    • E.g. in the return value of qfs.utils.readTextFromFile
    • rc.returnValue(text, autoExpandable:false)
    • wrapped = qf.wrapObject(text); wrapped.setAutoExpandable(false)
  • Rerun from run log
    • Only available for certain (simple) objects