JX通信社 Advent Calendar 2018 7日目の記事です。
いきさつ
WebAPIのテストをするときに、リクエストに対して帰ってきたJSONをassertすることはよくあると思います。
PythonではJSONをそのまま扱うよりも辞書型にして扱うことが多いと思いますし、辞書型なら期待する値をリテラルで書いてレスポンスの値と比較できるので楽ですね。
しかし、例えばリソースの作成・更新日時などはテストの実行時に期待値を用意しても、assertの実行タイミングによって微妙な差が生じて単純に比較すると失敗してしまうことがあります。
ほかにも「ここの数値は期待値の±nまでは許したい」「このキーの値はUUID使うから無視したい」「Optionalだから要素があってもなくてもOK」など、いろんな基準でassertしたくなるケースがあると思います。
だからといって、assertしたい要素だけ取り出してから比較したり一部の要素だけ別の基準でassertしたりを個別にいちいち書くのも面倒です。
そこで、辞書型同士の比較の条件を簡単に指定できるライブラリを作ってみました。
作ったもの自体は非常に小さく(というか関数1つだけ)、簡単なものですがせっかくなのでPyPIに登録してみました。
ライブラリの使い方と、それをPyPIにアップロードしたとき手順をまとめてみます。
使い方
普通にpipでインストールします。Python3.6以上を想定しています。
pip install chabie
簡単なサンプルコードはこちら
from chabie import chabie
chabie.compare_dicts({'foo': 100}, {'foo': 200}) # False
chabie.compare_dicts({'foo': 100}, {'foo': 100, 'bar': 200}) # False
# keysに{<キー>: <boolを返す関数オブジェクト>}を指定すると、特定のキーの比較の条件を指定できる
chabie.compare_dicts({'foo': 100}, {'foo': 105},keys={'foo': lambda a, b: abs(a-b) <= 5}) # True
# typesに{<クラスオブジェクト>: <boolを返す関数オブジェクト>}を指定すると、特定の型の比較の条件を指定できる
chabie.compare_dicts(
{'foo': 'abcde'},
{'foo': 'fghij'},
types={str: lambda a, b: len(a)==len(b)}
) # True
# ignoreにリストで渡したキーは無視される
chabie.compare_dicts({'foo': 100}, {'foo': 100, 'bar': 200}, ignore=['bar']) # True
中身に辞書型やリストがネストされていても再帰的に比較します。
keysとtypesを同時に渡すとkeysが優先されます。
PyPIへの登録
公式のドキュメントはこちら
PyPIでアカウント作成
PyPIの登録フォーム からアカウントを作ります。
ユーザ名とパスワードが後でライブラリをアップロードする際に必要になります。
※ テスト用のPyPIとして、https://test.pypi.org/account/register/ もあります。
パッケージングやアップロードの操作に慣れたりCI/CDのテストしたい時に利用しても良いでしょう
パッケージング
公式チュートリアルはこちら
ディレクトリ構成
├── chabie
│ ├── chabie.py
│ ├── __init__.py
│ └── key.py
├── LICENSE
├── README.md
├── setup.py
setup.pyの作成
from setuptools import setup, find_packages
setup(
name='chabie', # pip installで使う名前を指定します
version='0.3.0', # バージョンを指定します
description='Comparison utility', # どんなパッケージかを説明します
author='TatchNicolas',
author_email='TatchNicolas@users.noreply.github.com',
license='MIT',
packages=find_packages(),
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
]
)
-
packages
: パッケージに含めるパッケージ(もっと上手い言い方したい)を指定します。-
find_packages()
を使うことでディレクトリ内で見つかるモジュールを良い感じに探してくれます。
-
-
classifiers
: ライセンスやサポートしている環境、プロジェクトの状態(alpha, betaなど)、用途などのメタ情報を指定します。
LICENSE、README.mdの作成
任意のライセンスと、適当なREADME.mdを作成します。
今回はMITライセンスにしてみました。
MIT License
Copyright (c) 2018 Tatch
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
setuptoolsでパッケージング
パッケージングに必要なパッケージをインストールします。
pip install setuptools wheel
続いてパッケージングします。
python3 setup.py sdist bdist_wheel
sdistはSource Distribution、bdist_wheelはBuilt Distributionのことです。
ここでは両方指定しておきましょう。
完了すると、プロジェクトフォルダに以下のようなファイルが作成されます。
├── chabie.egg-info
│ ├── dependency_links.txt
│ ├── PKG-INFO
│ ├── SOURCES.txt
│ └── top_level.txt
└── dist
├── chabie-0.3.0-py3-none-any.whl
└── chabie-0.3.0.tar.gz
アップロード
いよいよアップロードです。twine
コマンドを使います。
ユーザ名とパスワードは、以下のいずれかの方法で指定できます。
- プロンプトから入力
- .pypircというファイルに記載
- コマンドラインのオプションで指定(
-u, --username
/-p, --password
) - 環境変数で指定
2.は間違えてGitHubへ大公開して大後悔しないようにご注意ください。
CI/CDにのせるなら、そのサービスの提供する方法で認証情報をストアすることになると思うので、3.か4.の方法が良いでしょう。
今回は環境変数を使ってみます。
$ export TWINE_USERNAME=<PyPIのユーザ名>
$ export TWINE_PASSWORD=<PyPIのパスワード>
# (注) test.pypi.orgを使う場合は、以下の環境変数でアップロード先を切り替えてください
$ export TWINE_REPOSITORY_URL=https://test.pypi.org/legacy/
最後にアップロードコマンドを実行します。
$ twine upload dist/*
めでたく自作のライブラリをPyPIにアップロードすることができました。
ダウンロード
試しにpip install
できるか試してみましょう。test.pypi.org
を使った人は、URLの切り替えを忘れずに。
pip install <アップロードしたリポジトリの名前>
pip install -i https://test.pypi.org/simple/ <アップロードしたリポジトリの名前> # test.pipy.orgの場合