Run script silently and collect errors in log file

Asked by Pascal Roth

--- the solution's requested features
- should not abort caused by errors like FindFailed
- should report failure situations
- should present a compound failure report after completion

----------------------------------------------------------------

Hallo zusammen,

ich arbeite zurzeit an einem Projekt zu dem ich das Programm Sikuli verwende. Ich wollte nun wissen, ob es eine Möglichkeit gibt das ich das Programm durchlaufen lasse ohne das es bei einem Fehler abbricht und ich mir zum Schluss eine detailierte Fehlermeldung ausgeben lassen kann?

Question information

Language:
German 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

Nein, sowas geht mit Sikuli nicht.

Jeder Fehler (Image nicht gefunden) führt mit den Standardeinstellungen zum Abbruch.

Man kann zwar einstellen, dass in diesem Fall nicht abgebrochen wird, aber dann gibt es im Standard auch keine Fehlermeldungen.

Alternativ kann man exists() generell und ausnahmslos verwenden - z.B. so
if not exists(some_image):
    print "nicht gefunden", some_image
    # hier musst du überlegen wie es weiter gehen soll ;-)
click(getLastMatch())

Das grundsätzliche Problem:
Wenn in einem Sikuli Workflow ein Image nicht gefunden wird, obwohl du es an dieser Stelle erwartest, dann macht es üblicherweise auch keinen Sinn, den Ablauf fortzusetzen ohne irgendwelche "recovery actions".

Wenn ich nicht richtig verstanden habe, was du willst, dann sag es.

Revision history for this message
j (j-the-k) said :
#2

Also ich würd das so machen:

log = []

# Bei jeder Region/Screen Exception deaktivieren
setThrowException(False)
# Dann das script ausführen und ggf. ein Log schreiben
if (wait/find/exists("bild.png") == None):
    log.append("bild wurde nicht gefunden")

# Log am ende Ausgeben
print log

Bleibt die Frage was du unter einer detaillierten Fehlermeldung verstehst.

@RayMan ich kann mir schon Einsatzgebiete vorstellen, wo man sowas brauchen kann ;-)
Stell dir mal ne Diashow vor die von selbst läuft und du willst zählen wie oft ein Bild erscheint, ohne, dass das Script abbrechen soll, wenn es mal nicht erscheint, weil die Diashow ja von selbst weiterblättert. :p

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

@ j-the-k
Wenn ich ein Script machen wollte, dass ohne FindFailed Exception laufen soll, dann würde ich wie oben grundsätzlich mit exists() arbeiten.

Hatte noch vergessen drauf hinzuweisen, dass man das Script dann von der Kommandozeile laufen lässt und die Printausgabe in eine Datei umleitet. Das ganze dann mit Sikuli-IDE-w.bat laufen lassen und man sieht gar nichts mehr.

--- Sikuli Logging
Sowas fehlt wirklich in Sikuli.

Noch eine generelle Anmerkung:
Wenn man das ganze als echten Python UnitTest aufsetzt, zumindest für die wichtigen Dinge assert verwendet und das ganze dann noch mit dem modifizierten HTMLTestRunner (Screenshot im Fehlerfall) laufen lässt, dann bekommt man ein relativ hochwertiges Protokoll (faq 1804).
Wäre für dieses Diashow Thema auch ein Ansatz.

Revision history for this message
Pascal Roth (pascalroth94) said :
#4

Also schon mal Danke für die schnellen Antworten!

Jedoch löst das mein Problem noch nicht so ganz. Ich versuche das ganze mal etwas genauer zu beschreiben: Ich habe mit Sikuli ein Programm geschrieben, das ungefähr 40 Programme öffnet und eine Test-Datei speichert und diese wieder löscht. Nun benötige ich das ganze ohne das Sikuli abbricht, sonder das es durch läuft und mir zum Schluss ausgibt, welche Programme Probleme bereitet haben. Ich habe gelesen, das sich das ganze auch in Java einbinden lässt, nur fehlen mir dazu die Kenntnisse....könnt ihr mir weiter helfen?

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

Ob Java oder Python spielt keine Rolle hierfür.

