Unittest assertRaises - Was mache ich falsch?

Code-Stücke können hier veröffentlicht werden.
Antworten
TogehterAlone
User
Beiträge: 2
Registriert: Freitag 15. April 2022, 17:59

Hallo zusammen,

ich bin gerade dabei meinen Code mit Unittest auszugestalten und habe angefangen auch konkrete Exceptions einzubauen. Dabei habe ich das Problem das meine Exception vom Unittest nicht erkannt wird. Folgender Aufbau liegt vor. Ich habe "unnötige" Stellen einfach mit Sternen versehen, da es nur um die Stuktur geht.

"Oberklasse" welche ich testen will und welche die oberste Schicht bildet:
Modul 1:

Code: Alles auswählen

    def vlwKurseUmrechnen(self, zielWaehrung:str = None):
        try: 
            if *****:                 
                self._vlwKurse.waehrungUmrechnen(*)            
        except Exception as Ex:
            raise Ex
Diese ruft wieder eine andere Klasse auf, bei dem ich auch die Prüfungen eingebaut habe:
Modul 2:

Code: Alles auswählen

    def waehrungUmrechnen(*****:):
        try: 
            if (zielWaehrung != self._kursWaehrung): 
                
                letztesWechselkursDatum = *****
                kleinstesWechselkursDatum = *****
                letztesDatumInBasisTabelle = *****
                erstesDatumInBasisTabelle = *****
                
                Eingabepruefung().pruefeWertGroesserGleich(pruefGroesse = erstesDatumInBasisTabelle, pruefBezeichnung = "Kleinstes Datum der Kurstabelle", grenzwert = kleinstesWechselkursDatum)
                Eingabepruefung().pruefeWertGroesserGleich(pruefGroesse = letztesWechselkursDatum, pruefBezeichnung = "Groesstes Datum der Wechselkurstabelle", grenzwert = kleinstesWechselkursDatum)
                
                relevantenWechselkurse = *****
                zwischenErgebnisTabelle = *****
                self._kursVerlauf = zwischenErgebnisTabelle

                self._kursWaehrung = zielWaehrung
                self._wechselkursDaten= None
                
            else:      
                return self
        
        except Exception as ex: 
                    raise ex   
Ausgelöst werden die Exceptions in der Klasse "Eingabepruefung()" weil ich eine zentrale Stelle für die Prüfungen haben wollte und so auch den Code lesbarer machen wollte.

Modul 3:

Code: Alles auswählen

    def pruefeWertGroesserGleich(self, pruefGroesse, pruefBezeichnung, grenzwert):        
        if (pruefGroesse >= grenzwert) == False: 
            raise fehlermeldungen.fehlerPruefwertZuKlein(f"Der Wert {pruefBezeichnung} muss größer oder gleich {grenzwert} sein. ({pruefBezeichnung} = {pruefGroesse})")
        else: 
            return self
"fehlerPruefwertZuKlein" ist einfach nur eine Klasse welche von Exceptions erbt. Ich erhalte folgende Fehlermeldung wenn ich den Fehler produziere ohne Unittest:

Code: Alles auswählen

conda activate base
    raise Ex
  File "c:/Users/alexa/Desktop/myProjects/fondsmanager/modAnlageklassen.py", line 177, in vlwKurseUmrechnen
    self._vlwKurse.waehrungUmrechnen(zielWaehrung= zielWaehrung, wechselkursDaten=self._wechselkursDaten)
  File "c:\Users\alexa\Desktop\myProjects\fondsmanager\modTypes.py", line 55, in waehrungUmrechnen
    raise ex
  File "c:\Users\alexa\Desktop\myProjects\fondsmanager\modTypes.py", line 40, in waehrungUmrechnen
    Eingabepruefung().pruefeWertGroesserGleich(pruefGroesse = erstesDatumInBasisTabelle, pruefBezeichnung = "Kleinstes Datum der Kurstabelle", grenzwert = kleinstesWechselkursDatum)
  File "c:\Users\alexa\Desktop\myProjects\fondsmanager\modPlausibilisierungen.py", line 10, in pruefeWertGroesserGleich
    raise fehlermeldungen.fehlerPruefwertZuKlein(f"Der Wert {pruefBezeichnung} muss größer oder gleich {grenzwert} sein. ({pruefBezeichnung} = {pruefGroesse})")
