JavaScript ist eine dynamische Sprache, die ihre starke Leistungsfähigkeit verleiht, aber auch den Compiler unmöglich macht, Entwicklern Hilfe zu leisten. Aus diesem Grund sind wir der Ansicht, dass das Schreiben eines JavaScript -Codes eine leistungsstarke und vollständige Reihe von Tests haben muss. Angular verfügt über viele Funktionen, die es uns erleichtern, unsere Anwendungen zu testen. Wir sollten keine Entschuldigung haben, keine Tests zu schreiben (das ist es ...).
1. Es geht darum, keine Bedenken zu mischen (es geht darum, dass die Code -Beziehung kompliziert wird ...)
Bei Unit -Tests wie der Name geht es darum, eine einzelne "Einheit" zu testen. Unit -Tests bemühen sich, diese Fragen zu beantworten: Bin ich in meinen logischen Überlegungen bereits korrekt? Sind die Ergebnisse nach der Sortiermethode korrekt? Um diese Fragen zu beantworten, ist es besonders wichtig, sie zu trennen. Dies liegt daran, dass wir uns bei Testen der Sortiermethode nicht um andere verwandte Fragmente wie DOM -Elemente kümmern oder XHR -Anfragen zum Abrufen von Daten usw. initiieren. Offensichtlich ist es normalerweise schwierig, eine Funktion in einem typischen Projekt getrennt zu bezeichnen. Was dieses Problem verursacht, ist, dass Entwickler häufig Beziehungen kompliziert machen und am Ende ein Snippet so aussehen lassen, als ob es alles kann. Es erhält die Daten über XHR, sortiert die Daten und manipuliert dann die DOM. Zusammen mit Angular können wir einen besseren Code leichter schreiben, sodass Angular eine Abhängigkeitsinjektion von XHR (die wir simulieren können) und Angular auch Abstraktionen erzeugt, die es uns ermöglichen, das Modell zu sortieren, ohne das DOM manipulieren zu müssen. Am Ende können wir also einfach eine Sortiermethode schreiben und dann einen Datensatz über den Testfall erstellen, damit die Sortiermethode beim Testen verwendet werden soll, und dann feststellen, ob das Ergebnismodell die Erwartungen erfüllt. Der Test muss nicht darauf warten, dass XHR das entsprechende DOM erstellt und feststellt, ob die Funktion das DOM korrekt betreibt. Die Kernidee von Angular beinhaltet die Testbarkeit von Code, erfordert aber auch, dass wir das Richtige tun. Angular ist verpflichtet, den Weg zu vereinfachen, das Richtige zu tun, aber Angular ist keine Magie, was bedeutet, dass wir möglicherweise eine nicht testbare Anwendung haben, wenn wir nicht den folgenden Punkten folgen.
1. Abhängigkeitsinjektion
Es gibt viele Möglichkeiten, die Abhängigkeitsressourcen zu erhalten: 1) Wir können den neuen Bediener nutzen; 2) Wir verwenden eine bekannte Methode namens "Global Singleton"; 3) Wir können es vom Registrierungsdienst anfordern (aber wie erhalten wir eine Registrierung? Sie können die folgenden Kapitel überprüfen); 4) Wir können erwarten, dass es bestanden wird.
Lassen Sie uns von den oben aufgeführten Methoden nur der letzte prüfbar sehen, warum:
1) Verwenden des neuen Bedieners
Grundsätzlich gibt es keine Fehler bei der Verwendung des neuen Operators, aber das Problem ist, dass das Aufrufen des Konstruktors über New den Anrufer dauerhaft an den Typ binden. Zum Beispiel versuchen wir, ein XHR -Objekt zu instanziieren, damit wir einige Daten vom Server abrufen können.
Funktion myclass () {this.dowork = function () {var xhr = new XRH (); xhr.open (Methode, URL, TRUE); xhr.onReadyStatechange = function () {…}; xhr.send (); }}Das Problem ist, dass wir beim Testen normalerweise ein virtuelles XHR instanziieren müssen, mit dem Testdaten oder Netzwerkfehler zurückgegeben werden können. Indem wir neue XHR () anrufen, binden wir das echte XHR dauerhaft und es gibt keine gute Möglichkeit, es zu ersetzen. Natürlich gibt es ein schlechtes Mittel und es gibt viele Gründe zu beweisen, dass es eine schlechte Idee ist:
var oldxhr = xhr; xhr = new MockxHr () {}; myclass.dowork (); // Beurteilen Sie, ob MockxHr XHR = oldxHR durch normale Parameter ruft; // Wenn Sie diesen Schritt vergessen, ist es leicht, traurige Dinge zu verursachen.2) Globale Suche
Eine andere Möglichkeit, das Problem zu lösen, besteht darin, die Abhängigkeitsressourcen an einem bekannten Ort zu erhalten.
Funktion myclass () {this.dowork = function () {global.xhr ({…}); };}Ohne eine Instanz eines neuen abhängigen Objekts zu erstellen, ist das Problem im Grunde genommen das gleiche wie neu, und es gibt keine gute Möglichkeit, Global.xHR beim Testen abzufangen. Das grundlegendste Problem bei der Prüfung ist, dass globale Variablen geändert werden müssen, um virtuelle Methoden aufzurufen und geändert werden. Weitere Informationen zu seinen Nachteilen finden Sie hier: http://misko.hevery.com/code-reviewer-guide/flaw-britle-global-state-singletons/
Der obige Code ist schwer zu testen, daher müssen wir den globalen Zustand ändern:
var oldxhr = global.xhr; global.xhr = function mockxhr () {…}; var myclass = new myclass (); // beurteilen, ob mockxhr global.xhr = oldxhr durch normale Parameter; // Wenn Sie diesen Schritt vergessen, sind es einfach, traurige Dinge zu verursachen.3) Dienstregister
Eine Registrierung mit allen Diensten scheint das Problem zu lösen und dann den erforderlichen Dienst im Testcode zu ersetzen.
Funktion myclass () {var serviceregistry = ???; this.dowork = function () {var xhr = serviceregistry.get ("xhr"); …};}Aber woher kommt der Serviceregistry? Wenn es sich: * Neu-Ed-up befindet, hat der Test keine Chance, die Dienste zum Testen zurückzusetzen.
Ändern Sie nach dieser Methode die obige Klasse mit der folgenden Methode:
var oldservicelocator = global.servicelocator; global.servicelocator.set ('xhr', function mockxhr () {}); var myclass = new myclass (); myclass.dowork (); //, ob MockxHr Global.servicelocator = OldServicelocator; // Wenn Sie diesen Schritt vergessen, ist es leicht, traurige Dinge zu verursachen.4) Abhängigkeiten vorhanden
Schließlich können Abhängigkeitsressourcen übergeben werden.
Funktion myClass (xhr) {this.dowork = function () {xhr ({…}); };}Dies ist die bevorzugte Methode, da der Code weder darauf achten muss, woher XHR stammt, und es interessiert sich auch nicht, wer das übergebene XHR erstellt hat. Daher kann der Schöpfer der Klasse getrennt vom Klassenverbraucher codiert werden, was die Verantwortung der Erstellung von der Logik trennt, was eine Übersicht über die Abhängigkeitsinjektion ist.
Diese Klasse ist leicht zu testen und wir können sie im Test so schreiben:
Funktion xhrmock (args) {…} var myclass = new MyClass (xhrmock); myclass.dowrok (); // Machen Sie einige Urteile ... Durch diesen Testcode können wir erkennen, dass keine globalen Variablen beschädigt werden.Abhängigkeitsinjektion (//www.vevb.com/article/91775.htm), das in dieser Weise mit Angular enthalten ist, erleichtert das Schreiben von Testcode. Wenn wir Code schreiben möchten, der sehr prüfbar ist, sollten wir ihn besser verwenden.
2. Controller
Logik macht jede Anwendung einzigartig, und das möchten wir testen. Wenn unsere Logik mit DOM -Operationen gemischt wird, ist dies genauso schwer zu testen wie das folgende Beispiel:
Funktion passwordcontroller () {// Erhalten Sie eine Referenz auf das DOM -Objekt var msg = $ ('. Ex1 span'); var input = $ ('. ex1 input'); var Stärke; this.grad = function () {msg.removeclass (Stärke); var pwd = input.val (); password.text (pwd); if (pwd.length> 8) {streng = 'strong'; } else if (pwd.length> 3) {streng = 'medium'; } else {streng = 'w geblust'; } msg.addClass (Stärke) .Text (Stärke); }}Der obige Code tritt beim Testen auf Probleme auf, da wir bei der Ausführung des Tests die richtige DOM haben müssen. Der Testcode ist wie folgt:
var input = $ ('<Eingabe type = "text"/>'); var span = $ ('<span>'); $ ('body'). Passwartcontroller (); input.val ('ABC'); pc.grad (); erwartete (span.text ()). Tequal ('schwach'); $ ('Körper'). Html ('');In Angular trennt der Controller die DOM -Betriebslogik streng, wodurch die Schwierigkeit des Schreibens von Testfällen stark verringert wird. Schauen Sie sich das folgende Beispiel an:
Funktion passwordCntrl ($ scope) {$ scope.password = ''; $ scope.grad = function () {var size = $ scope.password.length; if (size> 8) {$ scope.Strength = 'strong'; } else if (size> 3) {$ scope.Strength = 'medium'; } else {$ scope.Strength = 'Wew'; }};}Der Testcode ist unkompliziert:
var pc = new PasswordController ($ scope); PC.Password ('ABC'); pc.grad (); erwartete ($ scope.Strength) .toEqual ('schwach');Es ist erwähnenswert, dass der Testcode nicht nur diskontinuierlicher ist, sondern auch einfacher zu verfolgen ist. Wir haben immer gesagt, dass Testfälle Geschichten erzählen und andere irrelevante Dinge nicht beurteilen.
3. Filter
Filter (http://docs.angularjs.org/api/ng.$filter) wird verwendet, um Daten in ein benutzerfreundliches Format umzuwandeln. Sie sind wichtig, da sie die Verantwortung für die Konvertierung von Formaten von der Anwendungslogik trennen und die Anwendungslogik weiter vereinfachen.
MYMODULE.FILTER ('Länge', function () {return function (text) {return (''+(text || ''). Länge;}}); var länge = $ filter ('länge'); erwarten (länge (null)). toequal (0); erwarten ('abc').4. Richtlinien
5. Mocks
6. Globale staatliche Isolation
7. Bevorzugte Testweise
8. JavaScriptTestDriver
9. Jasmine
10. Beispielprojekt
Wir werden in Zukunft weiterhin verwandte Artikel aktualisieren. Vielen Dank für Ihre Unterstützung für diese Seite!