Beispiel - Body-Mass-Index
Bewertung des Gewichts
Mit dem Body-Mass-Index versucht man, das Gewicht einer Person in Abhängigkeit von seiner Größe zu bewerten.
Beachte, dass die Angaben in der Tabelle nur grobe Richtwerte liefern. Sie berücksichtigen z.B. nicht das Alter der Person oder den Körperbau.
Aufgabe 1
Bestimme deinen BMI-Wert mit der angegebenen Formel und ermittle mit der Tabelle, ob du Normalgewicht hast.
Ein BMI-Rechner
Ziel ist es, einen BMI-Rechner zu entwickeln, der aus den Daten einer Person eine Bewertung vornimmt, ob die Person Unter-, Normal oder Übergewicht hat.
Hier ein erster Vorschlag für eine Funktionsdefinition:
def bmiBewertung(geschlecht, groesse, gewicht):
bmi = gewicht / (groesse*groesse)
if geschlecht == 'w':
if bmi < 19:
bewertung = 'Untergewicht'
elif bmi > 24:
bewertung = 'Übergewicht'
else:
bewertung = 'Normalgewicht'
else:
if bmi < 20:
bewertung = 'Untergewicht'
elif bmi > 25:
bewertung = 'Übergewicht'
else:
bewertung = 'Normalgewicht'
return bewertung
Aufgabe 2
(a) Überprüfe, ob die Funktionsdefinition so in Ordnung ist.
(b) Überprüfe, wie sich die Funktion bei folgenden Aufrufen verhält. Ist das jeweils sinnvoll?
>>> bmiBewertung('w', 1.65, 60)
>>> bmiBewertung('m', 1.80, 90)
>>> bmiBewertung('m', 1.80, 0)
>>> bmiBewertung('m', 180, 70)
>>> bmiBewertung('W', 1.65, 60)
>>> bmiBewertung('O+', 1.65, 60)
Verhalten beschreiben
Mit dem Black-Box-Diagramm wird das Verhalten der Funktion bmiBewertung
nur grob beschrieben.
Mit dem Diagramm wird durchaus verdeutlicht, welche Daten an die Funktion übergeben werden sollen.
Anhand eines Beispiels wird auch exemplarisch beschrieben, welche Rückgabe bei den übergebenen Daten erwartet wird.
Ein Beispiel reicht jedoch oft nicht aus, um das Verhalten einer Funktion adäquat zu erfassen. Im vorliegenden
Fall ist z.B. nicht klar, wie die Funktion "reagiert", wenn man eine unsinnige Länge wie 20 oder auch 0
übergibt. Auch nicht klar ist, wie das Geschlecht als Datum beschrieben werden muss. Kann man auch 'W'
oder gar 'O+' als Geschlecht übergeben?
Das Verhalten einer Funktion lässt sich oft mit Hilfe von Testfällen beschreiben. Die Testfälle sollten
dabei so gewählt sein, dass alle typischen und auch alle kritischen Fälle berücksichtigt werden.
Für die Funktion bmiBewertung
könnte eine Sammlung von Testfällen z.B. so aussehen.
>>> bmiBewertung('w', 1.65, 60)
'Normalgewicht'
>>> bmiBewertung('m', 1.80, 90)
'Übergewicht'
>>> bmiBewertung('m', 1.80, 0)
'?'
>>> bmiBewertung('m', 180, 70)
'?'
>>> bmiBewertung('W', 1.65, 60)
'Normalgewicht'
>>> bmiBewertung('O+', 1.65, 60)
'?'
Klar, dass der genaue Umfang der zulässigen Übergabedaten so noch nicht exakt erfasst ist. Zumindest wird aber das Problem unzulässiger Übergabedaten thematisiert.
Verhalten überprüfen
Beachte, dass die gezeigten Testfälle das gewünschte Verhalten der Funktion bmiBewertung
beschreiben.
Fraglich ist, ob bei einer vorliegenden Funktionsdefinition die Funktion bmiBewertung
auch tatsächlich
dieses Verhalten aufweist. Nimmt man die oben gezeigte Funktionsdefinition, so weichen gewünschtes und
tatsächliches Verhalten in etlichen Fällen voneinander ab.
Wenn man eine Funktionsdefinition entwickelt hat, muss nachträglich überprüft werden, ob gewünschtes und tatsächliches Verhalten zusammenpassen. Das kann man selbst im Python-Ausführfenster tun, oder es von Python automatisiert durchführen lassen. Wie die automatisierte Überprüfung erfolgt, wird hier jetzt Schritt für Schritt gezeigt.
Wir betrachten die oben gezeigte Funktionsdefinition und fügen die zu überprüfenden Testfälle als lange
Zeichenkette in die Funktionsdefinition (direkt unter den Funktionskopf) ein.
Zur Überprüfung benutzen wir die Anweisung testmod
aus der Bibliothek doctest
:
def bmiBewertung(geschlecht, groesse, gewicht):
"""
>>> bmiBewertung('w', 1.65, 60)
'Normalgewicht'
>>> bmiBewertung('m', 1.80, 90)
'Übergewicht'
>>> bmiBewertung('m', 1.80, 0)
'?'
>>> bmiBewertung('m', 180, 70)
'?'
>>> bmiBewertung('W', 1.65, 60)
'Normalgewicht'
>>> bmiBewertung('O+', 1.65, 60)
'?'
"""
bmi = gewicht / (groesse*groesse)
if geschlecht == 'w':
if bmi < 19:
bewertung = 'Untergewicht'
elif bmi > 24:
bewertung = 'Übergewicht'
else:
bewertung = 'Normalgewicht'
else:
if bmi < 20:
bewertung = 'Untergewicht'
elif bmi > 25:
bewertung = 'Übergewicht'
else:
bewertung = 'Normalgewicht'
return bewertung
# Überprüfung der Testfälle
from doctest import testmod
testmod(verbose=True)
Wenn man diese Funktionsdefinition mit [Run][Run Module] ausführt, erhält man genaue Rückmeldungen:
>>>
Trying:
bmiBewertung('w', 1.65, 60)
Expecting:
'Normalgewicht'
ok
Trying:
bmiBewertung('m', 1.80, 90)
Expecting:
'Übergewicht'
ok
Trying:
bmiBewertung('m', 1.80, 0)
Expecting:
'?'
**********************************************************************
File ".../bmiBewertung1.py", line 8, in __main__.bmiBewertung
Failed example:
bmiBewertung('m', 1.80, 0)
Expected:
'?'
Got:
'Untergewicht'
Trying:
bmiBewertung('m', 180, 70)
Expecting:
'?'
**********************************************************************
File ".../bmiBewertung1.py", line 10, in __main__.bmiBewertung
Failed example:
bmiBewertung('m', 180, 70)
Expected:
'?'
Got:
'Untergewicht'
Trying:
bmiBewertung('W', 1.65, 60)
Expecting:
'Normalgewicht'
ok
Trying:
bmiBewertung('O+', 1.65, 60)
Expecting:
'?'
**********************************************************************
File ".../bmiBewertung1.py", line 14, in __main__.bmiBewertung
Failed example:
bmiBewertung('O+', 1.65, 60)
Expected:
'?'
Got:
'Normalgewicht'
1 items had no tests:
__main__
**********************************************************************
1 items had failures:
3 of 6 in __main__.bmiBewertung
6 tests in 2 items.
3 passed and 3 failed.
***Test Failed*** 3 failures.
Aufgabe 3
(a) Wie ist diese Rückmeldung zu verstehen?
(b) Ändere die Funktionsdefinition der Funktion bmiBewertung
so ab, dass alle Testfälle
mit einem ok
quittiert werden.
(c) Oft benutzt man die Anweisung testmod
aus der Bibliothek doctest
auch
folgendermaßen.
def bmiBewertung(geschlecht, groesse, gewicht):
"""
>>> bmiBewertung('w', 1.65, 60)
'Normalgewicht'
>>> bmiBewertung('m', 1.80, 90)
'Übergewicht'
>>> bmiBewertung('m', 1.80, 0)
'?'
>>> bmiBewertung('m', 180, 70)
'?'
>>> bmiBewertung('W', 1.65, 60)
'Normalgewicht'
>>> bmiBewertung('O+', 1.65, 60)
'?'
"""
...
# Überprüfung der Testfälle
if __name__ == "__main__":
from doctest import testmod
testmod()
Hier wird die Anweisung testmod()
nur dann ausgeführt, wenn der Quelltext direkt (als Hauptprogramm)
ausgeführt wird. Es gibt auch keine Rückmeldung, wenn kein Fehler gefunden wurde. Probiere das selbst aus.