背景
PythonからPostgreSQLにアクセスする処理のテストをpytestで記述した。これをGithub ActionsのCIに組み込みたい。
環境
- Python 3.8
ディレクトリ構成は以下。
my-repository
├── app
│ ├── my_module.py
│ └── tests
│ └── test_my_module.py
└── .github
└── workflows
└── psql-ci.yml
実装
早速だが実装例。
テストコード
pytestを使った以下のようなテストがあることを想定する。
pytestの詳細な説明は他に譲るとしてざっくりと何をやっているかを書いておく。
-
setup_and_teardown_psql
-
yield
より前: データの準備。テーブルの作成とdata/init_data.csv
ファイルに記述された初期データのinsertを行う。この処理はテストケースの実行前に行われる。 -
yield
より後: テスト用に作ったテーブルを削除する
-
-
test_my_function
- PostgreSQLに接続して何かしらする関数のテストを行う。
from pathlib import Path, PurePath
import psycopg2
import pytest
from my_module import my_function
connect_info = {
"host": "localhost",
"port": "5432",
"user": "test",
"password": "password",
"dbname": "postgres",
}
@pytest.fixture(scope="function")
def setup_and_teardown_psql():
conn = psycopg2.connect(**connect_info)
# connコンテキストが終わったタイミングでコミットされる
with conn:
with conn.cursor() as cur:
cur.execute("""
CREATE TABLE users (
name VARCHAR(50),
age INTEGER,
);
""")
data_path = PurePath(Path(__file__)).parent / "data/init_data.csv"
with open(data_path, "r") as f:
cur.copy_expert("COPY users FROM stdin WITH csv;", f)
# yieldより前がsetup/後がteardown
yield
with conn:
with conn.cursor() as cur:
cur.execute("DROP TABLE users;")
def test_my_function(setup_and_teardown_psql):
# PostgreSQLへの接続が必要な関数
res = my_function(**connect_info)
expected_res = {}
assert res == expected_res
Github Actions
.github/workflows/psql-ci.yml
など適当な名前でファイルを作成して以下を記載する。
流れとしてはざっくりと
- レポジトリのコードを取ってきて
- Pythonのセットアップをして
- テストコードを実行
という感じ。
name: postgres-ci
on:
push:
branches:
- '**'
workflow_dispatch:
jobs:
postgres-test:
runs-on: ubuntu-latest
# サービスコンテナには`localhost:<port>`または`127.0.0.1:<port>`で接続可能
services:
postgres:
image: postgres
# refer: https://hub.docker.com/_/postgres
env:
POSTGRES_PASSWORD: password
POSTGRES_USER: test
POSTGRES_DB: postgres
ports:
- 5432:5432
steps:
- uses: actions/checkout@v2
- name: Setup
run: sudo apt install -y curl
- name: Python
uses: actions/setup-python@v2
with:
python-version: '3.8'
architecture: 'x64'
- name: Setup Poetry
run: |
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -
echo "$HOME/.poetry/bin" >> $GITHUB_PATH
- name: Setup Python Libraries
run: poetry install
working-directory: ./app
- name: test
run: poetry run pytest -vs
working-directory: ./app/tests