HTTPクライアントの単体テスト
HTTPクライアントとして書いたプログラムから、リクエストが正しく出ているか、またサーバから受け取ったデータを正しく処理できるか、テストコードとして書きたい場合があります。
もちろんlocalhostでHTTPサーバを立ち上げて結合テストを行うことも考えられますが、プロジェクトの進捗として必ずしもHTTPサーバ側のコードが先に完成しているとは限りませんし、HTTPクライアントだけで単体テスト可能になっていた方が嬉しいことが多いはずです。
ここでは偽のソケットを作ってHTTPクライアントが正しく動作しているか確認するコードを書いてみます。
PyUnitなどでテストを書く場合、httplib.HTTP._connection_classを書き換える部分はsetUp/tearDownメソッドに書いて、sendbuf/recvbufはテストメソッドごとに用意するのがいいかもしれません。
# -*- coding: utf-8 -*- from StringIO import StringIO import httplib from urllib import URLopener ## 送受信内容をトラップする偽ソケット class FakeSocket: sendbuf = None recvbuf = None def close(self): pass def sendall(self, data): self.sendbuf.write(data) def makefile(self, mode, bufsize): return self.recvbuf ## HTTP接続をFakeSocketに差し替える class FakeHTTPConnection(httplib.HTTPConnection): def connect(self): self.sock = FakeSocket() httplib.HTTP._connection_class = FakeHTTPConnection ## FakeSocketクラス変数にバッファをセット FakeSocket.sendbuf = StringIO() FakeSocket.recvbuf = StringIO('aaaaaaaaaaaaaaaaaaaaaa') ## urllibを使うが本当のHTTPリクエストは送信されない u = URLopener() f = u.open('http://server/path/file') ## recvbufの内容がリスポンスとして返されている assert f.read() == 'aaaaaaaaaaaaaaaaaaaaaa' ## リクエスト内容はsendbufに保存されている assert FakeSocket.sendbuf.getvalue() == 'GET /path/file HTTP/1.0\r\nHost: server\r\nUser-agent: Python-urllib/1.16\r\n\r\n' ## HTTP接続を通常のソケットに戻す httplib.HTTP._connection_class = httplib.HTTPConnection