ユニットテスト実行時にローカルサーバを立てることで外部に依存しないテストを行うことができる。
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におけるsetUp
とtearDown
がそれぞれに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)さん、参考にさせて頂きました