5
6

More than 3 years have passed since last update.

Pytestでローカルに一時的なhttpサーバを起動する

Last updated at Posted at 2020-01-18

ユニットテスト実行時にローカルサーバを立てることで外部に依存しないテストを行うことができる。

APIやクローラ開発で便利。

流れはこんな感じ

  • conftest.pyにフィクスチャとしてhttpサーバの起動/終了処理を記述
  • テスト関数の中でフィクスチャを呼び出す

実装

  • conftest.py
conftest.py
import pytest
from http.server import (
    HTTPServer as SuperHTTPServer,
    SimpleHTTPRequestHandler
)
import threading


class HTTPServer(SuperHTTPServer):
    """
    ThreadでSimpleHTTPServerを動かすためのラッパー用Class.
    Ctrl + Cで終了されるとThreadだけが死んで残る.
    KeyboardInterruptはpassする.
    """
    def run(self):
        try:
            self.serve_forever()
        except KeyboardInterrupt:
            pass
        finally:
            self.server_close()


@pytest.fixture()
def http_server():
    host, port = '127.0.0.1', 8888
    url = f'http://{host}:{port}/index.html'
    # serve_forever をスレッド下で実行
    server = HTTPServer((host, port), SimpleHTTPRequestHandler)
    thread = threading.Thread(None, server.run)
    thread.start()
    yield url  # ここでテストに遷移
    # スレッドを終了
    server.shutdown()
    thread.join()

yield文でテスト関数に制御を移す。
unittestにおけるsetUptearDownがそれぞれにyield文の前後あたる。

実行ディレクトリにコンテンツを配置しておく。

index.html
<html>Hello pytest!</html>

テスト関数でフィクスチャ(http_server)を利用する

  • test_httpserver.py
test_httpserver.py
import requests


def test_index(http_server):
    url = http_server
    response = requests.get(url)
    assert response.text == '<html>Hello pytest!</html>'

実行結果

$ pytest --setup-show test_httpserver.py
========================================= test session starts =========================================platform linux -- Python 3.8.1, pytest-5.3.3, py-1.8.1, pluggy-0.13.1
rootdir: /home/skokado/workspace/sandbox
collected 1 item

test_httpserver.py
        SETUP    F http_server
        test_httpserver.py::test_index (fixtures used: http_server).
        TEARDOWN F http_server

========================================== 1 passed in 0.60s ==========================================

--setup-showオプションをつけることでフィクスチャの生成をトレースできる。
test_index関数でフィクスチャhttp_serverが使用されているのがわかる。

その他

ばんくし(@vaaaaanquish)さん、参考にさせて頂きました

参考 - Pythonのhttp.serverを利用してWebスクレイピングのunittestを書く

5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6