久しぶりのブログになってしまいました。
開発チームのエンジニア、片岡です。
今回は、ユニットテストにおける時間の問題についてのTipsです。
ユニットテストを行う際に手間のかかる作業として、テスト用環境の構築があります。
今はDockerがあるのでかなり手間が減りました。
ユニットテストは何度やっても同じテストができて、同じ結果になることが重要ですが、その際に問題となるのはシステム日時です。
「今日」とか「今月」などの日付・時刻によって返す結果が変わる処理があった場合にどうやって環境を設定しておけばよいか。
Docker Composeとlibfaketimeを使ってシステム日時を固定することができます。
以下、PythonのWebフレームワークであるDjangoをサンプルとして方法を紹介します。
他の言語、フレームワークでも基本は同じになります。
1. Dockerfileでlibfaketimeをインストール
Dockerfile
FROM python:3 ENV PYTHONUNBUFFERED 1 # テスト時にシステム時刻を固定化するためのlibfaketimeをインストール WORKDIR / RUN git clone https://github.com/wolfcw/libfaketime.git WORKDIR /libfaketime/src RUN make install RUN mkdir /code WORKDIR /code ADD requirements.txt /code/ RUN pip install -r requirements.txt ADD . /code/
2. docker-compose.ymlで環境変数FAKETIMEに固定したい日時を指定
起動すると、コンテナ上の日時が固定された状態になります。
docker-compose.yml
version: '3' services: db: image: postgres environment: POSTGRES_PASSWORD: postgres web: build: . command: python3 manage.py runserver 0.0.0.0:8000 environment: # この2行で日時を設定 - LD_PRELOAD=/usr/local/lib/faketime/libfaketime.so.1 - FAKETIME=2021-04-24 10:30:00 volumes: - .:/code ports: - "8000:8000" depends_on: - db
3. アプリケーション上での確認
views.py (Djangoチュートリアルより)
from django.http import HttpResponse from datetime import datetime def index(request): return HttpResponse(f"Hello, world. " f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
のようにして、現在日時を表示してみると以下のようにdocker-compose.ymlで設定した日時が表示されます。(何度やっても同じ結果)
備考
後から環境変数FAKETIMEを変更することで、コンテナ的にはシステム日時を変更することができます。
# date Sat Apr 24 10:30:00 UTC 2021 # export FAKETIME="2021-08-22 12:50:33" # date Sun Aug 22 12:50:33 UTC 2021
ただ、Djangoとしては再起動まで反映されません。
エンジニア募集中
TVISION INSIGHTSでは、エンジニアを大募集中です。
ビッグデータを活用した自社サービスの開発に取り組む環境があります。
Python/Django/TypeScript/Angular/Docker/AWSの経験があるエンジニアの方、是非一度下記サイトをご覧ください。