Laden...

Tatsächlicher Nutzen von Unit-Tests [und TDD]

Erstellt von Rainbird vor 13 Jahren Letzter Beitrag vor 13 Jahren 53.354 Views
S
489 Beiträge seit 2007
vor 13 Jahren

Stellt Euch vor, ihr habt eine WCF Schnittstelle die ein dutzend Methoden zur Verfügung stellt. Bei jedem Aufruf einer Methode auf der Schnittstelle können dutzende verschiedener Exceptions auftreten. Jede der Exception soll anders behandelt werden (benutzerfreundlicher und passender Text und verpacken in eigene Exception und throw). Wie testet Ihr so was? Wenn Ihr das nur auf dem Interface der Komponente testet welche die WCF-Kommunikation kapselt, dann habt ihr allein für das Fehlerhandling deutlich über 100 Tests. Und es sind immer genau dieselben Tests! Wäre es denn nicht einfacher einen ExceptionCatcher wie folgt zu bauen:


private T ExceptionCatcher<T>(Func<T> function)
{
	try
	{
		return function();
	}
	catch (ArgumentNullException ex)
	{
		throw new IrgendwasException("parameter war null", ex);
	}
	catch (Exception ex)
	{
		throw new IrgendwasException("unbekannter fehler", ex);
	}
}

Diesen dann vollständig zu testen (der gehört ganz sicher nicht zu einem Kontrakt) und dann immer nur noch (z.B. mit Rhino.Mocks) zu prüfen, ob die Methode bei jeder Operation auf der WCF-Schnittstelle auch wirklich aufgerufen wird.


public bool IsEqual(string irgendwas)
{
	return ExceptionCatcher(() => TryIsEqual(irgendwas));
}

Das reduziert die Tests um einen erheblichen Faktor und die Wahrscheinlichkeit dass Testfälle fehlen oder falsch getestet wird nimmt entsprechend ab.

F
10.010 Beiträge seit 2004
vor 13 Jahren

Dann ist aber ExceptionCatcher aber nicht Bestandteil der Implementierung sondern eine Hilfsklasse für die Tests und gehört in die Unittest Klasse.

S
489 Beiträge seit 2007
vor 13 Jahren

Dann ist aber ExceptionCatcher aber nicht Bestandteil der Implementierung sondern eine Hilfsklasse für die Tests und gehört in die Unittest Klasse.