--1. Wenn die Scripts/Programme so geschrieben sind, dass Funktionen enthalten sind, die das Script abbrechen können, dann muss man diese Teile in try/except einpacken oder halt alternative Funktionen/Lösungen verwenden, die nicht abbrechen, aber trotzdem benutzt werden können, die Situationsbeschreibung zu protokollieren.

--2. da es fürs Protokollieren keine durchgehend standardisierte Schnittstelle/Funktionalität in Sikuli gibt, muss man das selbst scripten/programmieren.

Und nochmal: Wenn im Verlauf eines Workflows (Programm öffnen, Test-Datei speicheren, Test-Datei löschen, Programm schließen) ein Image nicht gefunden wird, muss man sich eh überlegen, wie in diesem Fall das Script weitergehen soll.
(wenn die Test-Datei nicht gespeichert wird, kann sie auch nicht gelöscht werden).
Ohne irgendwelche "recovery actions" macht es normalerweise wenig Sinn, das Script einfach durchlaufen zu lassen.

BTW: Für solche Dinge haben sich die Entwicklungs Cracks das Unittesting ausgedacht, das mit relativ vielen Konfigurations/Steuerungs/Protokollierungs Optionen daherkommt.

Was du da machst, sieht nach einem typischen Anwendungsfall dafür aus.

Revision history for this message
Pascal Roth (pascalroth94) said :
#6

So wie du mir das erklärst, versteh ich leider nur Bahnhof :/

Also habe ich das richtig verstanden, dass wenn ich ein Fehlerprotokoll ausgeben lassen will, muss ich dazu selbst was programmieren (beispielsweise in Java)? Das würde bedeuteten ich muss mein Sikuli-Programm in Java einbinden und dazu noch was dazu schreiben, dass mir mein Programm nicht abbricht und eine Fehlermeldung ausgibt, oder versteh ich da was komplett falsch?

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

