Laden...

Wie testet man ViewModels die in Views mit AttachedBehaviours (Eingabeformat) verwendet werden?

Erstellt von sth_Weird vor 7 Jahren Letzter Beitrag vor 7 Jahren 1.570 Views
S
sth_Weird Themenstarter:in
469 Beiträge seit 2007
vor 7 Jahren
Wie testet man ViewModels die in Views mit AttachedBehaviours (Eingabeformat) verwendet werden?

Hallo,

ich habe eine Anwendung mit MVVM-Pattern. Viele Eingaben in meinem View erfordern ein bestimmtes Format, z.B. nur Zahlenwerte, Texte die nur eine bstimmte Länge haben dürfen, Texte die nur in Großbuchstaben sein dürfen, Texte ohne Leer/Sonderzeichen etc.
Ich liebäugle hier mit einem AttachedBehaviour zur Eingabeprüfung, im Internet habe ich auch schon Beispiele gefunden (z.B. NumericTextBoxBehaviour), die ich gut auf meine Anforderungen anpassen könnte.
Ich frage mich nun aber, wie man so etwas testet. Teste ich nur das ViewModel, würde dieses ja Werte annehmen, die nicht gültig sind, da in der realen Umgebung der View die Werte durch das AttachedBehaviour abweisen würde. Andererseits, wenn ich die Prüfung im ViewModel nochmal implementiere, wozu dann überhaupt noch das AttachedBehaviour (die Prüfungen wären ja doppelt implementiert und das ganze damit sogar noch fehleranfällig).
Oder testet man in dem Fall das AttachedBehaviour einzeln und wenn das passt, dann testet man das ViewModel nur noch mit "guten" Eingaben, da man weiß, dass gar keine schlechten durchkommen?
Oder testet man beide in Kombination, d.h. man arbeitet im UnitTest mit ViewModel UND AttachedBehaviour und schickt einen neuen Wert erst an eine (evtl. statische) Prüffunktion im AttachedBehaviour, bevor man ihn an das ViewModel übergibt?

Gruß
sth_Weird

++++++++++++++++++++~+
Fluchen ist die einzige Sprache, die jeder Programmierer perfekt beherrscht


Linux is for free...if your time is worth nothing
++++++++++++++++++++~+

D
985 Beiträge seit 2014
vor 7 Jahren

Man testet das ViewModel so, wie man jedes ViewModel testet. Da gibt es keinen Unterschied.

So ein AttachedBehaviour macht die UI etwas mehr UserFriendly, weil völlig unsinnige Eingaben erst gar nicht zugelassen werden.

So ein NumericTextBoxBehaviour lässt einfach nur Ziffern als Eingabe zu und nun kann man bedenkenlos ein integer Property vom ViewModel daran binden.

Sinnvoll im Sinne des ViewModels sind aber z.B. nur Werte zwischen 6 und 42. Das kann aber eh nur das ViewModel prüfen.

S
sth_Weird Themenstarter:in
469 Beiträge seit 2007
vor 7 Jahren

Das mit dem Int ist aber ein sehr einfacher Fall...
Um mal etwas komplexeres zu nehmen, ich könnte ein AttachedBehaviour haben, das nur IP-Adressen oder GUIDs als Eingabe zulässt (angenommen das ViewModel würde diese als String anbieten).
Es ist eine komfortable Vorstellung, dass ich nur meinen Textboxen in den Views das AttachedBehaviour zuweisen muss und es werden nur gültige Eingaben erlaubt. In den ViewModels muss ich nichts weiter machen (es sei denn ich muss noch Dinge prüfen, die für dieses ViewModel spezifisch sind).

Es gibt neben AttachedBehaviours z.B. auch ValidationRules, welche man direkt im XAML verwenden kann und welche Eingaben prüfen können...das Problem müsste hier dasselbe sein - ich bekomme die Fehler nicht in mein ViewModel! Mir scheint manchmal, dass sich diese Mechanismen und das MVVM-Prinzip hier in die Quere kommen 😕

Gruß
sth_Weird

++++++++++++++++++++~+
Fluchen ist die einzige Sprache, die jeder Programmierer perfekt beherrscht


Linux is for free...if your time is worth nothing
++++++++++++++++++++~+

3.003 Beiträge seit 2006
vor 7 Jahren

