Thursday, October 7, 2010

Implementing asynchronous Robot Framework keywords

Before tests can be run I have to start all the necessary systems (processes, servers, stuff and things). Let's imagine that there are multiple systems that need to be started. I would like to start them all at the same time and wait until they are all ready to rock 'n' roll before starting my tests (assume that it would take a lot longer if I started all the systems in sequence).

So how to do this with Robot? Basic idea is to have re-usable keywords for starting each system and a keyword for waiting until the systems are ready so that testing can begin (and we don't have to use ugly and unreliable sleeps). Doing this on Robot keyword level makes it possible to have different combinations of systems in different tests.

*** Settings ***
Documentation Example of using parallel things
Suite Setup StartSystems
Library SystemStarterLibrary.py

*** Test Cases ***
... Here should be my tests

*** Keywords ***
StartSystems
${SYSTEM1_STARTED}= Asynchronously Start System 1
${SYSTEM2_STARTED}= Asynchronously Start System 2
Wait until ${SYSTEM1_STARTED} ${SYSTEM2_STARTED}




The way I'm going to implement this is by using python decorator that executes the function that it decorates in a separate thread. The decorated function will return the thread object so that it can be used to implement the waiting functionality.

I'm using this little code for the decorator.

After I've imported that to my SystemStarterLibrary.py I can implement system starter functions as normal functions.

@run_async
def asynchronously_start_system_1():
.. do stuff to start system 1

@run_async
def asynchronously_start_system_2():
.. do stuff to start system 2


Now all I need to do is to implement Wait until.

def wait_until(*stuff):
for something in stuff :
something.join()



This is kind of OK but it will wait forever if starting of some system will take forever. So it is better to have some timeout that will tricker setup failure after the timeout.

*** Keywords ***
StartSystems
[Timeout] 5 minutes
${SYSTEM1_STARTED}= Asynch Start System 1
${SYSTEM2_STARTED}= Asynch Start System 2
Wait until ${SYSTEM1_STARTED} ${SYSTEM2_STARTED}


And that should do it.

No comments: