Large Test Batch (3000 test cases) gradually slows down in execution

Asked by Nathan Ash-Vie

Hello all,

Hoping someone might be able to offer some advice.

First a little background... I have written a script that automatically enters test cases into a UI I am testing. The UI contains around 90 fields each of which is populated from a CSV file (which is read by the Sikuli script). The script is perfectly functional and enters the test cases without issue if left for several days.

The problem I have is the speed at which keys are typed gradually slows down the longer Sikuli runs. To start with a test case takes around 19 seconds to enter. After 1000 test cases the execution has slowed to 43 seconds and by the end of the file it's several minutes. The java memory use peaks at 750mb which is absolutely fine (the machine has 8gb RAM). I'm unsure how to prevent the degredation in peformance. A few pieces of key info:

• The tests themselves do not appear to be the cause as I tried running some of the later tests (800-1000) at the beginning of the batch and they averaged 19 seconds. It purely seems to be the length of time Sikuli has been running.

• Ending the script (Shift-Alt-C) and immediately restarting it from the point it had reached results in the script immediately speeding back up. The increase in speed is quite noticeable.

• No memory problems are encountered no matter how long the script has been running.

• The system is responsive after the script is stopped.

• CPU use is not excessive whilst running.

• The Sikuli script is 806 lines in length which doesn't seem to be excessive.

Is anyone else having trouble?

Thanks,

Nathan

EDIT: Is it possible to restart Sikuli via Jython? Perhaps raise a SystemExit and have it run the script afresh?

Question information

Language:
English Edit question
Status:
Answered
For:
SikuliX Edit question
Assignee:
No assignee Edit question
Last query:
Last reply:
Revision history for this message
RaiMan (raimund-hocke) said :
#1

-- how do you get the data from the csv file and how do you provide it to the test function? everything inline or somehow modularised/seperated into functions?

This is some kind of data driven testing: so you might simulate the behaviour of e.g. TestNG and spawn every test run into a new thread with a clean setup and teardown.
So you are able to separate the managing of the data from the test run.

When running such tests from command line, you have more options to abort the test at the time, when test runs start to last longer and take appropriate actions (e.g. abort and restart)

Revision history for this message
Nathan Ash-Vie (nathaniel-ash-vie) said :
#2

This is how I extract the data from the CSV file:

    xReader = file("G:\\UW Manual\\EDI Development\\Test Batches\\i90 Rates Bulk Test Pack - CDN.csv")

    for line in xReader:
        Val = line.strip().split(",")

The loop contains around 700 lines of automation but 99% of it is simply using the paste function for the current CSV cell value. For instance:

            paste(Val[3]) #Policyholder Name
            type(Key.TAB)

            paste(Val[5]) #Title
            type(Key.TAB)

            paste(Val[6]) #Marital
            type(Key.TAB)

            paste(Val[7]) #Gender
            type(Key.TAB)
            type(Key.TAB)
            type(Key.TAB)
            type(Key.TAB)

Every now and again there is some data formatting (for instance converting US date formats into EU data formats e.g. MM/DD/YY into DD/MM/YY).

There is a lot of image recognition, for instance there are 26 waits which ensure the script does not begin entering information before the screen has fully transitioned:

            wait("1386751004792.png",10)

To capture results I write to text files:

        if not os.path.exists(ResultsDir):
            os.makedirs(ResultsDir)

        #Capture results
        ResultsFile = open(ResultsDir + "\Test " + str(testCount) + ".txt", "w")
        ResultsFile.write(Results.encode('latin-1'))
        ResultsFile.close()
        Results = ""

I've not modularised or separated the code into functions/subs. This is the first time I've used the Jython. Is it fully OO e.g. class hiearchies, interfaces and inheritance or can you simply create subs/functions and have the script run procedurally?

Thanks,

Nathan

Revision history for this message
Nathan Ash-Vie (nathaniel-ash-vie) said :
#3

Forgot to add, thanks much for taking the time to reply. In response to the following:

"spawn every test run into a new thread with a clean setup and teardown"

That sounds more scalable. How does threading work in Jython, do you inherit from a Thread class ala Java? Do you use readers/writers to communicate between threads?

Thanks,

Nathan

Revision history for this message
RaiMan (raimund-hocke) said :
#4

-- Jython
yes Jython is fully OO: everything is an object, even functions.
The great advantage of language implementations like Jython, JRuby, Clojure, Scala, ..., is, that at every point in your script you can dive down to the Java level and use everything that Java offers.
This is why Sikuli uses Jython as the top level scripting environment (JRuby and others will follow next year).
... but the Jython currently used is on the Python language level 2.5 (going to 2.7 with the next version) and many Python modules cannot be used with Jython, because they contain C-based parts. Only modules completely written in Python are useable.

-- your script
I cannot see any obvious reason for the slowdown.

The only "flexible" parts are the wait-on-images. Since you use a max wait time of 10 seconds in your example: do you suspect your app to take some seconds to complete a GUI transition? If yes, are your sure that it is not your app that slows down over the time? Having 26 of these waits might sum up to some critical amount of elapsed time, if transition takes longer.

Currently you do not have any profiling in your script. At some points in your script, you might add this:
start = time.time()
# some code
Result += "naming the point: %d msec\n"%(time.time()-start)

and get some timing information in your result doc.

-- threading
the following is the most basic implementation of a thread, where the main waits for the completion.

import thread
def thread_function(args, kwargs = None):
# args is a list of values (might be your list Val)
# kwargs is a dictionary of key/value pairs) (optional)
   running = True
# here goes the payload of your loop, that deals with the test data given by Val
   running = False
   # the thread is closed here

# the following might be put into the csv-read-loop
running = False
thread.start_new_thread(thread_function, Val)
while not running: #waiting for start of thread
    wait(1)
while running: #waiting for the thread to end
    wait(1)

There is another module threading which allows much finer control over threads running in parallel (thread pools).

Can you help with this problem?

Provide an answer of your own, or ask Nathan Ash-Vie for more information if necessary.

To post a message you must log in.