Logo des digitalen Schulbuchs inf-schule.de. Schriftzug in Zustandsübergangsdiagramm eines endlichen Automaten.

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.

Formel: BMI = Gewicht (in kg) / (Größe (in cm) x Größe (in cm)); Tabelle zur Bewertung (siehe Wikipedia)

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.

<Black-Box-Diagramm><Funktionsname>bmiBewertung</Funktionsname><Übergaben><Übergabe><Wert>'w'</Wert><Variable>geschlecht</Variable></Übergabe><Übergabe><Wert>165</Wert><Variable>groesse</Variable></Übergabe><Übergabe><Wert>60</Wert><Variable>gewicht</Variable></Übergabe></Übergaben><Rückgabe><Text>return</Text><Wert>'Normalgewicht'</Wert></Rückgabe></Black-Box-Diagramm>

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.

X

Fehler melden

X

Suche