Djangoで開発するときCIで実行しておくと便利なコマンド5選

こんにちは。最近はDjangoを学ぶ初心者が増えてきましたね。
私はDjangoを10年近く使っているのですが、最近の盛り上がりを見て嬉しい限りです。
本記事は、Djangoの使い方を一通り覚えて次のステップに進みたい人向けに書きました。参考になれば幸いです。

## （まず前提として）CIは非常に便利、ぜひ使いましょう！
まず、Djangoの話の前にタイトルにある「CI」について説明します。
Djangoに限らず、開発初心者がチーム開発に参加する際、覚えておいてほしい言葉のひとつが「CI（Continuous Integration）」です。
CIは日本語だと「継続的インテグレーション」と呼ばれています。
チーム開発に参加してコードを書く様子を想像してみてください。当然それぞれのメンバーが独立してコードを書くので、「Aさんのコード」、「Bさんのコード」、「Cさんのコード」のように各メンバーが所有するコードがあちこちにあります。
「みんな担当分の実装が終わったね。ではリリースしよう！」となっても、このままではどれをリリースすればいいのか分かりません。各メンバーのコードをひとつに統合する必要があります。
大昔はこの作業を手作業で行っていました。そして、統合した時初めて問題が分かって慌てて対応する、といったこともよくありました。
最近では[GitHub](https://github.com/)のようなサービスがあるので、複数人が書いたコードを一箇所に集めるのは難しくありませんが、集めたあとにリリース可能な状態かを検証する作業は必要です。

現在では、このような統合作業はCIによって自動化するのが一般的です。CIはコードの変更があるたびに統合作業を実施し、問題があれば即座にフィードバックを返すため、リリース間際のトラブルを大幅に減らせます。

CIを利用するには、自前のサーバーに[Jenkins](https://cloudbees.techmatrix.jp/jenkins/)のようなツールをインストールする方法もありますが、以下のようなクラウドサービスは運用の手間をかけずに利用できるため、お勧めです。

- [GitHub Actions](https://github.co.jp/features/actions)
- [Circle CI](https://circleci.com/ja/)

この記事では上記サービスの具体的な利用方法については割愛しますが、CIが現代の開発において必須であることは覚えておいてください。

## お勧めコマンド5選
Djangoで開発する際、CIで問題のフィードバックを行ってくれる便利なコマンドがいくつかあります。今回は、どのプロジェクトでも使ったほうがよさそうなものを5つ選んで紹介します。

### `black --check`（または`black`に準ずるコード整形ツール）
[Black](https://black.readthedocs.io/en/stable/)はコードの整形を自動化してくれるツールです。
チーム開発だとコーディング規約を定めることがよくありますが、細かいルールを人間が覚えて完璧に実践するのは不可能に近いです。Blackを導入すれば、人間に頑張ってルールを暗記しなくても、ルールに従ったコードを書くことができます。
通常は開発環境上で`black ファイル名`のように実行すれば整形してくれるのですが、実行し忘れた場合にCI上でチェックしておくと、早めにミスに気づくことができます。
CI上で実行する場合は、`--check`オプションを付けて実行しましょう。整形の必要がるファイルがあると、ファイルの更新はせずエラーコードを返して終了してくれます。大抵のCIサービスはエラーコードを返すコマンドがあると、そこで「問題が発生した」と判定して開発者に通知してくれます。

なお、コード整形ツールはBlack以外にもあるので、気に入ったものがあればそれを使ってもいいでしょう。
例えば、[PEP 8](https://peps.python.org/pep-0008/)という規約に従って整形するツール[autopep8](https://github.com/hhatto/autopep8)があります。

### `flake8`
[Flake8](https://flake8.pycqa.org/en/latest/)は問題のあるコードを検出してくれます。
Blackと役割が少し被っているのですが、Blackの管轄外の問題も検出してくれるので、併せて利用するのがお勧めです。

例えば、以下のコードは`black --check`だと何の問題もありませんが、`flake8`だといくつかエラーを見つけてくれます。

```py:example.py
import os  # importしているのに使っていない


def say_hello():
    message = "Python"  # 使っていない変数
    print(f"Hello!")  # f-stringを使っているのに埋め込む変数がない
```

```bash
$ black --check example.py
All done! ✨ 🍰 ✨
1 file would be left unchanged.
$ flake8 example.py
example.py:1:1: F401 'os' imported but unused
example.py:5:5: F841 local variable 'message' is assigned to but never used
example.py:6:11: F541 f-string is missing placeholders
```

### `isort --check`
[isort](https://pycqa.github.io/isort/)はファイル先頭のimport文の並べ替えを行ってくれるツールです。
Pythonのimport文の並び順は[PEP 8のImports](https://peps.python.org/pep-0008/#imports)という規約があるのですが、開発しているとついつい忘れがちです。
とりあえず必要なimport文を適当に並べておいて、isortで並べ替えすると楽に開発できます。
isortもBlackと同じく、CI上では`--ckeck`オプションを付けて実行しましょう。import文の並べ替えが必要なファイルを見つけると、ファイルを変更せずエラーコードを返して終了します。　

### `coverage run python manage.py test`
CIでは通常テストコードを実行しますが、何をテスト対象としているかは常に気にしておきたいところです。テストによって実行されたコードの割合を「カバレッジ」と呼びますが、カバレッジが低いとテストの対象になってないコードが不具合を抱えているのに気づかない可能性があります。
[Coverage.py](https://coverage.readthedocs.io/en/6.4.3/)を通してテストを実行すると、テスト対象になっているコードを集計しておくことができます。

Coverage.pyはHTMLで結果を出力することができますが、[Coveralls](https://coveralls.io/)、[Codecov](https://about.codecov.io/)などと連携すると、手軽に結果を確認できます。
以下はCodecovの実際の画面です。
![Codecov_と_セキュリティとプライバシー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7809/c262e6f0-8902-0d3e-4ba6-47dc97d27810.jpeg "Codecovの画面")

### `python manage.py makemigrations --check`
DjangoはModel定義を変更するたびに`makemigrations`コマンドを実行してマイグレーションファイルを作成する必要があります。これを忘れると、データベーススキーマとModel定義が食い違って、思わぬ不具合に繋がります。
`makemigrations`コマンドを`--check`オプション付きで実行すると、コマンドの実行し忘れがあった場合にエラーコードを返してくれます。

### `python manage.py check --deploy`
`check`コマンドはDjangoの設定に問題がないかを検証するコマンドです。`--deploy`オプションを付けることで、本番環境で動かす上でセキュリティ上の問題がないかも確認できます。

## それぞれのコマンドを並行で実行させておくのがお勧め
以上、5つのコマンドを紹介しました。これらをCIで実行させる際は、それぞれを並行で実行させておくのがお薦めです。
`black --check`でエラーが出なければ`flake8`、その次に`isort --check`、のように逐次実行させると、あるコマンドがエラーになると後に続くコマンドは実行しません。
並行実行だと、1回の実行で問題の全体像を把握できます。