I tried the Python Tornado Testing Framework

I was wondering if Unittest or Pytest would be enough, but I decided to check out Tornado's Testing Framework. I found that it would be helpful to start Tornado HTTPServer in a test script and call it Tornado Mock Server, or to run and test it, so I decided to implement and test it immediately. .. I decided to put together a sample code as a memorandum at that time. Since I tried 2.4 series this time, the information may be a little out of date, but the basics should not change.

Sample code

test_tornadoweb.py


#!/usr/bin/env python
# -*- coding: utf-8 -*-

#Import required modules
import tornado.testing
import tornado.web
import mock
import urllib
from tornado.httpclient import HTTPRequest

#Helper function
def urlencode_request_params(**params):
    return urllib.urlencode(
        dict(
            [k, v.encode("utf-8") if isinstance(v, unicode) else v]
            for k, v in params.items()
        )
    )

def prepare_kwargs(**params):
    kwargs = dict(
        body=urlencode_request_params(**params),
    )
    return kwargs

#Sample handler
class ProfileHandler(tornado.web.RequestHandler):
    """To try get method
    """
    def get(self):
        user_id = self.get_argument("user_id")
        if user_id != "tornadoweb":
            raise tornado.web.HTTPError(404)
        self.finish("ok")

class AccountHandler(tornado.web.RequestHandler):
    """tornado.web.Tests when using authenticated decorators
Things to do
    """
    @tornado.web.authenticated
    def get(self):
        self.finish("I'm " + self.current_user)

    @tornado.web.authenticated
    def post(self):
        bio = self.get_argument("bio")
        self.finish("{error:0, msg:{bio:%s}}" % bio)

class TestSample(tornado.testing.AsyncHTTPTestCase):
    """Inherit AsyncHTTPTestCase and start HTTP Server
    """
    def setUp(self):
        """Find a free port in the super class get_Registered in app
Starting Tornado with handler as Application

        self.http_client is prepared and self.http_client.fetch()
Can also be used
        """
        super(TestSample, self).setUp()

    def get_httpserver_options(self):
        """You can also specify options when starting the HTTP server
        """
        return {}

    def get_app(self):
        """Set the routing of the application handler.
If you have application settings, you can specify them here.
        """
        application_settings = dict()
        return tornado.web.Application([
            ("/profile", ProfileHandler),
            ("/account", AccountHandler),
            ("/account/update", AccountHandler),
        ], **application_settings)

    def test_httprequest_sample(self):
        """You can also make a request directly using HTTPRequest, so a trial test
        """
        kwargs = dict()
        test_url = 'http://snapdish.co'
        request = HTTPRequest(test_url, **kwargs)
        self.http_client.fetch(request, self.stop, **kwargs)
        response = self.wait()
        self.assertEqual(response.code, 200)

    def test_profile(self):
        """Test if you can get the profile normally
        """
        kwargs = dict(
            user_id="tornadoweb"
        )
        path = "%s?%s" % ("/profile", urlencode_request_params(**kwargs))
        response = self.fetch(path)
        self.assertEqual(response.code, 200)
        self.assertEqual(response.body, "ok")

    def test_profile_404(self):
        """Test if profile request is returning 404 if wrong
        """
        kwargs = dict(
            user_id="tornadoweb?"
        )
        path = "%s?%s" % ("/profile", urlencode_request_params(**kwargs))
        response = self.fetch(path)
        self.assertEqual(response.code, 404)

    def test_account(self):
        """When using authenticated decorators, use mock
        current_user needs to be modified"""
        with mock.patch.object(AccountHandler, 'get_current_user') as m:
            m.return_value = "tornadoweb"
            path = "/account"
            response = self.fetch(path)
        self.assertEqual(response.code, 200)
        self.assertEqual(response.body, "I'm tornadoweb")

    def test_account_update(self):
        """When using authenticated decorators, use mock
        current_user needs to be modified"""
        with mock.patch.object(AccountHandler, 'get_current_user') as m:
            m.return_value = "tornadoweb"
            bio = "tornadoweb bio"
            params = dict(bio=bio)
            response = self.fetch("/account/update",
                                  method="POST",
                                  follow_redirects=False,
                                  body=urlencode_request_params(**params))
        self.assertEqual(response.code, 200)
        self.assertEqual(response.body, "{error:0, msg:{bio:%s}}" % bio)

