Python での開発を効率的に進めるためのツー
ル設定
pycon jp 2019 ビギナーセッション
Atsushi Odagiri
September 16, 2019
Outline
Python での開発を効率的に進めるためのツール設定
flake8
black
mypy
pytest
tox
エディタ設定
まとめ
おまえだれよ
aodag: Atsushi Odagiri
株式会社オープンコレクター
pylonsproject.jp
今日のお題
開発を効率的に進めるためのツールを知りましょう
効率的に進める
つまらないミスをしないようにしましょう
がんばるだけではいつかミスをします
機械は疲れない! ツールに頼ろう!
はじめの準備
いつでも venv で作業しましょう
$ python3.7 -m venv .venv
$ source .venv/bin/activate
> py -3.7 -m venv .venv
> .venvScriptsactivate.ps1
flake8 とは
静的チェックツール
バグにつながりやすいソースコードをチェック
静的なので実際動かしてどうこうではない
なぜ静的チェックツールを使うのか
つまらないミスをなくそう
レビューで指摘されるより手元のツールでわかったほうが気
分いいよね?
flake8 のインストール方法
$ pip install flake8
flake8 の設定ファイル
.flake8 か setup.cfg, tox.ini など
ツール独自のファイルだとトップディレクトリに散らかるの
で汎用的なのが好み
[flake8]
max-line-length = 88
ignore = E203,W503,W504
flake8 実行例
def add(a, b):
return a + b
def f():
return add(None, 0)
def add(a, b):
c = a if a else 0
return a + b
flake8 実行結果
flake8 .flake8_violated.py
.flake8_violated.py:9:1: F811 redefinition of unused 'add'
.flake8_violated.py:10:5: F841 local variable 'c' is assig
修正しましょう
def f():
return add(None, 0)
def add(a, b):
c = a if a else 0
return c + b
black とは
PEP8 準拠なコードフォーマッター
autopep8, yapf などの既存のフォーマッターとの違い
ほとんど設定できない
たとえ pep8 に準拠しているコードでも問答無用で black スタ
イルにフォーマットされる
もう設定で悩むのはやめよう (プロジェクトごとにちょっと
設定が違うとかもやめよう)
なぜフォーマッターを使うのか
フォーマットされたコードは読みやすい
なんか変なことしているコードを見つけやすい
black のインストール方法
$ pip install black
black の設定ファイル
一応 pyproject.toml が設定ファイル
行長と除外ファイルくらい設定できる
black の使い方
そのまま実行するとフォーマット実行
--check オプションでフォーマットされるファイルがあるか
チェック
--diff オプションでどのようにフォーマットされるか差分
表示
black 実行例
def add(a, b):
c = (
a
+
b)
return a + b
black 実行結果
black --diff .black_diff.py
--- black_diff.py 2019-09-16 01:11:41.391055 +0000
+++ black_diff.py 2019-09-16 01:11:47.066582 +0000
@@ -1,7 +1,4 @@
def add(a, b):
- c = (
- a
- +
- b)
+ c = a + b
return a + b
reformatted black_diff.py
All done! black --diff .black_diff.py
mypy とは
type hint チェック
実行時は関係ない
なぜ type hint チェッカーを使うのか
ドキュメントやコメントで書くより厳密
正しくない type hint はエディターの補完などで有害
実行しなくても型チェッカーで間違いがわかる
mypy のインストール
$ pip install mypy
mypy の設定ファイル
mypy.ini, setup.cfg
ignore_missing_imports は今のところ必須
type hint を提供していないライブラリを許す
[mypy]
ignore_missing_imports=1
mypy 実行例
from typing import Optional
def f():
return add(None, 0)
def add(a: Optional[int], b: int):
c = a if a else 0
return a + b
mypy 実行結果
mypy .mypy_violated.py
mypy_violated.py:9: error: Unsupported operand types for +
mypy_violated.py:9: note: Left operand is of type "Optional
修正しましょう
from typing import Optional
def f():
return add(None, 0)
def add(a: Optional[int], b: int):
c = a if a else 0
return c + b
pytest とは
テストランナー
ユニットテストフレームワーク
なぜ pytest か。unittest との違い。
詳細なテストレポート
アドオン
fixture の仕組み
関数 + assert 文 vs TestCase クラスの assert メソッド
pytest のインストール
$ pip install pytest
pytest アドオンの例
pytest-cov
coverage 情報収集
pytest-django
request や client などの fixture を提供
pytest-mock
mock を pytest 向けに使いやすくした fixture
pytest-freezegun
時間関連のモックツール freezegun の pytest fixture
pytest-randomly
random seed の設定
テスト順序をシャッフル
使い方 (1)
テスト対象
# loader.py
import json
FILENAME = "value.json"
def load():
with open(FILENAME) as f:
return json.load(f)
def save(v):
with open(FILENAME, "w") as f:
json.dump(v, f)
使い方 (1)
テストコード
# test_loader.py
import json
from loader import save, load
def test_save():
v = {"value": 1}
save(v)
with open("value.json") as f:
assert json.load(f) == {"value": 1}
def test_load():
result = load()
assert result == {"value": 1}
問題点
test_load は test_save 実行後じゃないと成功しない
test_save だけ単独実行できない
いつもテストを全部実行しないといけない?
対策
テスト実行順をシャッフルする
順序依存のテストを発見
全体実行
pytest-randomly なしだといつもうまくいってしまう
$ pytest .test_loader.py
テスト指定で実行
$ pytest .test_loader.py::test_load
$ rm value.json
$ pytest .test_loader.py::test_load
pytest-randomly を入れて実行
テスト順がシャッフルされるので複数回実行してみましょう
$ pip install pytest-randomly
$ pytest .test_loader.py
$ pytest .test_loader.py
$ pytest .test_loader.py
$ pytest .test_loader.py
tox とは
テスト用 virtualenv の管理
テストタスクの管理
tox を使う意味
様々なバージョンの python でテストする
CI 上でもローカルでも tox で同じテストを実行する
tox のインストール
$ pip install tox
tox.ini
[tox]
envlist = py36,py37
[testenv]
deps = pytest
commands = pytest
実行
-e オプションで実行したい env を指定する (指定しなければ
全部)
$ tox -e py37
ツールを実行するタイミング
CI で実行
pre-commit で実行
コマンドラインで手動実行
エディタ上で自動実行
エディタからツールを使えるようにしましょう
編集や保存と同時に警告、フォーマット
その場ですぐ直しましょう
自分で実行すると、たまに忘れて CI で落ちてがっかり
ツールとか連携できるエディタ
visual studio code
emacs
vim
pycharm
エディタで設定したいこと
編集中に flake8/mypy の警告を表示
保存したら black でフォーマット
テスト実行結果からエラー箇所にジャンプ
テストでカバーされた行をマーカーで表示
vs code
python.linting.flake8.enabled
python.linting.mypy.enabled
python.linting.pylint.enabled false
python.format.provider = ”black”
editor.formatOnSave
emacs
静的チェックのフレームワーク flycheck や flymake
flycheck はデフォルトで flake8 対応
save フック
save フックで black を適用
vim
使ってないのでわかりませんが、同じようなことができるで
しょう
pycharm
使ってないのでわかりませんが、同じようなことができるで
しょう
覚えて帰ってほしいこと
退屈なことは機械がやってくれる
レビュアーの時間を奪わないように
自分でやってみてほしいこと
自分のプロジェクトに導入できそうな pytest アドオンを調べ
てみましょう
pytest-django, pytest-mock…
プロジェクトの CI に導入してみましょう

Pythonでの開発を効率的に進めるためのツール設定