modExceptions.fehlerPruefwertZuKlein: Der Wert Kleinstes Datum der Kurstabelle muss größer oder gleich 20000102 sein. (Kleinstes Datum der Kurstabelle = 20000101) 

Wie verbaue ich das ganze dann im Unittest, damit er diesen Fehler korrekt findet?

Code: Alles auswählen

        def test_vlwKurseUmrechnen_fehlende_Wechselkurse(self):
        verFabrik = vermoegenswertFactory()
        testObjekt = verFabrik.generateVermoegenswert(4)  
        self.assertRaises(fehlerPruefwertZuKlein,testObjekt.vlwKurseUmrechnen, "EUR")     
Ergebnis: AssertionError: fehlerPruefwertZuKlein not raised by vlwKurseUmrechnen


Danke sehr, ich weiß nicht mehr weiter.

Danke!
TogetherAlone
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Module erkennt man daran, dass sie importiert werden; da braucht es kein mod-Präfix.
Module, Variablennamen und Funktionen schreibt man komplett klein_mit_unterstrich. Benutze keine kryptischen Abkürzungen; was soll ein vlw sein? Die ganzen try-Blöcke, wo im except nur ein raise steht sind überflüssig.
Eine Typannotation zielWaehrung:str = None ist so offensichtlich falsch.
Es wird eine Instanz der Klasse Eingabepruefung erzeugt, nur um eine Methode pruefeWertGroesserGleich aufzurufen, die self gar nicht benutzt. Ich vermute die ganze Klasse ist unnötig und die Methode eigentlich eine einfache Funktion.
Einen Vergleich mit False zu vergleichen ist ein kryptisch geschriebenes not. Und hier einfach durch einen <-Vergleich zu ersetzen.
Klassen (wie Exceptions) schreibt man mit großem Anfangsbuchstaben FehlerPruefwertZuKlein. Welchen Nutzen hat die Exception gegenüber dem üblichen ValueError?
Warum wird in waehrungUmrechnen mal None implizit und mal self explizit zurückgegeben? Das darf nicht sein. self als Rückgabewert ist selten sinnvoll, weil der Aufrufer ja das Objekt schon kennt. In Deinem Fall wird es auch gar nicht benutzt.
unmittelbar benutzt man heutzutage nicht mehr, weil zu kompliziert (zu viele Klassen, zu javaartig, zu wenig pythonisch). Statt dessen wird gerne pytest verwendet.
Bist Du sicher, dass die Exception geworfen wird?
TogehterAlone
User
Beiträge: 2
Registriert: Freitag 15. April 2022, 17:59

Danke für deine Rückmeldung. Ich habe extra mit diesem Projekt begonnen um mir die Grundlagen zu erarbeiten. Aber ja ich bin mir dennoch sicher, dass die Exception geworfen wird. Vielleicht komme ich mit pytest weiter.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Um Dein Problem nachstellen zu können, bräuchte man ein vollständig lauffähiges Beispiel.

Code: Alles auswählen

import pytest
from datetime import date as Date

class PruefwertZuKlein(Exception):
    pass

def pruefe_wert_groesser_gleich(wert, grenzwert, bezeichnung):
    if wert < grenzwert:
        raise PruefwertZuKlein(f"Der Wert {bezeichnung} muss größer oder gleich {grenzwert} sein. ({bezeichnung} = {wert})")

def test_kleinster_wert():
    erstes_datum = Date(2022, 4, 18)
    kleinstes_wechselkursdatum = Date(2022, 4, 19)
    with pytest.raises(PruefwertZuKlein):
        pruefe_wert_groesser_gleich(erstes_datum, kleinstes_wechselkursdatum, "Kleinstes Datum der Kurstabelle")

if __name__ == "__main__":
    test_kleinster_wert()
Antworten