🧭
Testinfraを使用したDockerコンテナのテスト
概要
インフラのテストツールであるTestinfraを使用して、Dockerコンテナのテストをしてみました。
docker execしてDockerコンテナにログインし、テストするイメージです。
環境
% python3 --version
Python 3.9.1
% pip list | grep -e ^pytest-testinfra
pytest-testinfra 6.8.0
% docker --version
Docker version 20.10.17, build 100c701
Docker環境の準備
DockerはMacにDocker Desktopをインストールして使用します。
インストール方法は割愛。
テスト用のDockerイメージ取得
Docker Desktopを起動して、Dockerイメージを取得します。
% docker pull docker/getting-started
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker/getting-started latest cb90f98fd791 5 months ago 28.8MB
DockerコンテナのOSリリース番号取得
Dockerコンテナにログインし、OSのリリース番号を確認します。
この後の工程では、このOSのリリース番号を確認するテストをします。
% docker run -d docker/getting-started
% docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
416f3f16f8db docker/getting-started "/docker-entrypoint.…" 7 seconds ago Up 6 seconds 80/tcp interesting_dirac
% docker exec -it 416f3f16f8db /bin/sh
# uname -r
5.10.124-linuxkit
# exit
ホスト側のOSリリース番号はこちら。
% uname -r
21.6.0
Testinfraのインストール
pythonの仮想環境にTestinfraをインストールします。
% python3 -m venv testinfra
% cd testinfra
% source bin/activate
% pip install pytest-testinfra
テスト定義ファイル作成
基本的に公式サイトに掲載されている例のままです。。。
% mkdir tests
% cd tests
% vi test.py
test.pyの中身はこちら。
ちゃんとDockerコンテナで実行されていれば、test_myimage01が成功し、test_myimage02が失敗します。
test.py
import pytest
import subprocess
import testinfra
@pytest.fixture(scope='session')
def host(request):
docker_id = subprocess.check_output(['docker', 'run', '-d', 'docker/getting-started']).decode().strip()
yield testinfra.get_host("docker://" + docker_id)
subprocess.check_call(['docker', 'rm', '-f', docker_id])
def test_myimage01(host):
assert host.check_output('uname -r') == '5.10.124-linuxkit'
def test_myimage02(host):
assert host.check_output('uname -r') == '21.6.0'
Testinfraの実行
DockerコンテナはTestinfra実行時に自動で起動・終了されるので、Docker Desktopが起動していれば実行できます。
失敗したテストは、テスト結果として想定していた内容と実際の内容が出力されます。
% py.test -v test.py
=========================================== test session starts ============================================
platform darwin -- Python 3.9.1, pytest-7.1.3, pluggy-1.0.0 -- /Users/hoge/testinfra/bin/python3
cachedir: .pytest_cache
rootdir: /Users/hoge/testinfra/tests
plugins: testinfra-6.8.0
collected 2 items
test.py::test_myimage01 PASSED [ 50%]
test.py::test_myimage02 FAILED [100%]
================================================= FAILURES =================================================
______________________________________________ test_myimage02 ______________________________________________
host = <testinfra.host.Host docker://9939579997d7c570444f27d3ed42e8f3944c53e0a7fc525385e4b377b50a93c3>
def test_myimage02(host):
> assert host.check_output('uname -r') == '21.6.0'
E AssertionError: assert '5.10.124-linuxkit' == '21.6.0'
E - 21.6.0
E + 5.10.124-linuxkit
test.py:15: AssertionError
----------------------------------------- Captured stdout teardown -----------------------------------------
9939579997d7c570444f27d3ed42e8f3944c53e0a7fc525385e4b377b50a93c3
========================================= short test summary info ==========================================
FAILED test.py::test_myimage02 - AssertionError: assert '5.10.124-linuxkit' == '21.6.0'
======================================= 1 failed, 1 passed in 1.75s ========================================
JUnit形式での出力
JUnit形式のXMLを出力することもできます。
% mkdir ../reports
% py.test --junit-xml=../reports/test_report.xml test.py
=========================================== test session starts ============================================
platform darwin -- Python 3.9.1, pytest-7.1.3, pluggy-1.0.0
rootdir: /Users/hoge/testinfra/tests
plugins: testinfra-6.8.0
collected 2 items
test.py .F [100%]
================================================= FAILURES =================================================
______________________________________________ test_myimage02 ______________________________________________
host = <testinfra.host.Host docker://cbc7c2431ad7fe545ae553c81907954f3954f1c208f4e7136195d31696b7d607>
def test_myimage02(host):
> assert host.check_output('uname -r') == '21.6.0'
E AssertionError: assert '5.10.124-linuxkit' == '21.6.0'
E - 21.6.0
E + 5.10.124-linuxkit
test.py:15: AssertionError
----------------------------------------- Captured stdout teardown -----------------------------------------
cbc7c2431ad7fe545ae553c81907954f3954f1c208f4e7136195d31696b7d607
--------------------- generated xml file: /Users/hoge/testinfra/reports/test_report.xml ---------------------
========================================= short test summary info ==========================================
FAILED test.py::test_myimage02 - AssertionError: assert '5.10.124-linuxkit' == '21.6.0'
======================================= 1 failed, 1 passed in 1.77s ========================================
% file ../reports/test_report.xml
../reports/test_report.xml: XML 1.0 document text, ASCII text, with very long lines (567)
Discussion