I ended up solving the problem only by having the root level object in the object map. All other objects are repeated in code using the following functions.
import sys
import time
ROOT_SYMBOLIC_OBJECT = ":_KMainView"
def findSymbolic(symbolicName):
try:
obj = findObject(symbolicName)
except LookupError:
sys.exc_clear()
test.log("FAIL: Root object not found: " + symbolicName)
sys.exit()
return obj
def findRoot():
return findSymbolic(ROOT_SYMBOLIC_OBJECT)
def findFlat(fromElement, findId, occurence, stopOnFail, verbose):
start = time.time()
result = None
found = 0
if fromElement and hasattr(fromElement, 'children'):
children = object.children(fromElement)
for child in children:
if hasattr(child, 'id') and child.id == findId:
found += 1
if found == occurence:
result = child
break
if result == None and stopOnFail:
test.log("FAIL: findFlat: " + findId + " not found")
sys.exit()
if verbose:
printElapsed("findFlat", findId, start)
return result
def findRecursive(fromElement, findId, occurence):
return findRecursiveWithOptions(fromElement, findId, occurence, True, False, True)
def findRecursiveWithOptions(fromElement, findId, occurence, stopOnFail, verbose, skipUnnamed):
start = time.time()
found = 0
depth = -1
obj, found, depth = objIter(fromElement, findId, occurence, verbose, skipUnnamed, found, depth)
if found == occurence:
printElapsed("findRecursive ok", findId, start)
return obj
printElapsed("findRecursive not found", findId, start)
if stopOnFail:
test.log("FAIL: findRecursive:" + findId + " not found.")
sys.exit()
return None
def objIter(fromElement, findId, occurence, verbose, skipUnnamed, found, depth):
depth += 1
if verbose:
printObjIter(fromElement, depth)
children = object.children(fromElement)
for child in children:
if hasattr(child, 'id'):
if child.id == findId:
found += 1
if found == occurence:
return child, found, depth
elif skipUnnamed:
continue
obj, found, depth = objIter(child, findId, occurence, verbose, skipUnnamed, found, depth)
depth = depth - 1
if found == occurence:
return obj, found, depth
return None, found, depth
def findRecursiveList(fromElement, findId):
return findRecursiveListWithOptions(fromElement, findId, True, False, True)
def findRecursiveListWithOptions(fromElement, findId, stopOnFail, verbose, skipUnnamed):
start = time.time()
objList = []
depth = -1
objList, depth = objListIter(fromElement, findId, verbose, skipUnnamed, objList, depth)
printElapsed("findRecursiveList", findId, start)
return objList
def objListIter(fromElement, findId, verbose, skipUnnamed, objList, depth):
depth += 1
if verbose:
printObjIter(fromElement, depth)
children = object.children(fromElement)
for child in children:
if hasattr(child, 'id'):
if child.id == findId:
objList.append(child)
elif skipUnnamed:
continue
objList, depth = objListIter(child, findId, verbose, skipUnnamed, objList, depth)
depth = depth - 1
return objList, depth
def printElapsed(functionName, objectId, start):
elapsed = time.time() - start
test.log(functionName + " - " + objectId + " in " + str(elapsed) + "s.")
def printObjIter(element, depth):
dashes = "-" * depth
if hasattr(element, 'id'):
test.log(dashes + " " + str(element.id))
else:
test.log(dashes + " [unnamed]")
Sample test script for a QML question:
startApplication("exampleapp")
snooze(10)
root = findRoot()
page = findFlat(root, "page", 1, True, False)
foobar = findFlat(page, "foobar", 1, True, False)
if foobar.text == "ipsum":
test.passes("text is ok")
else:
test.fail("Incorrect foobar text: " + foobar.text)