2016-02-22 7 views
6

Ich möchte versuchen, Code nach TDD-Praxis zu schreiben. Ich möchte eine einfache App basierend auf dem Tornado-Framework von Python erstellen. Ich war auf der Suche über das Internet, wie Menschen Tests für Tornado schreiben und fand etwas wie folgt aus:Wie schreibt man Komponententests für Python Tornado-Anwendung?

class TestSomeHandler(AsyncHTTPTestCase): 
    def test_success(self): 
     response = self.fetch('/something') 
     self.assertEqual(response.code, 200) 

mich korrigieren, wenn ich falsch, aber es sieht eher wie Integrationstests. Stattdessen versuche ich einen einfachen Komponententest für einen Dummy-Handler zu schreiben. Zum Beispiel so ein:

class SomeHandler(BaseHandler): 
    @gen.coroutine 
    def get(self): 
     try: 
      from_date = self.get_query_argument("from", default=None) 
      datetime.datetime.strptime(from_date, '%Y-%m-%d') 
     except ValueError: 
      raise ValueError("Incorrect argument value for from_date = %s, should be YYYY-MM-DD" % from_date) 

Und Test würde wie folgt aussehen:

class TestSomeHandler(AsyncHTTPTestCase): 

    def test_no_from_date_param(self): 
     handler = SomeHandler() 
     with self.assertRaises(ValueError): 
      handler.get() 

Ich weiß, dass ich bei get() Anwendung und Anforderung verpassen. Noch nicht behandelt, wie man sie erstellt.

Aber meine Frage ist, schreiben Menschen Tests für Tornado wie im ersten Beispiel oder jemand ruft Handler innerhalb der App? Welches Muster soll folgen? Es wäre schön, wenn jemand relevanten Code zum Teilen hätte.

Antwort

4

Das Muster mit AsyncHTTPTestCase wird hauptsächlich verwendet, weil es alle Anforderungssachen für Sie macht. Natürlich kann man AsyncTestCase verwenden und manuell handhaben.

Beispiel für AsyncTestCase. Da es get Methode testen wird, die Coroutine ist, werden wir gen_test verwenden, um es ein bisschen einfacher zu machen. RequestHandler erfordert Application und HTTPRequest Objekte. Da wir die Einstellungen der App nicht weiterleiten, ist ui_methods usw. Application ein einfacher Spott.

from tornado.testing import AsyncTestCase, gen_test 
from tornado.web import Application 
from tornado.httpserver import HTTPReuqest 
from unittest.mock import Mock 

class TestSomeHandler(AsyncTestCase): 

    @gen_test 
    def test_no_from_date_param(self): 
     mock_application = Mock(spec=Application) 
     payload_request = HTTPRequest(
      method='GET', uri='/test', headers=None, body=None 
     ) 
     handler = SomeHandler(mock_applciation, payload_request) 
     with self.assertRaises(ValueError): 
      yield handler.get() 

IMHO ist es an Ihnen, welches Muster zu verwenden. Ich wähle AsyncHTTPTestCase für http-Verb Methoden (get, Post usw.), denn:

  • es einfacher ist,
  • Verbraucher dieser Methode ist, HTTP-Client, so behauptet Antwortcode, Körper sehr viel Sinn machen
  • es verhindert, dass die über komplizierten Methoden

natürlich Rest Methoden mit AsyncTestCase getestet absetzen.

+0

Wie ich verstehe, ist ein solcher Fluss nicht vorzuziehen. Aber in anderen Fällen kann ich keine Ausnahmen testen. –

+0

@viakondratiuk der Verbraucher der Methode ist einige http-Client (Benutzer), jede Ausnahme, die Sie ausgelöst haben, ist es nur 50x mit einer Nachricht, wahrscheinlich Interner Fehler. Es ist okay? Ich denke nicht - es zeigt eine schlechte Fehlerbehandlung, versucht "Return" bedeutungsvolle Fehler zurückzugeben (sogar eine vereinheitlichte Nachricht) und weitere Serviceaufrufe und Debugging werden viel einfacher zu nehmen sein. – kwarunek

1

AsyncHTTPTestCase ist für Tests wie Ihr erstes Beispiel mit self.fetch konzipiert, anstatt Handler direkt instanziieren.

RequestHandler nicht ohne die Verwendung eines Application von Hand instanziiert werden entworfen, also wenn Sie Stücke von Funktionalität haben, die Sie bevorzugen würde, ohne die volle HTTP-Stack zu testen, sollte dieser Code im Allgemeinen in statischen Funktionen oder nicht sein RequestHandler Klassen.

+0

Also, wie ich es verstehe, sollte ich Handler mit 'AsyncHTTPTestCase' und anderem Code testen, der Ausnahmen auslösen kann und so weiter, ich sollte es isolieren und separat testen? –

+0

Ja. Die Trennlinie liegt bei Ihnen: Für das hier angegebene Ausnahmebeispiel würde ich das persönlich über HTTP testen und überprüfen, ob es den richtigen Statuscode und die Fehlermeldung anstelle des Ausnahmetyps erzeugt. –

Verwandte Themen