.
Anmeldung | Registrieren | Hilfe
in Suchen

Testen von EventHandlern

Letzter Beitrag 12. Sep 2010 14:02 von Peter Bucher. 9 Antworten.
Seite 1 von 1 (10 Treffer)
Beiträge sortieren: Zurück Weiter
  • 17. Aug 2010 23:51

    • Rainer Hilmer
    • Top 10 Mitwirkender
      Männlich
    • Registriert am 22. Jan 2008
    • Braunschweig
    • Beiträge 927
    • Punkte 14.070

    Testen von EventHandlern

    Hallo,
    ich bin ganz der Meinung von Golo und Ilker dass private Methoden nur indirekt getestet werden sollten (Details siehe http://www.des-eisbaeren-blog.de/post/2010/08/07/Privaten-Code-testen.aspx).

    Jetzt arbeite ich gerade an einem Artikel über Microsoft Moles und fahre Vergleiche mit anderen Mock-Frameworks (Moq und NMock3).
    Yadda yadda, genug der Hintergründe. Smile

    Was mir jedenfalls aufstößt, sind EventHandler in Verbindung mit gemockten Events. Ich brauche ein Verfahren mit dem ich verifizieren kann, ob das SUT das Event auch verarbeitet hat. Nun sind EventHandler aber in aller Regel a) private und b) void.
    Das NMock-Tutorial schummelt in dem Punkt. Dort hat die zu testende Klasse ein öffentliches Statusproperty, das im EventHandler gesetzt wird und im Test natürlich schön abgefragt werden kann.

    Auch im Moq-Quickstart steht ähnliches als Kommentar:
    // you would make assertions about later (how its state changed as a consequence, typically)

    Nun meine Frage: Ist das gängige Praxis?
    Ich kann mir nicht vorstellen dass ich für jeden EventHandler ein öffentliches Statusproperty schreiben soll - und das eigentlich nur für die Tests. Oder irre ich mich da? Wie macht ihr das denn?

    Gruß,
    Rainer
    • IP-Adresse ist Registriert
  • 18. Aug 2010 16:35 Antwort zu

    • Timo Rehl
    • Top 10 Mitwirkender
      Männlich
    • Registriert am 05. Mai 2009
    • Wald-Michelbach
    • Beiträge 591
    • Punkte 10.125
    • Moderator

    Testen von EventHandlern

    Hallo Rainer,

    normalerweise steckt ein Sinn hinter dem Registrieren von Events (z.B. Text muss auf der Oberfläche aktualisiert werden).
    Und genau das Verhalten würde ich nach dem Werfen auch testen.

    Ansonsten hätte ich als Idee (extrem aufwändig und wahrscheinlich oversized) den CLR Profiler zu verwenden, um festzustellen, dass der Handler aufgerufen wurde.

    Generell erachte ich es für sinnvoll auch ein Tracing zu ermöglichen. Dazu muss aber die zu testende Klasse in allen Methoden auch Tracing Ausgaben erzeugen. Wenn dem aber so wäre, dann könnte man anhand der Tracing Ausgaben sich behelfen.

    Grüße
    Timo
    - theres no place like 127.0.0.1 -
    • IP-Adresse ist Registriert
  • 18. Aug 2010 19:27 Antwort zu

    • Rainer Hilmer
    • Top 10 Mitwirkender
      Männlich
    • Registriert am 22. Jan 2008
    • Braunschweig
    • Beiträge 927
    • Punkte 14.070

    Testen von EventHandlern

    OK danke. Smile
    Gruß,
    Rainer
    • IP-Adresse ist Registriert
  • 18. Aug 2010 20:22 Antwort zu

    Testen von EventHandlern

    Antworten
    Die Frage scheint zwar beantwortet, aber dennoch will ich das jetzt wissen:

    Warum ist ein EventHandler privat? Wenn er privat ist, dann interessiert er mich auch nicht. Wenn ich einen Staubsauger in die Steckdose stecke und auf Power drücke, erwarte ich das er Staub saugt. Der Vertrag zwischen Benutzer und Gerät scheint also eindeutig. Was dieses Ding sonst noch so kann und wie es das anstellt ist mir ehrlich gesagt egal.

    Aber nochmal zurück zur Aussage: Der Event ist doch Public, oder? Und der Handler ist dann in meinem Fall eine eigene Methode. Oder meinst du, dass intern in dem SUT ein Event registriert wird und du testen willst ob in dem SUT der private Handler aufgerufen wurde?

    Ähmmm.... das geht dich ehrlich gesagt nichts an, da es Interna sind, ausser die Abhängigkeit wird von aussen in den Konstruktor in das SUT gereicht, dann kannst du es Anhand der gemockten Abhängikeit testen.

    Beispiel: Meine PomodoroTimer App. Auszug aus der Spezifikation:
    und hier die Implementierung:

    Von aussen gibts bei dem CountDownTimer zwei Events und die Test ich ob sie aufgerufen warten. Ich teste also kein Interna, sondern erwartetes Verhalten.

    Nun ist es aber wichtig zu unterscheiden, auf welcher Ebene du testest?
    Ist es ein BlackBox, WhiteBox, GreyBox Test? BlackBox, also mit Mocks ist klare Sache! Finger weg; Internas bleiben solche. Daher heißt es ja auch Blackbox. Bei White oder Greybox ist das was anderes. Da sind wir schon bei Integrationstests. Da dürfen Internas mitgetestet werden. Und hier kommen wir wieder zu unserem aller Lieblings-Pattern: Inversion Of Control. Du kannst nur das Testen, was du von aussen hereingibst (zumindest, wenn du Architektonisch Clean bleiben willst). 
    Du kannst aber die Profiler API nehmen, oder z.B. TypeMock (keine Ahnung wie das Ding es anstellt) und auch das auseinandernehmen.

    Ergo:
    Clean Code (gute Architektur)
    oder 
    Dirty Hack (schlechte Architektur)

    Das ist meine ganz persönliche Meinung. Wenn du im Brownfield unterwegs bist und dich dreckig machen musst, dann tu es! Nimm jedes ******** Werkzeug, dass du nur bekommen kannst um die Schwerverbrechen, die deine Erblasser verbrochen haben unter Kontrolle zu bekommen.

    Ansonsten bleib Clean und Teste Public.
    Vor allem stelle ich zur Diskussion, was passiert, wenn sich Internas ändern, aber die öffentliche Schnittstelle nicht?

    Mich interessiert nicht das wie, sonder das was bei einem Vertrag. Ob die Firma Rumänisch kann um mit outgesourcten Angestellten zu sprechen ist mir egal und ich werde es nicht prüfen. Ob die Firma ihren Arbeitern Pizza und Cola spendiert, damit die ihre Arbeit auch richtig machen, interssiert mich auch nicht.

    Was mich aber interessiert ist, was am Ende des Vertrages als Leistung erbracht wurde. Naja und so sehe ich das Verhältniss zwischen zwei Klassen auch. Contract First! und was sonst so im privaten abgeht .... hauptsache sie tut, was sie soll.

    my 2 cnt.

    P.S.: Frag dich dein Cheff, was du daheim in deinem Bett anstellst? Oder ist er zufrieden, wenn er zum Schluss das von dir bekommt, was ihr ausgemacht habt Wink

    • IP-Adresse ist Registriert
  • 18. Aug 2010 21:15 Antwort zu

    • Rainer Hilmer
    • Top 10 Mitwirkender
      Männlich
    • Registriert am 22. Jan 2008
    • Braunschweig
    • Beiträge 927
    • Punkte 14.070

    Testen von EventHandlern

    Hallo Rainer,
    ich glaube dir ja gerne. Ich suche für meinen Artikel eine sinnvolle Darstellung für das Mocking von Events. Vielleicht kannst du mir ja dabei helfen.

    Das Szenario ist folgendes: Irgendeine Klasse prüft einen Input. Ist dieser null, soll ein Report generiert werden. Das kann eine Email sein, ein Logeintrag oder sonstwas. Dafür habe ich ein Interface IErrorNotifier als Kontrakt.
    Falls das Senden des Reports fehlschlägt, wird ein Event mit der Exception im Gepäck gefeuert. Was der Receiver damit macht, ist mir egal. In meinem Demo ist es einfach eine Konsolenausgabe.
    ich habe mal diesen Test geschrieben:

          [TestMethod]
          [Description("Using Moq")]
          public void ShouldHandleTransmissionFailure()
          {
             var notifierMock = new Mock<IErrorNotifier>();
             notifierMock.Setup(errorNotifier =>
                              errorNotifier
                                 .SendErrorReport(It.IsAny<ErrorTransporter>()))
                .Raises(x => x.TransmissionFailed += null,
                   new ExceptionEventArgs(new Exception("Simulated Exception")))
                .Verifiable();
    
    
             var someClass = new SomeClass(notifierMock.Object);
             someClass.CheckInput(null);
             notifierMock.Verify();
             Assert.IsFalse(notifierMock.Object.TransmissionSuccessfull);
             Assert.IsTrue(someClass.TransmissionFailureHandled,
                "TransmissionFailed Event was not handled.");
          }

    Das Event-Mock wird aufgesetzt und später gefeuert, aber was würde dieser Test aussagen wenn ich nicht das TransmissionFailureHandled Property hätte? Ich finde, es wäre genau so unsinnig wie

    bool x = true;
    Assert.IsTrue(x);

    P.S.: Wenn ich meinem Chef nicht liefere was wir ausgemacht haben, wird er mich fragen ob ich mich zu lange im Bett herumgetrieben habe. Big Smile

    EDIT: Ich hab den Thread vorerst wieder auf unbeantwortet gestellt. Mal sehen was da noch kommt.

    Gruß,
    Rainer
    • IP-Adresse ist Registriert
  • 19. Aug 2010 13:01 Antwort zu

    • Timo Rehl
    • Top 10 Mitwirkender
      Männlich
    • Registriert am 05. Mai 2009
    • Wald-Michelbach
    • Beiträge 591
    • Punkte 10.125
    • Moderator

    Testen von EventHandlern

    Antworten
    Hallo Rainer S.,

    interessante Diskussion, ehrlich. So wie ich oben geschrieben habe bin ich ebenfalls Deiner Meinung: Der Sinn und das gewünschte Verhalten sollte man beim EventHandler testen.

    Aber jetzt speziell in diesem Fall: Ich war bisher immer der Überzeugung, dass EventHandler als "protected virtual" zu kennzeichnen wäre (wegen Vererbungen). Zumindest gibt das das Microsoft pattern so her (das auch nicht immer das goldene Ei ist, klar!).

    Ich würde es aber als kritisch ansehen, wenn EventHandler von außen öffentlich aufgerufen werden könnten. Dann wäre man in der Lage (auch ohne eigentliches Ereignis) eine Ereignisauslösung aufzurufen. Das halte ich für unsauber.

    Deshalb finde ich die Frage, wie ich es teste, ob ein Ereignis tatsächlich den EventHandler erreicht als durchaus berechtigt und nicht trivial. Hier an dieser Stelle würde ich 2 Fallunterscheidungen treffen:
    - Test, ob und mit welchen Parametern durch das Auslösen des Events vom EventHandler abgefangen werden
    - Test, ob der EventHandler richtig arbeitet, indem man überprüft, ob die entsprechenden Zustände verändert werden

    Schlimmstes Szenario, in das ich auch schon gelaufen bin: Ich ändere Ereignisreihenfolgen oder gar überhaupt das Verhalten, wann welche Events gefeuert werden => Resultat: Andere Komponenten verhielten sich dann nicht mehr so wie erwartet. Das sollte definitiv abgetestet sein, meiner Meinung nach.

    Grüße
    Timo

    Edit:
    TypeMock arbeitet, wenn ich das richtig interpretiert habe so, dass es eigene Klassen definiert, die anstelle der eigentlichen Objekte aufgerufen werden. Dabei muss immer vorgegeben werden wie die Rückgabewerte aussehen. Das Ganze würde ich mal tippen funktioniert mit Code Injection (Aber das ist nur das was ich vermute, für mich ist das eine BlackBox).
    - theres no place like 127.0.0.1 -
    • IP-Adresse ist Registriert
  • 19. Aug 2010 13:21 Antwort zu

    • karle
    • Top 25 Mitwirkender
    • Registriert am 20. Okt 2008
    • Beiträge 172
    • Punkte 2.030

    Testen von EventHandlern

    Ich steige mal wo anders ein:

    Ich bin mal beim rumspielen über folgendes gestolpert:

    - Der MultiCastDelegate hat eine Methode GetInvocationList

    - Dazu gibt es ein Feld irgendwo.

    - Dieses Feld hat mir der debugger einmal angezeigt (momentan finde ich es aber nicht oder der memory-inspector ist falsch eingestellt)

    - neben dem feld _invocationList war da noch ein _invocationCount oder so ähnlich und einige andere felder, ich habe allerdings nicht geschafft da über code ranzukommen. (2 der 6 felder oder so waren über system.reflection nicht sichtbar)

    - doch es gibt windbg und ich bin über eine seite gestolpert, bei der (wenn ich es richtig gesehen habe) eine kommandozeilenausgabe windbg den invocationcounter angezeigt hat. also scheint man auf dem weg ranzukommen.

    - da ich es im code gebräucht hätte, habe ich nicht weiter nachgeforscht, aber vl. hilft es dir ja als ansatz weiter. Die Suchergebnisse waren aber recht rar. Ich vermute das ganze wird als interna gehandhabt und ist offen für änderungen, so dass ich nicht darauf aufsetzen würde, wenn es anders geht.

    in meiner alten firma wurden aus message-logs testfälle generiert. es ist auch die frage ob whitebox oder blackbox test. bei whitebox tests werden auch interne zustände betrachtet, was die fehlerursache einschränkt, wenn ein test einen programmfehler entdeckt. dann habe ich schon gesehen, dass leute 'whiteboxinfo' - interfaces schreiben, um die internen zustände dem test bekannt zu geben. so abwegig finde ich das nicht,was rainer (hilmer) vorhat.

    karle

    In meinem Keller ist der Eingang zur Hölle - aber es stehen Kartons davor.
    • IP-Adresse ist Registriert
  • 12. Sep 2010 1:38 Antwort zu

    • Peter Bucher
    • Top 50 Mitwirkender
      Männlich
    • Registriert am 29. Jan 2008
    • Schweiz, Luzern
    • Beiträge 38
    • Punkte 560

    Testen von EventHandlern

    Antworten

    Hallo zusammen

    Privat ist privat, klar.
    Die öffentlichen Events vor einer Statusänderung per lokaler Variable (bool flag = false;) wie folgt im Pseudo-Eventhandler - per anonymer Methode, setzen.

     
    // somwhere in local scope
    bool flag = false;
    
    
    .Raises(x => x.TransmissionFailed += () => flag = true,
                   new ExceptionEventArgs(new Exception("Simulated Exception")))

    Nach einer Statusänderung (Schicken des Berichts), prüfung der lokalen Variable. Fertig.

    Öffentliche Eventhandler testen?

    • IP-Adresse ist Registriert
  • 12. Sep 2010 11:36 Antwort zu

    • Rainer Hilmer
    • Top 10 Mitwirkender
      Männlich
    • Registriert am 22. Jan 2008
    • Braunschweig
    • Beiträge 927
    • Punkte 14.070

    Testen von EventHandlern

    Hallo Peter,
    war ja klar. Auf die einfachste Lösung bin ich mal wieder nicht gekommen. *Kopf auf Tischplatte*

    Danke für den Tip. Smile

    Gruß,
    Rainer
    • IP-Adresse ist Registriert
  • 12. Sep 2010 14:02 Antwort zu

    • Peter Bucher
    • Top 50 Mitwirkender
      Männlich
    • Registriert am 29. Jan 2008
    • Schweiz, Luzern
    • Beiträge 38
    • Punkte 560

    Testen von EventHandlern

    Salute Rainer

    Okay :-).
    Diese Möglichkeit steht inzwischen schon in dutzenden Blogs, Phil Haack war einer der ersten, der das gebloggt hat. Eigentlich naheliegend, zu naheliegend *g*.

    • IP-Adresse ist Registriert
Seite 1 von 1 (10 Treffer)

WPF Forum | ASP.NET Forum | ASP.NET MVC Forum | Silverlight Forum | Windows Phone 7 Forum | SharePoint Forum | Dotnet Jobs | Dotnet Termine | Developer Blogs | Dotnet News

Das Team | Regeln | Impressum