memorandum

setUp() It works by searching for a free port, preparing http_client, setting an application handler, and starting Tornado HTTPServer. get_app() It is implemented on the subclass side, and specifies the handler you want to test and its path. You can also set up the application here. Specify template_path etc. fetch(path, **kwargs)

self.http_client.In a wrapper for fetch and self inside.get_url(path)I am doing. self.get_url(path)Will use the path passed as an argument to generate a url to the HTTPServer started in this test and execute the request. When you want to make a complicated request, self.http_client.fetch(request, self.stop, **kwargs)Handle requests directly using. At that time, the response is self.wait()To get using.


## tornado.web.authenticated decorators are not supported
 It seems that there is no choice but to cheat using mock or cheat cookies. You can also do it using HTTPRequest, so you can do various things depending on the implementation.
## Command line execution
 Specify the module name (file name) as follows and execute.

```bash
$ python -m tornado.test.runtests test_tornadoweb

reference

https://github.com/tornadoweb/tornado/tree/master/tornado/test http://www.tornadoweb.org/en/branch2.4/testing.html

Recommended Posts

I tried the Python Tornado Testing Framework
Python: I tried the traveling salesman problem
I tried Python> autopep8
I tried Python> decorator
I tried "smoothing" the image with Python + OpenCV
[Python] I tried substituting the function name for the function name
vprof --I tried using the profiler for Python
I tried "differentiating" the image with Python + OpenCV
I tried simulating the "birthday paradox" in Python
I tried the least squares method in Python
I tried python programming for the first time.
Try using the Python web framework Tornado Part 1
I tried "binarizing" the image with Python + OpenCV
I tried using the Datetime module by Python
Try using the Python web framework Tornado Part 2
I tried fp-growth with python
I tried to graph the packages installed in Python
[Trainer's Recipe] I touched the flame of the Python framework.
I tried Python on Mac for the first time.
I tried to touch the CSV file with Python
I tried python on heroku for the first time
I tried the changefinder library!
[Python] I tried to graph the top 10 eyeshadow rankings
I tried Python C extension
[Python] I tried using OpenPose
I tried to solve the problem with Python Vol.1
I tried gRPC with Python
I tried scraping with python
I tried hitting the API with echonest's python client
I tried to summarize the string operations of Python
I tried to find the entropy of the image with python
I tried "gamma correction" of the image with Python + OpenCV
I tried to simulate how the infection spreads with Python
I tried the accuracy of three Stirling's approximations in python
I tried using the Python library from Ruby with PyCall
I tried face recognition from the video (OpenCV: python version)
I tried programming the chi-square test in Python and Java.
I tried to implement the mail sending function in Python
Miscellaneous notes that I tried using python for the matter
I tried to enumerate the differences between java and python
I tried changing the python script from 2.7.11 to 3.6.0 on windows10
I tried to divide the file into folders with Python
I tried the TensorFlow tutorial 1st
I tried the Naro novel API 2
I tried web scraping with python.
I tried the TensorFlow tutorial 2nd
I tried using Thonny (Python / IDE)
I tried Grumpy (Go running Python).
I liked the tweet with python. ..
I wrote the queue in Python
I tried the Naruro novel API
I tried running prolog with python 3.8.2.
I tried Line notification in Python
I tried SMTP communication with Python
I tried to move the ball
I tried using the checkio API
[Python] I tried using YOLO v3
I wrote the stack in Python
I tried to estimate the interval.
I tried to solve the ant book beginner's edition with python
I tried running the Python Package Repository (Warehouse) that supports PyPI