Du hast es m.E. eigentlich richtig verstanden, aber immer noch keine Idee, wie es umgesetzt werden könnte :-(

Es ist immer schwierig, hier zu beurteilen, welchen Scripting/Programmierungsbackground jemand hat.
Ich finde die Erklärung in comment #5 eigentlich ganz verständlich.

Wenn du mir mal was typisches von Deinem Script zeigst, dann kann ich die vielleict praktisch Tipps geben (https://launchpad.net/~raimund-hocke).

Sonst habe ich hier zum Thema alles gesagt und weiß auch nicht weiter.

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

In english for the others:
This is a quick and dirty simple solution, to
- run a test as long as it makes sense
- report error situations

# switch off Sikuli's verbosity
Settings.ActionLogs = False
Settings.InfoLogs = False
Settings.DebugLogs = False

# helper function
def findClick(img, waitAfter = 0, reg = SCREEN):
    m = reg.exists(img)
    if not m:
        print img, "not found in" reg
        return False
    click(m)
    if waitAfter > 0: wait(waitAfter)
    return True

# same function using try/except
def findClick(img, waitAfter = 0, reg = SCREEN):
    try:
        click(img) # no find needed, click does it internally
    except:
        print img, "not found in" reg
        return False
    if waitAfter > 0: wait(waitAfter)
    return True

print "*** Test_Winscp_01"
# substituted: find("71L4-12.png") , click("71L4-12.png")
if findClick("71L4-12.png"):
    type("Winscp"), wait(4)
    type(Key.ENTER)
    # substituted: find("1343734713712-3.png")
    # substituted: click("1343734713712-3.png"), wait(2)
    if findClick("1343734713712-3.png", 2)
        type(Key.ENTER), wait(2)
        type(Key.DELETE)
        type(Key.ENTER)
        # substituted: find("1343733153070-12.png"), click("1343733153070-12.png"), wait(5)
        findClick("1343733153070-12.png", 5)

# same test, max 1 indent
print "*** Test_Winscp_01"
shouldContinue = True
# substituted: find("71L4-12.png") , click("71L4-12.png")
if not findClick("71L4-12.png"): shouldContinue = False
if shouldContinue:
    type("Winscp"), wait(4)
    type(Key.ENTER)
    # substituted: find("1343734713712-3.png")
    # substituted: click("1343734713712-3.png"), wait(2)
    if not findClick("1343734713712-3.png", 2): shouldContinue = False
if shouldContinue:
    type(Key.ENTER), wait(2)
    type(Key.DELETE)
    type(Key.ENTER)
    # substituted: find("1343733153070-12.png"), click("1343733153070-12.png"), wait(5)
    findClick("1343733153070-12.png", 5)

Run this from command line using:
Sikuli-IDE.bat -r myTests.sikuli >myTestsLog.txt

and it will silently run and continue the test as long as possible.
After the run you have your log messages in myTestsLog.txt

This could be done with Pythons unit test very elegantly. Using the modified HTMLTestRunner would even provide screenshots of the failure situations. Come back if interested.

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

BTW:
--- having more than one statement on a line:
the separator should be a semicolon
if you use a comma, Sikuli internally unnecessarily makes a tuple containing the results of each statement.

Revision history for this message
woermaxi (maxiwoerle) said :
#10

Hey RaiMan,

ich arbeite zusammen mit pascalroth94 an diesem Sikuli-Testingprojekt.

Den Code, den du in englischer Sprache nun als letztes hier gepostet hast, habe ich nun auf unseren Code angeglichen - Nun scheint es mir jedoch allerdings so, als wäre in Zeile 10 ein Tippfehler oder sonstiges vorhanden, da Sikuli mir bei jedem Versuch den Code ausführen zu lassen sagt, dass in Zeile 10 das "reg" unkorrekt bzw. unpassend ist:

---> print img, "not found in" reg <----

Was nun?

Danke schon mal vorab für deine Hilfe!

LG, woermaxi.

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

Uuups, easy one:

comma missing ;-)

print img, "not found in", reg

Revision history for this message
Pascal Roth (pascalroth94) said :
#12

Hey RaiMan,

wir haben den Code nun komplett angepasst, jedoch bricht das programm einfach ab und gibt folgende Fehlermeldung aus:

[error] Abgebrochen
[error] Fehlermeldung: java.lang.ArrayIndexOutOfBoundsException: 0
at org.python.objectweb.asm.Frame.a(Unknown Source)
at org.python.objectweb.asm.Frame.a(Unknown Source)
at org.python.objectweb.asm.MethodWriter.visitMaxs(Unknown Source)
at org.python.compiler.Code.visitMaxs(Code.java:151)
at org.python.compiler.ClassFile.endMethods(ClassFile.java:101)
at org.python.compiler.ClassFile.write(ClassFile.java:122)
at org.python.compiler.Module.write(Module.java:613)
at org.python.compiler.Module.compile(Module.java:669)
at org.python.compiler.Module.compile(Module.java:648)
at org.python.compiler.LegacyCompiler$LazyLegacyBundle.ostream(LegacyCompiler.java:64)
at org.python.compiler.LegacyCompiler$LazyLegacyBundle.saveCode(LegacyCompiler.java:58)
at org.python.core.CompilerFacade.compile(CompilerFacade.java:33)
at org.python.core.Py.compile_flags(Py.java:1703)
at org.python.core.Py.compile_flags(Py.java:1708)
at org.python.core.Py.compile_flags(Py.j

ava:1718)
at org.python.core.__builtin__.execfile_flags(__builtin__.java:514)
at org.python.util.PythonInterpreter.execfile(PythonInterpreter.java:225)
at org.sikuli.script.ScriptRunner.runPython(ScriptRunner.java:70)
at org.sikuli.ide.SikuliIDE$ButtonRun.runPython(SikuliIDE.java:1572)
at org.sikuli.ide.SikuliIDE$ButtonRun$1.run(SikuliIDE.java:1677)

java.lang.ArrayIndexOutOfBoundsException: java.lang.ArrayIndexOutOfBoundsException: 0

Könntest du uns eventuell weiter helfen?

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

Das sieht aber wirklich hässlich aus.

Da ist irgendein komisches problem in dem ausgeführten script.
Lässt sich die Stelle irgend wie eingrenzen, wo es abbricht?

Wenn ihr nicht weiter kommt:
alles zusammen zippen und mir schicken (https://launchpad.net/~raimund-hocke).

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

Have seen the script.

The following line has crashed the Jython interpreter, instead of showing a syntax error:
for i("1343378514721-1.png") in range(1, 4, 1):

Can you help with this problem?

Provide an answer of your own, or ask Pascal Roth for more information if necessary.

To post a message you must log in.