Die ValidationRules sind einzelne Klassen, dein(e) ViewModel(s) sind einzelne Klassen. Testen musst du für ungültige Eingaben nur, ob die ValidationRules die Ergebnisse liefern, die sie liefern sollen. Weil sie sicherstellen, dass das ViewModel nur die (nach ihren Vorschriften) gültigen Werte bekommt, musst du dem VM keine ungültigen Werte unterschieben, wenn es du testest - bzw dich auf die Werte beschränken, die trotz ValidationRules noch ungültig werden können. Die mittels ValidationRules abgesicherten Nutzereingaben musst du nicht noch einmal im VM testen. Dafür sind dann die Integrations/UI-Tests da (kann ich etwas ungültiges eingeben? Verhält sich die Anwendung dann so, wie ich erwarte?).

Besagtes NumericTextBoxBehaviour halte ich für einen furchtbaren Anwendungsfall für AttachedBehaviours, denn WPF stellt genau für diesen Zweck eben schon Eingabevalidierungen zur Verfügung. Aber das ist meine persönliche Meinung.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

S
sth_Weird Themenstarter:in
469 Beiträge seit 2007
vor 7 Jahren

Besagtes NumericTextBoxBehaviour halte ich für einen furchtbaren Anwendungsfall für AttachedBehaviours, denn WPF stellt genau für diesen Zweck eben schon Eingabevalidierungen zur Verfügung. Aber das ist meine persönliche Meinung.

Also dieses NumericTextBoxBehaviour verwende ich, damit ich direkt Int-Properties im View anbinden kann. Gebe ich sonst einen String in eine TextBox ein, die mit einem Int-Property verbunden ist, dann fliegt ne Exception.
Als Work-Around im Netz steht, man könnte an ein String-Property binden und nur wenn die Eingabe gültig ist, den Wert auf das tatsächliche Int-Property schreiben. Da empfinde ich dann aber ein Behaviour (oder auch eine ValdiationRule) als elegantere Lösung...
Jetzt nach deinem Kommentar frage ich mich, von welchen (anderen?) Eingabevalidierungen du sprichst, die WPF schon zur Verfügung stellt (und ich evtl noch nicht kenne)???
Mir fiele zum Thema Eingabevalidierung nur noch das IDataError-Interface ein, welches ich auch bei mir implementiert habe für weiterführende Validierungen. Aber dieses kommt erst später zum Zug und fängt falsche Eingaben in meine (an ein Int-Property gebundene) TextBox nicht ab...

Aber danke schon mal für deine Rückmeldung zum Thema Testen. So hatte ich mir das auch gedacht - also dass man jede Komponente einzeln testet, ob sie das macht was sie soll, und sich dann darauf verlässt, dass sie im Einsatz in einem größeren System das richtige macht. Sonst wären größere Systeme wahrscheinlich auch garnicht testbar...

gruß
sth_Weird

++++++++++++++++++++~+
Fluchen ist die einzige Sprache, die jeder Programmierer perfekt beherrscht


Linux is for free...if your time is worth nothing
++++++++++++++++++++~+

D
985 Beiträge seit 2014
vor 7 Jahren

Nehmen wir mal an, wir haben ein VM wo wir einen TCP-Port erfassen wollen*Mit einer String-Property


public class FooVM
{
  public string Port { get; set; }
}

*Mit einer int Property


public class FooVM
{
  public int Port { get; set; }
}

In beiden Fällen muss das VM jedoch prüfen, ob der Wert gültig ist.*Kann der Port-Wert in ein int umgewandelt werden und ist dieser Wert innerhalb des gültigen Bereichs *Ist der Port-Wert innerhalb des gültigen Bereichs

Im Fall b. obliegt die Prüfung der direkten Eingabe der View (z.B. mit dem AttachedBehaviour). Ansonsten ist die Prüfung aber inhaltlich völlig gleich (Prüfung auf den gültigen Bereich).

Das VM implementiert dann noch IDataErrorInfo und man kann den Test quasi automatisieren.

Für einen UnitTest des VM ist so ein AttachedBehaviour völlig uninteressant, weil ob das wirklich an dem Control/View hängt, kann man aus der Sicht des VM nicht sehen. Also einfach testen und gut.

3.003 Beiträge seit 2006
vor 7 Jahren

So hatte ich mir das auch gedacht - also dass man jede Komponente einzeln testet, ob sie das macht was sie soll, und sich dann darauf verlässt, dass sie im Einsatz in einem größeren System das richtige macht. Sonst wären größere Systeme wahrscheinlich auch garnicht testbar...

Ich bin sicher, du meinst das auch so, aber nur vorsichtshalber: wenn die Komponententests laufen, ist man mit dem Testen natürlich noch nicht fertig. Integrationstests, manuelle Tests, Bananaware-Tests durch den Kunden 😄 usw.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)