?( ?( ?( ?( Wie kommst Du denn darauf??

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo FZelle,

Dann ist aber ExceptionCatcher aber nicht Bestandteil der Implementierung sondern eine Hilfsklasse für die Tests und gehört in die Unittest Klasse.

der ExceptionCatcher wäre zwar eine Hilfsklasse, aber keine Hilfsklasse für die Tests sondern eine Hilfsklasse für das Modell. Insofern gehört er auf keinen Fall in die Unittest Klasse.

Hallo SeboStone,

wie schon gesagt, gibt es bestimmte Ausnahmen, bei denen es sinnvoll ist, Tests für private Methoden bzw. Klassen zu schreiben. Was du beschreibst klingt danach, als würde es so eine Ausnahme sein.

herbivore

F
10.010 Beiträge seit 2004
vor 13 Jahren

Und es sind immer genau dieselben Tests! Wäre es denn nicht einfacher einen ExceptionCatcher wie folgt zu bauen:

Das heisst für mich, hier wird eine Funktion gebaut, die für das Testen gedacht ist, also ist es ein TestHelper.

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo FZelle,

nein, das hast du missverstanden. Die Klasse ExceptionCatcher ist dafür da, um die Implementierung zu vereinfachen, nicht den Test. Das geht aber aus dem Post von SeboStone ziemlich klar hervor.

herbivore

F
10.010 Beiträge seit 2004
vor 13 Jahren

Denke ich nicht.

Wenn er explizit schreibt das es immer die selben Tests sind und daraufhin vorschlägt einen ExceptionCatcher zu schreiben, dann bleibt keine andere Wahl das so zu interpretieren.

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo FZelle,

du hast dir den ExceptionCatcher aber schon angeschaut und die Beschreibung was er tun soll? Das ist eindeutig Businesslogik. Im Prinzip wird hier ein Aspekt, nämlich das an verschiedenen Stellen immer gleich Exeption-Handling, ausgelagert. Das reduziert die Redundanz der Modellklasse. Den ExceptionCatcher wäre also auch dann sinnvoll, wenn man überhaupt keine Unit-Tests schreiben würden.

Die Testbarkeit erhöht sich nur wegen der Reduzierung die Redundanz.

Dass diese Verbesserung der Architektur durch Überlegungen zum Test ausgelöst wurde, deckt sich ja voll mit dem, was du oben gesagt hast:

TDD ist nicht nur Selbstzweck, sondern soll einem auch die Augen öffnen ...

Aber nur weil eine Änderung durch den Test motiviert wurde, heißt das ja noch lange nicht, dass die entstandene Klasse ExceptionCatcher in den Test-Code gehört. Und das tut sie eben auch nicht. Ob du das nun einsiehst oder auch nicht.

herbivore

F
10.010 Beiträge seit 2004
vor 13 Jahren

Das hat mit einsehen nichts zu tun.
Natürlich könnte dies tatsächlich so gedacht gewesen sein, aber es steht so nicht da.

Und selbst wenn, hat dann eine so wichtige Funktion ( sie wird dann ja dreh und Angelpunkt für jeden Funktionsaufruf ) nicht private zu sein, denn sie wird durch ihre Wichtigkeit automatisch zu einer nicht änderbaren und damit öffentlichen Funktion.

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo FZelle,

dass eine private Methode oder Klasse häufig benutzt wird und wichtig ist, sogar so wichtig, dass sie als nicht änderbar angesehen wird, heißt doch noch lange nicht, dass sie öffentlich gemacht werden muss oder auch nur darf. Das ist doch abstrus. Damit vermischt du völlig unterschiedliche Konzepte: Wichtigkeit für die Implementierung auf der eine Seite und öffentliches Verhalten eines Objekts. Ich kann mich des Eindrucks nicht erwehren, du hast dich bei dem konkreten Fall ziemlich verrannt.

herbivore

4.207 Beiträge seit 2003
vor 13 Jahren

herbivore,

ich muss an dieser Stelle FZelle zur Seite stehen - ich sehe das genauso wie er. AUch für mich ist das keine Businesslogik, und gehört zu den Tests - schließlich wird es ja auch nur für die Tests erstellt und ist Hilfslogik für die Tests.

Und woher Du weißt, ob etwas missverstanden wurde, ist mit schleierhaft - ich denke, das kann nur SeboStone beantworten.

Und gleich von verrannt zu sprechen, halte ich für etwas ... Fehl am Platze, um es mal vorsichtig auszudrücken.

Viele Grüße,

Golo

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

S
443 Beiträge seit 2008
vor 13 Jahren

Mir ist es ziemlich egal wer wohin rennt, solange ich nicht nachrennen muss.
(Für die Frauen unter uns: euch schon garnicht)

automatisch zu einer nicht änderbaren und damit öffentlichen Funktion

öffentlich im Sinnen von public class oder im Sinne von hervorgehoben und gut dokumentiert aber internal class?

mbg
Rossegger Robert
mehr fragen mehr wissen

Montag morgen ist die beste Zeit um eine erfolgreiche Woche zu beginnen

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo Golo Roden,

schließlich wird es ja auch nur für die Tests erstellt und ist Hilfslogik für die Tests.

nein, das stimmt beides nicht. Ich habe schon beschrieben warum.

ich denke, das kann nur SeboStone beantworten.

Richtig, und das hat er im Prinzip auch getan, indem er seine große Verwunderung und sein Unverständnis über die Behauptung, dass die Klasse in den Test-Code gehört, zum Ausdruck gebracht hat.

Und woher Du weißt, ob etwas missverstanden wurde, ist mit schleierhaft

Irgendwer muss es missverstanden haben, da es widersprüchliche Auffassungen gibt, wozu die Klasse dient.

Und gleich von verrannt zu sprechen, halte ich für etwas ... Fehl am Platze, um es mal vorsichtig auszudrücken.

Das bezog sich gar nicht auf das Missverständnis, sondern auf den in meinen Augen verzweifelten Versuch von FZelle, die Absolutheit der Regel, dass nur öffentliche Methoden getestet werden dürfen, trotz plausibler Gegenbeispiele aufrechtzuerhalten.

herbivore

S
489 Beiträge seit 2007
vor 13 Jahren

dass eine private Methode oder Klasse häufig benutzt wird und wichtig ist, sogar so wichtig, dass sie als nicht änderbar angesehen wird, heißt doch noch lange nicht, dass sie öffentlich gemacht werden muss oder auch nur darf. Das ist doch abstrus.

Dem stimme ich absolut zu. Wie kommt man auf die Idee Methoden-Zugriffsmodifizierer nach Wichtigkeit zu vergeben? Warum nicht gleich Zugriffsmodifizierer mit der Schrotflinte reinrotzen? 😁

Aber damit erklärt sich auch die Haltung nur Public Methods zu testen. Offensichtlich werden einfach alle Funktionen die es Wert sind getestet zu werden Public gemacht. Das ist ganz sicher der falsche Ansatz.

ich denke, das kann nur SeboStone beantworten.
Richtig, und das hat er im Prinzip auch getan, indem er seine große Verwunderung und sein Unverständnis über die Behauptung, dass die Klasse in den Test-Code gehört, zum Ausdruck gebracht hat.

Tatsächlich habe ich das getan. Herbivore hat mich richtig verstanden, Golo und FZelle leider nicht. Die Klasse / Komponente braucht ein entsprechendes Exceptionhandling und nicht der Test!
Ich gebe aber FZelle recht, wenn er sagt, dass man das auch in Tests verwenden kann. Ich bezweifle dann aber stark, dass die Tests leicht nachvollziehbar und selbsterklärend sind. So ist es auch kein Wunder warum er propagiert nur Integrationstests auf den Interfaces zu bauen.

Hoffentlich habe ich mich jetzt nicht schon wieder uneindeutig ausgedrückt. 😉

F
10.010 Beiträge seit 2004
vor 13 Jahren

Das hatte hier weniger etwas mit falsch verstanden zu tun:

"Ehefrau zum Ehemann:
Geh mal schnell in den Laden um die Ecke hol mal ein Brot, und wenn sie frische Tomaten haben, bring 6 mit."
Er brachte 6 Brote, und hatte vollkommen recht.

Genauso ist dein Satz oben.

S
489 Beiträge seit 2007
vor 13 Jahren

Ahh, dann bist Du also ein Till Eulenspiegel. 😁 Also wolltest Du mich nicht richtig verstehen, ist auch ok.

F
10.010 Beiträge seit 2004
vor 13 Jahren

Nein, das hat nichts mit verstehen wollen zu tun.
Du hast jetzt den Sinn meiner Analogie falsch interpretiert, weil du versuchst etwas "hineinzuinterpretieren".

Und genauso ist es beim Eheman.
Wenn du den Satz mal auseinander nimmst, ist es genauso wie er es verstanden hat richtig. Er hat nicht versucht das irgendwie zu interpretieren, sondern exakt so zu machen wie es ihm gesagt wurde.

Ich habe in 25 Jahren SW Entwicklung gelernt mit Sprache sehr präzise umgehen zu müssen.
Wenn man z.b. mal individual SW für eine Anwaltskanzlei macht, und auch sein Geld haben will, muss man seeeehr präzise sein.

S
489 Beiträge seit 2007
vor 13 Jahren

Wenn man z.b. mal individual SW für eine Anwaltskanzlei macht, und auch sein Geld haben will, muss man seeeehr präzise sein.){gray}

Dem stimme ich zu und ich bin der Meinung, dass ich mich fast immer entsprechend ausdrücke. Deswegen benenne ich auch immer wieder den Unterschied zwischen Unit- und Integrationstest - was Du z.B. nicht tust.
Vielleicht ist es mir bei dem betreffenden Post nicht ganz so gut gelungen wie gewollt, aber dann kann man doch davon ausgehen, dass ein intelligenter Leser das naheliegensde erkennt. Deine Analogie passt hierbei auch ins Bild. Wie wahrscheinlich ist es dass die Ehefrau gemeint hat dass er 6 Brote mitbringen soll?

4.207 Beiträge seit 2003
vor 13 Jahren

schließlich wird es ja auch nur für die Tests erstellt und ist Hilfslogik für die Tests.
nein, das stimmt beides nicht. Ich habe schon beschrieben warum.

Sorry, herbivore, Du hast => DEINE ≤ Sicht beschrieben, warum. Die ist doch nicht allgemein gültig?

Und gleich von verrannt zu sprechen, halte ich für etwas ... Fehl am Platze, um es mal vorsichtig auszudrücken.
Das bezog sich gar nicht auf das Missverständnis, sondern auf den in meinen Augen verzweifelten Versuch von FZelle, die Absolutheit der Regel, dass nur öffentliche Methoden getestet werden dürfen, trotz plausibler Gegenbeispiele aufrechtzuerhalten.

Mich hat hauptsächlich die Formulierung "verrannt" gewundert. Das klingt so ... absolutistisch, als ob FZelle ein Fanatiker wäre, der seine (in Deinen Augen) falsche Meinung auf Biegen und Brechen durchboxen muss. Das Wort "verzweifelt" geht in die gleiche Richtung.

Wie gesagt, mich wundern die Formulierungen ein wenig ...

Im Übrigen: Ich halte es nach wie vor für Blödsinn, privaten Code zu testen. Aus verschiedenen Gründen. Die genannten Beispiele (wieso eigentlich Beispiele? Es war doch nur eins?) haben mich nicht wirklich überzeugt.

Du hast selbst doch geschrieben, dass diese Helper-Klasse allgemein sein könnte:

Im Prinzip wird hier ein Aspekt, nämlich das an verschiedenen Stellen immer gleich Exeption-Handling, ausgelagert. Das reduziert die Redundanz der Modellklasse. Den ExceptionCatcher wäre also auch dann sinnvoll, wenn man überhaupt keine Unit-Tests schreiben würden.

Einen besseren "Beweis" als diesen kann es doch kaum geben, dass es eben nicht private zu sein hat - eben WEIL es an noch mehr Stellen Sinn machen würde.

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

S
489 Beiträge seit 2007
vor 13 Jahren

Im Prinzip wird hier ein Aspekt, nämlich das an verschiedenen Stellen immer gleich Exeption-Handling, ausgelagert. Das reduziert die Redundanz der Modellklasse. Den ExceptionCatcher wäre also auch dann sinnvoll, wenn man überhaupt keine Unit-Tests schreiben würden.

Einen besseren "Beweis" als diesen kann es doch kaum geben, dass es eben nicht private zu sein hat - eben WEIL es an noch mehr Stellen Sinn machen würde.

Was für ein Beweis? Schau Dir den ExceptionCatcher doch mal an, der wirft eine spezielle Exception, eine Komponenten-Exception. (Ok, das "Irgendwas" sieht wohl nicht danach aus, war aber so gemeint) Keine andere Komponente hat diesen ExceptionCatcher zu verwenden, denn normalerweise treten in jeder Komponente auch andere Exceptions auf. Und komponentenintern wird er auch nur an den Schnittstellen verwendet -> im Normalfall repräsentiert die Schnittstelle genau eine Klasse, im schlimmsten Fall gibts da noch eine Base-Klasse. Ergo, den ExceptionCatcher global zu machen oder sogar in den Kontrakt aufzunehmen ist ein architektonischer Gau.

2.891 Beiträge seit 2004
vor 13 Jahren

Thema ist ja "private Dinge testen". Stellt sich für mich erst einmal die Frage, was privat ist. Im Beispiel von SeboStone ist es eine Methode. (Anschlussfrage: Wie testest du denn konkret private Methoden). Nun ist in der Diskussion herausgekommen gibt es die Meinungen, dass der ExceptionCatcher relativ allgemein ist, an mehreren Stellen verwendet wird und somit ziemlich "wichtig" ist, sodass er doch öffentlich sein sollte.

Alternativvorschlag: Warum ist "der ExceptionCatcher" eigentlich eine Methode, die in irgendeiner anderen Klasse rumgammelt. Warum ist der ExceptionCatcher nicht eine separate Klasse, die die genannte Methode enthält? Käme auch dem Single Responsiblility Principle näher. Dann wäre die diskutierte Methode auch public und ließe sich auch separat testen (wenn Exception X geworfen wird, soll sie am Ende in einer Y gekapselt sein).
Bleibt noch der Einwand, dass die ExceptionCatcher-Klasse eher was internes ist und nicht jedem zugänglich sein soll. Dann mache in internal. Zurück beim Thema "wie teste ich privates" (denn das separate Test-Projekt kommt ja eigentlich nicht dran) kann man einfach das InternalsVisibleTo-Attribut, und schon ist das Problem gelöst.

Gruß,
dN!3L

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo Golo Roden,

Sorry, herbivore, Du hast => DEINE ≤ Sicht beschrieben, warum. Die ist doch nicht allgemein gültig?

sicher war das zu dem Zeitpunkt, als ich es geschrieben hatte, nur meine Sichtweise darüber, wie SeboStones Beitrag gemeint war. Aber nachdem SeboStones mittlerweile bestätigt hat, dass er tatsächlich so gemeint war, ist es die allgemeingültige Sichtweise. Oder wie SeboStones es formuliert hat:

Herbivore hat mich richtig verstanden, Golo und FZelle leider nicht.

..., als ob FZelle ein Fanatiker wäre, der seine (in Deinen Augen) falsche Meinung auf Biegen und Brechen durchboxen muss.

Richtig, genau das war in diesem konkreten Fall mein Eindruck.

wieso eigentlich Beispiele? Es war doch nur eins?

Nein, es gab zwei. Ein Beispiel war von spike24, eins von SeboStones.

Einen besseren "Beweis" als diesen kann es doch kaum geben, dass es eben nicht private zu sein hat - eben WEIL es an noch mehr Stellen Sinn machen würde.

Nur weil die Klasse/Methode einen bestimmten Aspekt realisiert, heißt das nicht, dass noch lange nicht, dass sie allgemein verwendbar ist. Diese konkrete Klasse/Methode sollte wie schon begründet private sein.

Hallo dN!3L,

Nun ist in der Diskussion herausgekommen, dass der ExceptionCatcher relativ allgemein ist, an mehreren Stellen verwendet wird und somit ziemlich "wichtig" ist, sodass er doch öffentlich sein sollte.

nein, das ist nicht rausgekommen. SeboStones als Autor der Methode ist immer noch der Meinung, dass sie nicht öffentlich sein sollte und ich kann ihm da nur beipflichten.

Dann wäre die diskutierte Methode auch public

Nein, nur weil man sie in eine separate Klasse auslagert, ist muss die Methode nicht public sein (und sollte es wie gesagt auch nicht). Sie könnte internal sein, oder die Methode ist zwar public, aber die Klasse nicht. In beiden Fällen wäre sie von außen betrachtet nicht öffentlich.

herbivore

2.891 Beiträge seit 2004
vor 13 Jahren

nein, das ist nicht rausgekommen

Seufz... hab die Formulierung geändert.

Nein, nur weil man sie in eine separate Klasse auslagert, ist muss die Methode nicht public sein (und sollte es wie gesagt auch nicht).

Wenn du die Methode in eine separate Klasse auslagerst, muss sie public (bzw. genauer: nicht private) sein, da du sie sonst nicht verwenden kannst.

internal [...] nicht öffentlich.

Wo wir beim Formulierungen auseinandernehmen sind: "nicht öffentlich"!="privat". Internal ist nicht öffentlich, aber auch nicht privat. Also beide Fliegen mit einer Klappe: Sie ist nicht öffentlich, weil SeboStone dass nicht möchte, sie ist aber auch nicht privat, damit man sie testen kann.
Und mithilfe des genannten Attributs ist sie (für die UnitTests) von außen betrachtet öffentlich, und für den Rest eben nicht.

Bleibt die Frage: Wie testet ihr denn konkret private Sachen?

Gruß,
dN!3L

U
1.578 Beiträge seit 2009
vor 13 Jahren

Über den Accessor?

Man kann in VS problemlos aus der UnitTest assembly auf die Privaten Methoden zugreifen, das InternalsVisibleTo braucht man gar nicht.

// Tested öffentliche Methode "GenerateObject"
[TestMethod]
public void GenerateObject_ValidObjectGenerated()
{
    MyFactory factory = new MyFactory();
    
    object generated = factory.GenerateObject("Bla");
    
    Assert.IsTrue(generated is typeof(Bla));
}

// Tested private Methode "IsValid" in der "SessionCreator" klasse
[TestMethod]
public void IsValid_IsInvalidSessionFolder()
{
    // IsValid wird nur intern verwendet und ist private
    SessionCreator_Accessor creator = new SessionCreator_Accessor();

    bool isValid = creator.IsValid("abc");

    Assert.IsFalse(isValid);
}

Änderungen an den Original Objekten ist nicht erforderlich.

Wenn ich die Privaten Methoden nicht teste zeigt mir Visual Studio im Code Coverage alle Privaten als komplett ungetestet.

Wenn ich nun den SessionCreator eine Session erstellen lass, dann muss ich aufwändig die Session validieren, das ist mit den internen Methoden einfacher, und sobald ich keine Session bekomme muss ich raus finden warum, eine Unit auf der privaten IsValid Methode hätte mir gleich gezeigt das dort ein Fehler ist.
Das sind die gründe warum ich Privates auch Teste, das macht die Validierung und Fehlersuche viel einfacher.

4.207 Beiträge seit 2003
vor 13 Jahren

Genau das, was dN!3L beschrieben hat, meinte ich: Man ziehe das Ding in eine eigene Klasse und mache es public.
1.Haben dann alle was davon (gegebenefalls muss man es ein wenig generischer machen, aber prinzipiell ist die Idee ja gemeingültig). 1.Kann man es dann problemlos testen, weil public. 1.Erschließt sich mir immer noch nicht, warum dieser Code in einer Klasse, die eigentlich eine ganz andere Aufgabe erfüllt, als private Methode herumliegen sollte.

Zum Thema, wie man privaten Krams testet. Dazu gibt's in meinen Augen nur eine Handvoll Varianten, die aber alle ihre Nachteile haben und für mich persönlich deshalb nicht in Frage kommen:
1.Per Reflection. Nachteil: Abhängigkeit von Magic Strings, keine Unterstützung bei Refaktorisierung.
@ CSL: Dazu zählt auch der Accessor. IMHO eine ganz schlechte Idee, das so zu machen. Um ehrlich zu sein: Von den hier aufgezählten vier Möglichkeiten ist es die in meinen Augen schlechteste.

1.private in protected umwandeln und Test ableiten: private und protected sind zwei Paar Schuhe und haben nicht die gleiche Semantik. Zudem keine Unterstützung bei sealed Klassen. 1.private in internal umwandeln und InternalsVisibleTo nutzen: Auch hier, andere Semantik von private und internal. 1.Zustand als Abhängigkeit (siehe http://ralfw.blogspot.com/2009/11/zustand-als-abhangigkeit-ioc-konsequent.html): Für mich von allem noch die sauberste Lösung, weil die wenigsten Probleme bestehen. Trotzdem Nachteil: Zusätzlicher Konstruktor notwendig, es wird nicht der Konstruktor verwendet und getestet, der auch im Produktivcode zum Einsatz kommt.

Alles in allem gibt es für mich keinen sauberen Weg, privaten Code zu testen.

Aber: Ganz abgesehen davon kann ich nur FZelle beipflichten, der weiter oben bereits erklärt hat, warum man privaten>Code nicht testet: Weil er Interna betrifft und nicht den nach außen zugesicherten Kontrakt.

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

4.207 Beiträge seit 2003
vor 13 Jahren

Sorry, herbivore, Du hast => DEINE ≤ Sicht beschrieben, warum. Die ist doch nicht allgemein gültig?
sicher war das zu dem Zeitpunkt, als ich es geschrieben hatte, nur meine Sichtweise darüber, wie SeboStones Beitrag gemeint war. Aber nachdem SeboStones mittlerweile bestätigt hat, dass er tatsächlich so gemeint war, ist es die allgemeingültige Sichtweise. Oder wie SeboStones es formuliert hat:

Herbivore hat mich richtig verstanden, Golo und FZelle leider nicht.

Nein, herbivore - es ist Deine und SeboStones Sichtweise. Nicht die allgemeingültige. Wenn es sie wäre, würde hier nicht so viel Gegenwind kommen, siehe FZelle, dN!3L und ich. Und wir alle drei nicht gerade erst seit gestern entwickeln, empfinde ich es als etwas überheblich, wenn Du Deine beziehungsweise Eure Meinung als "allgemeingültig" darstellst und unsere Meinung mit einem Handschlag wegwischst.

..., als ob FZelle ein Fanatiker wäre, der seine (in Deinen Augen) falsche Meinung auf Biegen und Brechen durchboxen muss.
Richtig, genau das war in diesem konkreten Fall mein Eindruck.

Ich muss mir wirklich Mühe geben, hier nicht sarkastisch zu werden - aber etwas Reflektion wäre in diesem Fall gegebenenfalls nicht verkehrt.

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

U
1.578 Beiträge seit 2009
vor 13 Jahren

Also ich find es mit dem Accessor daher gut das man das original Projekt nicht anfassen muss, keine Sichtbarkeit ändern und auch keine Attribute hinzu.

Du bist aber nicht auf den Vorteil eingegangen den sich durch testen von privaten Methoden ergibt: Gleich sehen wo der Fehler liegt (Objekt ist nicht valide, warum?) und Validieren das man den Bug an der Stelle auch wirklich behoben hat.

Wenn eine Klasse ein komplexes Objekt zurück gibt kann man viel übersehen bei der Validierung dieses Objektes, das fängt man in den einzelnen Zwischenschritten in den privaten Methoden ab, so übersieht man auch wirklich nichts, da man die privaten Methoden auch mit falschen Parametern ausreizen kann.

4.207 Beiträge seit 2003
vor 13 Jahren

Ich bin deshalb nicht darauf eingegangen, weil für mich die Nachteile die Vorteile um Welten überwiegen.

Was das Testen von privatem Code angeht: Entweder liefern mir die Methoden, Eigenschaften, Events, ... die als public im Kontrakt definiert sind, das zurück, was ich erwarte, oder nicht. Ob der Fehler dann aus dem public-Element direkt stammt oder aus einem dahinterliegenden private-Element sehe ich nicht auf Anhieb. Das stimmt. Nur findet man das im Normalfall relativ fix über den Debugger raus, indem man durchsteppt.

Wenn in privaten Methoden dermaßen viel Code ist, dass jetzt als Gegenargument kommt, dass das zu viel Aufwand wäre, dann kann ich mich nur wiederholen: Dann steckt in der privaten Methode zu viel Logik, die in 99% der Fälle ausgelagert gehört.

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

4.207 Beiträge seit 2003
vor 13 Jahren

PS: Noch mal zum Thema "allgemeingültig" ...

Google-Suche nach "what to unittest public private" liefert als zweiten Treffer einen interessanten Treffer von stackoverflow.com.

Am besten geratete Antwort (mit 49 Ups):

If you want to unit test a private method, something may be wrong. Unit tests are (generally speaking) meant to test the interface of a class, meaning its public (and protected) methods. You can of course "hack" a solution to this (even if just by making the methods public), but you may also want to consider:

If the method you'd like to test is really worth testing, it may be worth to move it into its own class.
Add more tests to the public methods that call the private method, testing the private method's functionality. (As the commentators indicated, you should only do this if these private methods's functionality is really a part in with the public interface. If they actually perform functions that are hidden from the user (i.e. the unit test), this is probably bad).

Die zweitbeste Antwort (mit 15 Ups) bezieht sich auf InternalsVisibleTo.

Quelle: http://stackoverflow.com/questions/250692/how-do-you-unit-test-private-methods

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

4.207 Beiträge seit 2003
vor 13 Jahren

PPS: Wikipedia schreibt unter http://de.wikipedia.org/wiki/Modultest#Eigenschaften_von_Modultests:

Test des Vertrages und nicht der Algorithmen
Modultests sollen gemäß dem Design by contract Prinzip möglichst nicht die Interna einer Methode testen, sondern nur ihre externen Auswirkungen (Rückgabewerte, Ausgaben, Zustandsänderungen, Zusicherungen). Werden auch interne Details der Methode geprüft (dies wird als White-Box-Testing bezeichnet), droht der Test fragil zu werden, er könnte auch fehlschlagen, obwohl sich die externen Auswirkungen nicht geändert haben. Daher wird in der Regel das sogenannte Black-Box-Testing empfohlen, bei dem man sich auf das Prüfen der externen Auswirkungen beschränkt.

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

U
1.578 Beiträge seit 2009
vor 13 Jahren

Private Methoden Testen:

Pro:

  • Genaueres Testen möglich, man kann die Privaten lustig mit Informationen voll pumpen und so die Stabilität erhöhen, das ohne zu erreichen ist manchmal verdammt schwer
  • Genaueres Validieren, die privaten Methoden machen sehr wenig, also gibt es auch sehr wenig zu Validieren, und das ist schneller, einfacher und dadurch auch sicherer

Contra:

  • Refactoring komplizierter

Welche nachteile siehst du denn noch so?

Interessant ist auch der Artikel zum White-Box-Testing 😉

PS. Wie kann man dem Code Coverage in VS klar machen das Private Methoden ignoriert werden soll (ohne Anpassung des Original Codes)? Wenn ich die Privaten weg lasse komm ich nie auf 100%

2.891 Beiträge seit 2004
vor 13 Jahren

Du bist aber nicht auf den Vorteil eingegangen den sich durch testen von privaten Methoden ergibt[...]

Aber dadurch verschlimmerst du doch noch die Nachteile von Unittests: Refactoring wird erschwert durch ständiges nachwarten der Tests, bei der kleinsten Änderung schlagen viele Tests fehl, obwohl das Verhalten der Komponente (der öffentliche Kontrakt) korrekt ist. Die Tests sind völlig überspezifiziert.
Da würde ich aber schnell die Nase voll haben von Unittests...

Wie kann man dem Code Coverage in VS klar machen das Private Methoden ignoriert werden soll (ohne Anpassung des Original Codes)? Wenn ich die Privaten weg lasse komm ich nie auf 100%

Dann musst du entweder mehr Tests schreiben (mit Parametern, sodass alles getroffen wird), oder aber deine privaten Methoden enthalten wirklich Code, der nie benutzt wird.
Du musst dir erstmal genauer Gedanken machen, warum du wirklich nicht auf 100% kommst bzw. kommen kannst. Und dass die Unittest-Methode die einzige ist, die den Code mal durchläuft (nur damit eine dir wichtige Zahl größer wird), kann auch auch nicht Sinn und Zweck sein...

Gruß,
dN!3L

4.207 Beiträge seit 2003
vor 13 Jahren

Contra:
*Refactoring komplizierter *Abhängigkeit von Interna, die mich als Außenstehender nichts angehen (ein Test ist wie jeder andere Verwender auch ein solcher Außenstehender) *Tests sind ein Verwender von Code => jeden anderen Verwender interessiert auch nur der Kontrakt, nicht das Innenleben

Umgekehrt möchte ich Dich fragen:

Welche Nachteile siehst Du, wenn man die privaten Methoden in öffentliche umwandelt und in neue Klassen mit dedizierter Aufgabenstellung gemäß dem SRP verpackt?

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

U
1.578 Beiträge seit 2009
vor 13 Jahren

Ich rede natürlich von Methoden wo ein auslagern kein sinn macht.
Oder habe ihr alle klassen ohne private Methoden?

Nehmen wir ein Beispiel.
Eine UI wo man verschiedene Objekte die in Controls stecken durch schalten kann
Unten links hat man ein Zurück, und ein Vor Button welche das "CurrentItem" durch loopt.

Dadurch ergibt sich eine private "MoveCurrent" Methode

  • Die lohnt nicht aus zu lagern
  • Die wird durch die äußeren Schnittstellen nie aufgerufen
    -> Sie ist privat und ohne privaten Test nicht abgedeckt.
4.207 Beiträge seit 2003
vor 13 Jahren

1.Nein, meine Klassen haben private Methoden. Die sind aber über die aufrufenden öffentlichen Methoden mit abgedeckt. 1.Wieso wird in Deinem Beispiel niemals die MoveCurrent-Methode über die öffentliche Schnittstelle aufgerufen?

Sauber wäre doch, wenn Du hinter der Form ein Modell hast, das den aktuellen Stand repräsentiert (quasi ein ViewModel 😉), das zwei Methoden bietet: MoveNext, MovePrevious.

Die sind öffentlich und werden von der Form aufgerufen.

Und dann wird auch MoveCurrent von MoveNext und MovePrevious aufgerufen. Wenn Du die beiden richtig testest, wird MoveCurrent ja automatisch mitgetestet.

Wo ist da das Problem?

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

U
1.578 Beiträge seit 2009
vor 13 Jahren

Nein ich habe keine Öffentliche Schnittstelle zu diesen Methoden 😉 Da es außerhalb des Fensters niemanden etwas angeht und auch die View nie ausgetauscht wird 😉

4.207 Beiträge seit 2003
vor 13 Jahren

Das ist aber dann Dein Problem. Dein Code ist nicht sauber getrennt, weil die View mit dem Model stärker zusammenhängt als notwendig. Es steht Dir ja frei, ein Interface einzuführen und Dein Testproblem damit zu lösen.

Die Argumentation, dass es nicht anders möglich wäre, hast Du damit gerade ad absurdum geführt.

Es geht in diesem konkreten Fall nämlich nicht um nicht können, sondern um nicht wollen.

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

U
1.578 Beiträge seit 2009
vor 13 Jahren

D.h. ich sollte die (sehr gute!) Applikationsarchitektur umstellen nur damit ich private Methoden nicht testen muss? Das ist absurd.

Das es nicht gut getrennt ist kannst du nicht behaupten 😉 Es ist eine reine View Aktion die mit den Models absolut nichts zu tun hat, wie gesagt, die Architektur ist sehr gut und bewährt.

4.207 Beiträge seit 2003
vor 13 Jahren

Deine View soll Daten anzeigen. Nicht mehr und nicht weniger. Das ist der Sinn einer View. Wie der Name schon sagt 😉. Sie hat nicht als Aufgabe, vor oder zurück zu blättern, oder sonstwas zu machen. Sie hat nur ein paar Buttons, mit denen man das Vor- und Zurückblättern auslösen kann.

Wenn Deine View mehr macht, als nur anzeigen und Eingabefelder bieten, verletzt sie das SRP. Darüber brauchen wir nicht diskutieren, das ist so.

Wenn es nun nicht möglich ist, das Blättern zu testen, weil das Blättern irgendwie privat in der View drin steckt, macht die View mehr als sie soll, und erfüllt für meine Begriffe den Term "unsauber". Sie zeigt nicht nur an.

Wenn Du irgendwann (hypothetisch) doch eine andere View einführen müsstest, hättest Du ein Problem. Daran siehst Du, dass die Trennung nicht sauber ist. Ob Du diese View jemals brauchen wirst oder nicht, ändert ja nichts an der Tatsache, dass View und Logik nicht sauber getrennt sind.

Kurzum: Zumindest in Bezug auf die View kann ich nach Deiner kurzen Darstellung nicht erkennen, dass die View eine sehr gute Architektur aufweist. Vielleicht tu ich Dir damit unrecht - ich kenne den Code ja auch nicht. Was Du beschreibst, klingt aber alles andere als sauber.

Und wie ich schon sagte: Es geht nicht um nicht können, sondern um nicht wollen - denn wenn Du wolltest, könntest Du die Trennung ja herstellen. Es ist Dir aber zu viel Aufwand. Das mag berechtigt sein. Es ist aber kein berechtigter Grund für die Aussage, dass es nicht ginge - denn das tut es sehr wohl.

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

U
1.578 Beiträge seit 2009
vor 13 Jahren

Natürlich gehört das in die View, denn sie Zeigt ja die geblätterten Controls an.
Es war tatsächlich zu beginn so das die View alle Controls zuerst in Tabs anzeigte, das hatten wir dann zwecks Übersicht geändert sodass man durch die Liste iteriert.

Auf jeden Fall zeigt das das es Private View Methoden gibt die nicht öffentlich zugänglich sind aber getestet werden sollen.
Ich bin dann konsequent und Teste immer alle Privaten Methoden.

In deiner Contra liste hast du ein verhalten "Unit ist Customer" als zwei Punkte aufgeführt, und da stimme ich auch nicht zu, die Units sind nicht nur ein Customer sondern sie Testen die Applikation auf Herz und Nieren.

Und das übertrifft keineswegs die Pros die ich aufführte.

  • Genaueres Testen
  • Genaueres Validieren

Es wurde hier in diesem Thread auch oft erwähnt das man nicht an alle Cases Denken kann, durch solch detaillierte Tests hat man eine viel bessere abdeckung der möglichen fälle.

PS. Meine Fragen wegen den VS Code Coverage steht noch.

4.207 Beiträge seit 2003
vor 13 Jahren

CSL, nein, es gehört nicht in die View, sondern ins ViewModel. Genau dafür gibt es dieses nämlich. Siehe MVVM-Pattern.

Und wieso die darin enthaltenen privaten Methoden nicht im ViewModel öffentlich gemacht werden können, habe ich nach wie vor nicht verstanden.

Wegen dem VS CodeCoverage wurde Dir bereits von dN!3L geantwortet:

Dann musst du entweder mehr Tests schreiben (mit Parametern, sodass alles getroffen wird), oder aber deine privaten Methoden enthalten wirklich Code, der nie benutzt wird.
Du musst dir erstmal genauer Gedanken machen, warum du wirklich nicht auf 100% kommst bzw. kommen kannst. Und dass die Unittest-Methode die einzige ist, die den Code mal durchläuft (nur damit eine dir wichtige Zahl größer wird), kann auch auch nicht Sinn und Zweck sein...

Weißt Du, was mich etwas wundert? dN!3L hat Dir gesagt, dass es Quatsch ist. Ich habe Dir gesagt, dass es Quatsch ist. FZelle hat gesagt, dass es Quatsch ist. Bei StackOverflow sagen eine Menge Leute, dass es Quatsch ist. Bei Wikipedia steht, dass es Quatsch ist.

Dass Du es anders siehst, ist Dein gutes Recht. Aber was mich wundert, ist, dass es Dich nicht zumindest einmal nachdenklich stimmt, wenn nicht nur hier im Forum gesagt wird, dass man privates nicht testet.

Um es mal auf den Punkt zu bringen: Hast Du es schon einmal getestet mit privates in eigene Klassen auslagern ausprobiert? Und damit meine ich nicht nur mal eben fünf Zeilen hin- und hergeschoben, sondern mal ein etwas größeres Beispiel auf die Art entwickelt?

Und PS: Es wird weder genauer getestet noch validiert, wenn Du private-Code testest. Wenn Deine Tests im public-Fall schlechter sind, heißt das, dass Dein Code nicht sauber strukturiert ist.

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

2.891 Beiträge seit 2004
vor 13 Jahren

Hallo CSL,

zum Thema "100% Testabdeckung durch Testen privater Methoden": Angenommen, du hast folgende Klasse:


public class Adder
{
   public int Add(int a,int b) { return a + b; }
   private int Foo() { /* crazy code */ }
   private void Bar(string value) { /* insane code */ }
   private string Baz() { /* buggy code */ }
}

Nur die öffentlichen Methoden getestet, erhältst du eine Testabdeckung von 25% (1 von 4 Member abgedeckt).
Dein Vorgehen ist jetzt also...*25% ist kleiner als 100%, also teste ich auch die drei privaten Methoden. 100% erreicht, fertig.

... statt dich zu fragen ...*Habe ich alle Parameterkombinationen von a und b abgedeckt? *Habe ich vielleicht irgendwo vergessen, Foo, Bar oder Baz aufzurufen? *Brauche ich Foo, Bar oder Baz überhaupt, oder können sie gelöscht werden?

Du lässt also lieber erstmal versteckte Bugs liegen oder wartest/debuggst/testest drei mal mehr Methoden als nötig?

4.207 Beiträge seit 2003
vor 13 Jahren

Als Ergänzung: Ich habe zu dem Thema noch gebloggt, siehe http://www.des-eisbaeren-blog.de/post.aspx?id=fbf99245-0a81-46e7-bbab-3420cb8fe0d7

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

5.742 Beiträge seit 2007
vor 13 Jahren

Wenn Du irgendwann (hypothetisch) doch eine andere View einführen müsstest, hättest Du ein Problem. Daran siehst Du, dass die Trennung nicht sauber ist

Ohne jetzt gegen deine Aussage argumentieren zu wollen, private Member nicht zu testen, doch eine kleine Anmerkung:
Das klingt doch - wie du auch selbst schreibst - sehr "hypotetisch". IMHO sollte man sehr vorsichtig sein mit dem "auf Vorrat" refaktorieren.
Das führt letztendlich zu extrem aufgeblähtem Code, der nicht mehr wirklich einfach zu durchschauen ist. Jedes Interface erhöht zwar den Abstraktionsgrad - mit einer Erhöhung des Abstraktionsgrades steigt aber auch zweifelsfrei die Komplexität eines Systems.
Und nur weil man denkt, ein Feature "irgendwann" mal brauchen zu können oder "irgendwann" eine gewisse Abstraktion auf eine andere Art einsetzen zu wollen, heißt das noch lange nicht, dass man sie sofort durchführen sollte.

Wenn man die Abstraktion dann tatsächlich braucht, stellt man häufig fest, dass man eigentlich eine ganz andere Abstraktion braucht, als man sie schon geschaffen hat.
Dann hat man zwei Möglichkeiten: Entweder, man löst die "ursprüngliche" Abstraktion auf und schafft eine, die perfekt passt.
Die Alternative (die aber vermutlich eher durchgeführt wird) wäre eine nicht so angenehme: Man verwendet die bestehende Abstraktion, auch wenn sie nicht ganz passt, weil man ja schon eine entsprechende Abstraktion besitzt und arbeitet irgendwie um die Unzulänglichkeiten dieser herum.

Daher: Für die Einführung der Abstraktion sollte auch noch genügend Zeit sein, wenn man die Abstraktion tatsächlich braucht. Man hätte eben kein Problem, wenn man ein zweites View einführen möchte - man refaktoriert ein wenig und kann dann das neue View einführen.
Einigermaßen ordentlich strukturierter Code sollte sich zu diesem Zwecke leicht refaktorisieren lassen. Genau das ist ja auch das Tolle an Refactoring: Man kann das System auch im Nachhinein so umstrukturieren, wie es die aktuelle Situation erfordert, ohne vorher an alle Eventualitäten denken zu müssen.

Single Responsibility? Auf jeden Fall! Aber eben nur da, wo es auch Sinn macht. Nur des Zweckes wegen alle Verantwortlichkeiten aufsprengen zu wollen, halte ich nicht wirklich für sinnvoll - "Keep it Short and Simple"; und zu starke Abstraktion aufgrund irgendwelcher Annahmen macht das IMHO nicht.

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo Golo Roden,

Nein, herbivore - es ist Deine und SeboStones Sichtweise. Nicht die allgemeingültige. Wenn es sie wäre, würde hier nicht so viel Gegenwind kommen, siehe FZelle, dN!3L und ich. Und wir alle drei nicht gerade erst seit gestern entwickeln, empfinde ich es als etwas überheblich, wenn Du Deine beziehungsweise Eure Meinung als "allgemeingültig" darstellst und unsere Meinung mit einem Handschlag wegwischst.

reg dich mal ab. Meine Aussagen bezogen sich darauf, wie SeboStones Beispiel von ihm selbst gemeint war. Und wenn SeboStones sagt, es war so und so gemeint und das stimmt mit dem überein, was ich gesagt habe, aber nicht mit dem, was du gesagt hast, dann hatte ich Recht und du hattest dich geirrt. Das Wort etwas hochtrabende Wort "allgemeingültig" hast du ins Spiel gebracht und nicht ich. Ich habe es nur aufgegriffen und allgemeingültig ist es deshalb, weil es es nur eine Instanz gibt, die sagen kann, wie das Beispiel gemeint war, nämlich SeboStones. Du bist ein schlechter Verlierer, wenn du das nicht eingestehen kannst.

Was anderes ist die Aussage darüber über das Testen von privaten Methoden. Da habe ich nie behauptet, etwas allgemeingültiges zu sagen zu können. Da stimmt außerdem meine Meinung mit deiner Meinung fast vollständig überein. Wie ich schon oben schrieb, bin ich der Meinung, dass von Grundsatz her private Methoden nicht getestet werden sollen. Ich habe auf CSLs Frage sogar oben schon ausführlich begründet, welchen Nachteile es hat, private Methoden zu testen. Wo unsere Meinung (zumindest FZelles Meinung und meine Meinung) voneinander abweichen, ist ob man aus der Regel ein absolutes Dogma machen sollte. Und da sage ich nein, die Regel ist zwar vom Grundsatz her gut, aber es gibt auch einige wenige berechtige Ausnahmen.

Der einzige massive "Gegenwind" (der übrigens nur von dir und FZelle, aber nicht von dN!3L kam), den ich sehe, ist der, wo du erwiesenermaßen Unrecht hattest, nämlich der bei bei der Frage, wie SeboStones Beispiel gemeint war. Und diesen Gegenwind - nachdem diese Frage abschließend und eindeutig geklärt ist - aufrecht zu erhalten und immer und immer wieder nachzukarten, ist - sorry - einfach nur peinlich.

Weißt Du, was mich etwas wundert? dN!3L hat Dir gesagt, dass es Quatsch ist. Ich habe Dir gesagt, dass es Quatsch ist. FZelle hat gesagt, dass es Quatsch ist. Bei StackOverflow sagen eine Menge Leute, dass es Quatsch ist. Bei Wikipedia steht, dass es Quatsch ist.

Nicht zu vergessen, herbivore hat gesagt, dass es Quatsch ist. 😃

herbivore

U
1.578 Beiträge seit 2009
vor 13 Jahren

...

Diese Fragen kommen nicht auf

>> Habe ich alle Parameterkombinationen von a und b abgedeckt?
<< Das denke ich immer wenn ich UnitTests schreibe, ich Pumpte eine Methode immer mit allen möglichen voll

>> Habe ich vielleicht irgendwo vergessen, Foo, Bar oder Baz aufzurufen?
>> Brauche ich Foo, Bar oder Baz überhaupt, oder können sie gelöscht werden?
<< Kommt nicht vor, ich erstelle eine Methode sobald ich sie auch brauch, entsprechend wird sie dann auch aufgerufen

@Golo Roden
Es mag sein das einige der Meinung sind das es Quatsch ist, aber ich habe bisher keine nachteile gehört die die Vorteile aufwiegen.
Am ende ist es lediglich das Refactoring was erschwert wird, weitere nachteile gibt schlichtweg nicht, du hast ja auch nur pseudo nachteile aufgeführt auf denen ich schon ein ging. Auch alle anderen reden im Prinzip nur von den Refactorings.

Des weiteren gibt es viele nach plapperer die nicht selber mal nach denken und es ausprobieren 😉

Zudem muss ich dir schon wieder widersprechen, es ist reine View arbeit, da lediglich die Controls anders angezeigt werden, sieh diese Loop Möglichkeit als ein modifiziertes TabControl. Findest du auch das ein TabControl ins ViewModel gehört?

Des weiteren entwickel ich dieses tool nicht nach MVVM, da ich es einfach nicht benötige, trotzdem habe ich eine klare Trennung, das wenn die Anforderung kommen sollte die View aus zu tauschen, ich den Code problemlos in ViewModels auslagern könnte.

BTW. denkst du deine Argumentation/Meinung gewinnt an Gewicht nur weil du es Bloggst? Hast bisher viel Werbung für dein Blog gemacht 😉

4.207 Beiträge seit 2003
vor 13 Jahren

@ CSL: Nein, ein TabControl gehört in die View. Weil es ein Control ist, das etwas anzeigt. Genauso gehören die Buttons zum Blättern in die View, weil sie die UI-Elemente darstellen.

Logik zum Weiterblättern ist nichts sichtbares und hat damit auch nichts in der View verloren, weil es eben keine UI, sondern UI-Logik ist. Deswegen gehört so was ins ViewModel.

Natürlich kannst Du es anders machen.

Es ging darum, für Dein konkretes Beispiel zu zeigen, dass es sehr wohl möglich ist, privaten Code so in eine andere Klasse als öffentlich zu verlagern, dass er gut testbar wird. Dass dem so ist, habe ich Dir mit MVVM gezeigt. Dass Du das nicht machen willst, ist Deine Sache, es ging ja aber darum zu zeigen, ob es denn überhaupt möglich wäre. Das habe ich gezeigt.

Du hast geschrieben, dass Du Dich mit Unittests noch nicht all zu lange befasst, und TDD für Dich noch relativ neu ist. Das ist okay, jeder fängt mal an. So lange ist es bei mir selbst ja auch noch nicht her.

Du siehst keine Vorteile im Nicht-Testen von privatem Code. Das ist okay, das ist Deine derzeitige Meinung. Du hast es aber - zumindest schien mir das so - auch noch nie wirklich anders versucht, bügelst es aber von vornherein als sinnlos ab, weil Du keine Vorteile siehst. Das finde ich schade. Denn manchmal erkennt man die Vorteile erst, wenn man es einmal eine Weile lang versucht hat.

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

2.891 Beiträge seit 2004
vor 13 Jahren

Diese Fragen kommen nicht auf [...] [da ich] eine Methode immer mit allen möglichen voll [pumpte] [und ich] eine Methode sobald ich sie auch brauch [erstelle], entsprechend wird sie dann auch aufgerufen

Tja, dann musst du aber auch auf eine Testabdeckung von 100% kommen können. Wenn du alle öffentlichen Member so benutzt, dass alle Codepfade abgedeckt sind, und es keine nicht benutzten/nicht benötigten Codeteile gibt, dann muss ja alles komplett abgedeckt sein.

Gruß,
dN!3L

U
1.578 Beiträge seit 2009
vor 13 Jahren

Nicht wenn diese Methoden nur von der UI benutzt werden, und privat sind, wie das weiter blättern Beispiel. Diese sind von der äußeren Schnittstelle nicht abgedeckt.

@Golo Roden
In einem Tab blätter man auch weiter, nur halt indem man auf die Tab Header klickt, nach deiner Logik müsste das umschalten der Tabs auch ins ViewModel.

Oder nehmen wir mal dieses Beispiel:
MVVM: Ersetzen der TextBox selektion?

Da steh ich mit der Meinung das es in die Methoden in die View gehören auch nicht allein da, wie man sieht sind das private Methoden die nur von der View verwendet werden, die ich mit den Accessor Problemlos testen kann.
Bei den oberen kann ich Testen das die TextBox den neuen Text bekommen hat, und bei den Unteren kann ich überprüfen welches Control den Focus bekommen hat (das geht auch ohne das ich die View anzeigen lass).

4.207 Beiträge seit 2003
vor 13 Jahren

@ CSL:

Offensichtlich hast Du weder MVVM verstanden, noch hast Du das Problem mit der Reflection verstanden. Mit TDD hast Du Dich nach eigener Aussage noch nicht groß beschäftigt, und Unittests sind für Dich nach eigener Aussage noch relativ neu.

Man kann Dir zum Thema "privaten Code testet man nicht" als Quelle vorsetzen, was man will - Du siehst den Vorteil in den Accessoren als so überdramatisch wichtig an und ignorierst sämtliche Hinweise, dass an Deiner Testvorgehensweise etwas falsch sein könnte. So wie Du es beschreibst, hast Du auch nicht verstanden, wie das Testen in VS funktioniert bzw wie die Codecoverage arbeitet.

Da Du aber offensichtlich nicht gewillt bist, es Dir auch einfach mal anzugucken, und Deine bisherige Vorgehensweise für das Nonplusultra hältst, mit der Du sehr gute Architekturen baust und anscheinend ja perfekt getesteten Code entwickelst - was will man da noch sagen? Da fehlen mir irgendwann einfach die Worte.

Teste so, wie Du es für richtig hältst. Viel Erfolg damit.

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de