Sript zum Ausführen von Unittest

Du hast eine Idee für ein Projekt?
Antworten
merlinerick
User
Beiträge: 5
Registriert: Dienstag 28. Juli 2009, 17:50

Hallo!
Ich brauche mal Hilfe. Ich soll ein Python-Skrpt schreiben, das CppUnittest ausführt.
Dafür habe ich eine XML-Konfigurationsdatei vorliegen.

Wie kann ich vorgehen?

Die XML-Konfigurationsdatei sieht folgendermassen aus:

Code: Alles auswählen

<?xml version="1.0" encoding="UTF-8"?>
<!-- Konfigurationsfile fuer alle Tests-->
<run>
    <!-- Globale Einstellungen -->   
    <global>
        <!-- Pfad zur Installation. Dies muss eine Developer-Installation inklusive Sourcetree sein! -->
        <basepath path="..\.."/>

        <!-- Pfad, in dem die Protokoll- und Archivdateien abgelegt werden sollen -->
        <output path="..\Logs"/>

        <!-- Wer soll ueber Fehler beim Kompileren informiert werden? -->
        <notify>
            <email name="xxx@hfg.de"/>
        </notify>

        <!-- Welches skript muss für die suite ausgeführt werden? -->
        <suiterunner type="CppUnit" script="./suiterunners/cppunit_runner.py"/>
    </global>

    <!-- Angabe aller durchzufuehrenden Tests -->
    <tests>
        <suite type="CppUnit">
            <!-- Allgemeine Konfiguration fuer den Buildvorgang und Testlauf-->
            <configuration>
                <!-- Pfad zu den Testfaellen. -->
                <testcasepath path="..\..\Source\Projekte"/>
                <!-- Tests nur in der Debug oder Releaseversion oder in beidem ausfuehren? -->
                <runtests>
                    <debug/>
                    <release/>
                </runtests>
                <!-- Optional: Wer soll über alle Tests der Suite informiert werden (damit man die
                  entsprechenden Personen nicht bei allen tests angeben muss -->
                <notify>
                    <email name="xxx@hkg.de" type="always"/>
                </notify>
            </configuration>
            <!-- Kann entfallen, wenn die Empfänger über alle Suitetests informiert werden sollen (s.o.)
            <test name="Base" path="Base\BaseTest\BaseMathTest.sln">
                <notify>
                    <email name="xxx@hkg.de" type="always"/>
                </notify>
            </test>
            -->
            <test name="Base" path="Base\BaseTest\BaseTest.sln"/>
            <test name="Util" path="Util\UtilTest\UtilTest.sln"/>
        </suite>
    </tests>
</run>
Hat sich jemand schon mit ähnliche Aufgabe beschäftigt??

danke im voraus
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Du parst die XML Datei (z.B. mit xml.dom.minidom) und führst dann die cpp TestSuite mit subprocess aus. Was ist daran jetzt unverständlich? Was genau ist deine Frage?
Bottle: Micro Web Framework + Development Blog
merlinerick
User
Beiträge: 5
Registriert: Dienstag 28. Juli 2009, 17:50

Hallo Defnull,
erstmal vielen Dank für deine Antwort, ich bin damit ein Stuck weiter gekommen.
Für das Parsen habe ich folgendenmasse gemacht und hänge an der Stelle. so sieht mein cppunit_runners.py skript aus:

Code: Alles auswählen

#  cppunit_runners.py
from xml.dom import minidom
buildReceivers = []  # Liste der Leute die den Mail enpfangen
configFile = minidom.parse('config.xml')
#print configFile.toxml()

# Read global data                                                                                      
glob = configFile.getElementsByTagName(u"run")[0].getElementsByTagName(u"global")[0]
#print glob.toxml()

BasePath = glob.getElementsByTagName(u"basepath")[0].getAttribute(u"path")
#print BasePath

repository = glob.getElementsByTagName(u"output")[0].getAttribute(u"path")
#print repository

for receivers in glob.getElementsByTagName(u"notify")[0].getElementsByTagName(u"email"):                
    buildReceivers.append( receivers.getAttribute(u"name") )
    #print receivers.toxml()
Kannst du mir an der Stelle weiterhelfen?

Du hast auch vom Subprocess gesprochen, wie soll dieser Process aussehen? Ein Beispiel wäre mir auch sehr hilfreich

Danke im voraus.
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

@Defnull: Warum die Empfehlung auf Minidom, wo doch ElementTree und lxml wesentlich angenehmere API's bieten?!
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

merlinerick hat geschrieben: Du hast auch vom Subprocess gesprochen, wie soll dieser Process aussehen? Ein Beispiel wäre mir auch sehr hilfreich
Schau mal in der Dokumentation unter http://docs.python.org/library/subprocess.html.

Gruß,
Matthias
merlinerick
User
Beiträge: 5
Registriert: Dienstag 28. Juli 2009, 17:50

Defnull hat geschrieben:Du parst die XML Datei (z.B. mit xml.dom.minidom) und führst dann die cpp TestSuite mit subprocess aus. Was ist daran jetzt unverständlich? Was genau ist deine Frage?
Hallo!
Ich habe es geschaft, die XML-Datei wie folg zu parsen zu parsen:

Code: Alles auswählen

#  cppunit_runners.py

def has_child_node(nodeList, name ):
##    nodeList = nodeList
##    name = name
    """Returns true if the xml node list nodeList contains a node of the given name."""
    for node in nodeList:
        if node.nodeName == name:
            return True
    return False
# def has_child_node()


from xml.dom import minidom

buildReceivers = []  # Liste der Leute die den Mail enpfangen
runTests = []
solutionDirs = []    # Source directories to watch for changes
projectName = []


configFile = minidom.parse('config.xml')
#print configFile.toxml()

# Read global data                                                                                      
glob = configFile.getElementsByTagName(u"run")[0].getElementsByTagName(u"global")[0]
#print glob.toxml()
hicadBasePath = glob.getElementsByTagName(u"hicadbasepath")[0].getAttribute(u"path")
#print hicadBasePath
repository = glob.getElementsByTagName(u"output")[0].getAttribute(u"path")
#print repository         
                                                                                                        
for receivers in glob.getElementsByTagName(u"notify")[0].getElementsByTagName(u"email"):                
    buildReceivers.append( receivers.getAttribute(u"name") )
    #print receivers.toxml()
                                                                                                
### Read configuration data
Test = configFile.getElementsByTagName(u"run")[0].getElementsByTagName(u"tests")[0]
#print Test.toxml()
testSuite = Test.getElementsByTagName(u"suite")[0]
#print TestSuite.toxml()
suiteType = Test.getElementsByTagName(u"suite")[0].getAttribute(u"type")
#print suiteType
conf = testSuite.getElementsByTagName(u"configuration")[0]
#print conf.toxml()
testSuiteRunner = conf.getElementsByTagName(u"suiterunner")[0].getAttribute(u"script")
#print testSuiteRunner
testCasePath = conf.getElementsByTagName(u"testcasepath")[0].getAttribute(u"path")
#print testCasePath

if ( has_child_node( conf.getElementsByTagName(u"runtests")[0].childNodes, u"debug") ):        
    runTests.append(u"debug")
if ( has_child_node( conf.getElementsByTagName(u"runtests")[0].childNodes, u"release") ):      
    runTests.append(u"release")
#print runTests

for receivers in conf.getElementsByTagName(u"notify")[0].getElementsByTagName(u"email"):                
    buildReceivers.append( receivers.getAttribute(u"name") )
    #print receivers.toxml()

for Name in testSuite.getElementsByTagName(u"test"):               
    projectName.append( Name.getAttribute(u"name") )
print projectName

for Solution in testSuite.getElementsByTagName(u"test"):
    solutionDirs.append( Solution.getAttribute(u"path") )
print solutionDirs                                                                               
Das mit dem Subprocess habe ich nach mehrmal Lesen nicht verstanden, zumindest wie ich anfangen kann. Es schein mir sehr schwer zu sein.
Kannst du mir bitte ein Beispiecode für Subprocess basteln? Das wird mir sehr hilfreich, die XML-Datei erklärt schon alles was ich zu mache habe (Ausführung der CppUnit- bzw. NunitTest aus der Python-Datei). Alleine wird es mir sehr schwer ein Subprocess zu schreiben, das ich Neuling in Python bin. Ich laufe im moment gegen die Zeit.

Ich danke im Voraus

Merlinerick[/code]
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Wow ... dass du dir minidom freiwillig antust, wenn dir schon ElementTree empfohlen wird ... (und Defnull einmal in die Ecke !)

In der Library Reference sind jede Menge Beispiele: http://docs.python.org/library/subprocess.html
merlinerick
User
Beiträge: 5
Registriert: Dienstag 28. Juli 2009, 17:50

cofi hat geschrieben:Wow ... dass du dir minidom freiwillig antust, wenn dir schon ElementTree empfohlen wird ... (und Defnull einmal in die Ecke !)

In der Library Reference sind jede Menge Beispiele: http://docs.python.org/library/subprocess.html
Hallo, Cofi!
Als newby in Python, habe ich es nur probiert und bin schon froh dass es geklappt hat. Ich werde später mich mit dem "elementTree" beschäftigen.

Ich habe jetz ein anderes problem, nämlich diese code in den Execute code zu benutzen. Hier das Execute code:

Code: Alles auswählen

# -*- coding: latin1 -*-

"""Script zum Durchführen der Unit-Tests in den Sourcen.
"""

import os


################################################################################
# BuildError
class BuildError(Exception):
    """Diese Exception wird geworfen, wenn ein Fehler bei der Erstellung aufgetreten ist.
    """

################################################################################
# shell_command
def shell_command(cmd):
    """Startet einen Prozess und gibt den Output des Prozesses als
       Stringliste zurück.
    """
    cmd2 = cmd + ' 2>&1'
    p = os.popen(cmd2)
    lines = []
    line = p.readline()
    while line:
        lines.append(line)
        line = p.readline()
    try:
        status = p.close()
    except KeyboardInterrupt, e:
        raise
    except:
        raise BuildError(''.join(lines))
    if status:
        raise BuildError(''.join(lines))
    print line
    return lines

################################################################################
# execute_config
def execute_testscripts(path, logpath, config):
    """Sucht in dem gegebenen Verzeichnis nach Scripten, die auf .test.pl, .test.py oder .test.bat enden
       und führt diese aus. Wird ein Status verschieden von 0 zurückegegeben, dann wird die Ausgabe
       des Scriptes als Fehlermeldung eingefügt.
       Zurückgegeben wird eine Table, pro Testscript ein Eintrag mit den Fehlermeldungen.
    """
    messages = {};
    for root, dirs, files in os.walk(path):
        if root.find('.svn') < 0: # nicht die Dateien aus den .svn-Verzeichnissen
            for file in files:
                cmd = None
                if file.lower().endswith('.test.pl'):
                    cmd = 'perl.exe '
                elif file.lower().endswith('.test.py'):
                    cmd = 'python.exe '
                elif file.lower().endswith('.test.bat'):
                    cmd = 'cmd /C '
                if cmd:
                    cmd += root + '\\' + file
                    print '%-30s ' % file,
                    try:
                        if 'Debug' in dirs:
                            shell_command('rmdir /S /Q ' + root + '\\Debug')   # Lösche alle Dateien des letzten Tests
                        shell_command(cmd + ' %s' % config)
                        print 'ok'
                        messages[file] = ''
                    except BuildError, e:
                        print 'Fehler'
                        messages[file] = str(e)
    return messages

################################################################################
# main
def main():
    """Das "Hauptprogramm".
    """
    import sys

    messages = execute_testscripts(rootpath, logpath, 'Debug')   # Debug usw. muss ins Config-File

    has_errors = False
    for file in sorted(messages.keys()):
        if messages[file]:
            has_errors = True

            log.writeLog( "Loading configuration file: config.xml", "Configuration" )
 
    return has_errors
    
################################################################################
if __name__ == '__main__':
    main()

Mit dem code wie die Unittest durchgeführt, aber nicht mit meine ConfigDatei.
Ich möchte die geparste ConfiDatei hier benutzen. Sowie ich den Code gelesen habe, habe ich gedacht, dass ich nur das main-Programm benutzen soll. Ist es richtig?
Wie soll ich meine Datei hier anpassen? hat jemand schon damit zu tun gehabt?
Ich brauche Eure Hilfe! Eim Beispiel wäre mir sehr hilfreich

Danke im voraus

Merlinerick
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

- Statt os.popen besser das subprocess-Modul verwenden!

- PEP8 besser einhalten (speziell die Zeilenlänge ist ätzend!)

- es gibt in os.path die Funktion join, mit der man Dateipfade zusammensetzen sollte.

- in shutils gibt es Funktionen (rmtree z.B.) zum Löschen von Datein und Verzeichnissen. Bordmittel sind da immer externen Shell-Kommandos vorzuziehen.

Sicher, dass das Script so funktioniert? log taucht hier imho undefiniert auf, ohne, dass es vorher intitialisiert worden ist.

Last but bot least: Bitte nutze doch die Code-Tags in diesem Board korrekt. [ code=py ] z.B. für Python-Quellcode. So kann man dann Deine Scripte besser lesen.

Zur eigentlichen Frage: Kapiere ich nicht? Von wem stammt welcher Code? Wieso wird hier etwas nicht berücksichtigt? Was wird nicht berücksichtigt?
Antworten