Kapitel 25
Testen und Tuning
712
Die Klasse Sky wird um die öffentliche Methode getStar() erweitert. Sie besitzt als Parame-
ter ein Tupel
(x, y), das Koordinaten auf dem Foto repräsentiert. Der Aufruf sky.
getStar(position)
liefert einen Stern, der sich an der Position position = (x, y) befin-
det, sofern ein solcher Stern existiert. Anderenfalls wird das leere Objekt
None zurückge-
geben.
Die Klasse
Starwatch muss um folgende Elemente erweitert werden:
Ein neues Label mit dem Text "Helligkeit:"
Ein neues Label, das den Helligkeitswert des ausgewählten Sterns zeigt. In Abbildung
25.6 ist das die Zahl
29.
Der Canvas mit der Fotografie muss an einen Eventhandler (eine neue Methode) gebun-
den werden. Der Eventhandler verarbeitet einen Mausklick-Event auf folgende Weise:
Er ermittelt aus dem Event-Objekt die Koordinaten (x,y) der angeklickten Position
auf dem Canvas.
Dann sucht er mit der Methode getStar() des Sky-Objektes den zugehörigen Stern
und ermittelt dessen Helligkeit mit der
Star-Methode getBrightness().
Zum Schluss konfiguriert er das Label, das den Helligkeitswert zeigt, neu.
Abb. 25.7: UML-Diagramm für das erweiterte Himmelsmodell. Neue Methoden sind kursiv.
b) Schreiben Sie an das Ende des Moduls mit den Klassen Star und Sky eine Testroutine,
die aufgerufen wird, wenn die Moduldatei direkt ausgeführt wird.
Mithilfe des Profilers und der Testroutine soll die mittlere Laufzeit der neuen
Sky-Methode
getStar() bei einer typischen Himmelsfotografie ermittelt werden. Um einigermaßen prä-
zise Ergebnisse zu erhalten, soll die Methode
getStar() 1000 Mal mit zufällig gewählten
Koordinaten aufgerufen werden.
25.8 Lösungen
Lösung 1
Skript:
def sucheWoerter (text, n):
""" Liefert Menge aller Wörter mit n Buchstaben
Sky
threshold
__brightness()
__createStars()
__integrate()
__search()
count()
getStar()
Starwatch
Star
__dots
integrate()
contains()
getBrightness()
11
1*
sky
__stars
713
25.8
Lösungen
Erläuterung:
#1: Da es für ein und dieselbe Menge unterschiedliche Repräsentationen gibt (die Reihen-
folge der Elemente ist nicht festgelegt), kann die korrekte Arbeitsweise nur mithilfe eines
Vergleichs überprüft werden.
#2: Die Satzzeichen werden entfernt.
#3: Erzeugt eine Liste mit Wörtern der Länge n.
Lösung 2
Skript:
>>> text = "Habe nun, ach! Philosophie,\
Juristerei und Medizin und leider auch Theologie\
durchaus studiert, mit heißem Bemühn."
>>> s = sucheWoerter (text, 4)
>>> s == {"Habe", "auch"} #1
True
"""
textBereinigt = "".join(
[c for c in text if c not in "!?.,;:-"]) #2
wortmenge = set(textBereinigt.split())
liste = [wort for wort in wortmenge
if l e n(wo r t) = = n] #3
return set(liste)
if __name__ == "__main__":
import doctest
doctest.testmod(verbose=True)
#sortTest.py
import unittest, random
class TestSort (unittest.TestCase):
def setUp(self):
self.list = [random.randint(0, 100)
fo r i in r a nge ( 2 0)] #1
def testlength(self):
""" Ist die sortierte Liste genauso lang
wie die unsortierte Liste?"""
len_unsorted = len(self.list)
self.list.sort()
Kapitel 25
Testen und Tuning
714
Ausgabe:
Erläuterung:
#1: Hier wird eine Liste mit 20 Zufallszahlen zwischen 0 und 100 erzeugt.
Lösung 3
a) und b) Die folgenden Listings zeigen nur die Erweiterungen (fett gedruckt) der ursprüng-
lichen Skripte.
len_sorted = len (self.list)
self.assert_(len_sorted == len_unsorted)
def testbegin(self):
"""Ist am Anfang der sortierten Liste
das kleinste Element?"""
self.list.sort()
self.assert_(self.list[0] == min (self.list))
def testorder (self):
"""Ist der linke Nachbar eines Listenelementes
nicht größer?"""
self.list.sort()
for i in range(1,len(self.list)):
self.failIf(self.list[i-1]> self.list[i])
suite = unittest.TestSuite()
TestSort("testlength")
suite.addTest(TestSort("testlength"))
suite.addTest(TestSort("testbegin"))
suite.addTest(TestSort("testorder"))
testrunner = unittest.TextTestRunner(verbosity=2)
testrunner.run(suite)
Ist die sortierte Liste genauso lang ... ok
Ist am Anfang der sortierten Liste ... ok
Ist der linke Nachbar eines Listenelementes ... ok
--------------------------------------------------------
Ran 3 tests in 0.078s
OK
715
25.8
Lösungen
Skript 1:
# starwatch_b.pyw
...
class Starwatch(object):
def __init__ (self):
self.__createWidgets()
self.r = 5 # Radius des Markierungskreises
self.markID = None # ID des Kreises auf dem Canvas
self.sky = Sky(self.image)
. . .
def __createWidgets(self):
. . .
self.canvas = Canvas(master=self.window,
width="9c", height="5c")
self.imageID = self.canvas.create_image(0, 0,
image = self.image, anchor=NW)
self.canvas.bind(sequence="<Button-1>",
func=self.markStar) #1
...
Label(master = self.window,
text="Helligkeit:").pack(side=LEFT)
self.labelBrightness=Label(master=self.window,
width=5, fg="blue")
def __layout(self):
. . .
self.labelBrightness.pack(side=LEFT)
...
def markStar(self, event): #2
position = (event.x, event.y) #3
x0, y0 = event.x - self.r, event.y - self.r #4
x1, y1 = event.x + self.r, event.y + self.r
self.canvas.delete(self.markID) #5
self.markID = self.canvas.create_oval(x0, y0, x1, y1,
outline="yellow")
star = self.sky.getStar(position) #6
if star:
brightness=str(star.getBrightness()) #7
self.labelBrightness.config(text=brightness) #8
Kapitel 25
Testen und Tuning
716
Erläuterung 1:
#1: Der Canvas mit dem Sternenfoto wird an den Eventhandler self.markStar gebunden.
#2: Definition des Eventhandlers. Bei jedem Mausklick auf den Canvas wird diese Methode
gestartet. Sie verarbeitet das als Argument übergebene Event-Objekt
event.
#3: Aktuelle Mausposition auf dem Canvas.
#4: Eckpunkte der Bounding Box des gelben Markierungskreises.
#5: Der alte Markierungskreis auf dem Canvas wird gelöscht und anschließend ein neuer
Kreis gezeichnet.
#6: Der angeklickte Stern wird ermittelt.
#7: Sofern beim Anklicken tatsächlich ein Stern getroffen worden ist, wird dessen Helligkeit
ermittelt und der Zahlenwert in einen String umgewandelt.
#8: Das Label, das die Helligkeit anzeigt, wird neu konfiguriert.
Skript 2:
else:
self.labelBrightness.config(text="---")
sw = Starwatch()
# stars_b.py
class Star(object):
""" modelliert einen Stern"""
...
def contains (self, dot): #1
return dot in self.__dots
def getBrightness(self): #2
return len(self.__dots)
class Sky:
""" Modelliert einen Sternenhimmel"""
...
def getStar(self, dot): #3
for star in self.__stars:
if star.contains(dot):
return star

Get Python 3 - Lernen und professionell anwenden now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.