みなさんこんにちは、電通国際情報サービス(ISID)Xイノベーション本部ソフトウェアデザインセンターの佐藤太一です。
皆さんは最近発売された『実践プロパティベーステスト ― PropErとErlang/Elixirではじめよう』はもう読みましたか?
この本はErlangやElixirを使ってプロパティベーステストというテスト手法について具体的なコードを使って実践的に学習できる本です。非常に素晴らしい本ですが、難しい部分も多いため私は少しずつ読んでいる所です。
この記事では、この本を読むにあたってサンプルコードを動かすための環境を使っているOSに依存せずに作成する方法を説明します。
- 事前の準備
- 最小限のDev Container
- devcontainer.jsonを編集する環境の構築
- Erlang用VS Code拡張
- テスト用プロファイルで使うライブラリをエディタに認識させる
- まとめ
事前の準備
この記事が前提とする環境について軽く説明します。
まず、 VS Code を事前にインストールしておいてください。
次に、Docker Desktopをインストールして動作する状態にしてください。基本的には単にインストーラを実行すれば動作する状態になります。
そして、VS Codeに Dev Containers拡張をインストールしておいてください。
最後に、作業用のプロジェクトディレクトリを作成してください。ここでは、pbt というディレクトリを作成してプロジェクトのルートディレクトリとしています。
最小限のDev Container
まずは、Dev Containerを使ってErlangが提供する公式のDockerイメージを使った開発環境を作成してみましょう。
プロジェクトのルートディレクトリに、 .devcontainer
というディレクトリを作って、その中に devcontainer.json
というファイル名で以下の内容を保存します。
{ "name": "devcontainer-erlang", "image": "erlang:slim", "containerEnv": { "TZ": "Asia/Tokyo" }, "runArgs": ["--init"] }
- name の値は、分かりやすい名前なら何でもいいです。ここでは、devcontainer-erlang としています。
- image の値は、erlang:slim としています。これは公式のイメージ名です。
- ベースイメージやErlangランタイムのバージョンを別なものにしたい場合には、https://hub.docker.com/_/erlang から探してください。
- containerEnv の値は、コンテナ内で参照される環境変数です。ここではタイムゾーンが
Asia/Tokyo
になるよう設定しています。時刻に起因する問題の調査は難しいので、ここで明示的に設定しています。 - runArgs の値は、
--init
を渡すことでDockerが/dev/init
というシグナルハンドリング用のプロセスを起動してくれます。これによってコンテナを安定的にシャットダウンできます。
devcontainer.jsonを編集する環境の構築
ここから、devcontainer.json を編集しながら開発環境を構築していくので、まずは快適にjsonファイルを編集できるようにしましょう。
devcontainer.jsonには、Dev Containerとして起動したVS Codeを構成するための設定項目がありますので、それらを編集します。
{ "name": "devcontainer-erlang", "image": "erlang:slim", "customizations": { "vscode": { "settings": { "editor.renderWhitespace": "all", "[json][jsonc]": { "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll": true } } }, "extensions": ["esbenp.prettier-vscode"] } } }
customizations
というキーがDev Containerの構成を行うための設定項目です。この中にvscode
という項目がありますね。
settings
の中では、VS Codeの設定項目を管理します。
editor.renderWhitespace
の値として、all
を設定しているのは、ファイルの中に紛れ込んだ全角スペースを見つけやすくするためです。私たちがIMEを使っている以上、意図しない場所に全角スペースが入り込んでしまい、それによって理解が困難なエラーメッセージを読むことになるのは避けられません。全角スペースが見えていれば、そういったドハマりから抜け出しやすくなります。[json][jsonc]
の値として、いくつか設定しています。ちなみに、jsoncは、JSON with commentsの略称です。editor.defaultFormatter
の値として、esbenp.prettier-vscode を設定しています。これによってprettierを使ったフォーマットが行われます。editor.formatOnSave
の値として、trueを設定することでファイル保存時にフォーマットが行われるようにしています。editor.codeActionsOnSave
の値として、source.fixAll を有効化することで自動的に補正できるフォーマットエラーをprettierが積極的に補正してくれます。
extensions
の中では、Dev Containerとして起動されたVS CodeにインストールされるVS Code拡張を列挙します。ここでは、JSONを自動フォーマットするための esbenp.prettier-vscode
を設定しています。
Erlang用VS Code拡張
次は、Erlang用のVS Code拡張を追加します。マーケットプレイスを確認するといくつかの拡張がありますが、一番利用者の多いものを今回は使います。
devcontainer.jsonのextensionsに拡張を追加すると、以下のようになります。
{ "name": "devcontainer-erlang", "image": "erlang:slim", "customizations": { "vscode": { "settings": { "editor.renderWhitespace": "all", "erlang.formattingLineLength": 200, "[erlang]": { "editor.defaultFormatter": "pgourlain.erlang", "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll": true } }, "[json][jsonc]": { "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll": true } } }, "extensions": ["pgourlain.erlang", "esbenp.prettier-vscode"] } } }
erlang.formattingLineLength
の値として、200を設定しています。この設定項目はドキュメントには記載がないので、私の設定値をここに書いています。[erlang]
の値として、いくつか設定しています。何をしているかは[json][jsonc]
の時と同じです。
これでErlangのアプリケーション開発環境は完成です。しかし、本を読み進めていくと早々に問題にぶつかります。
テスト用プロファイルで使うライブラリをエディタに認識させる
書籍では、PropErというライブラリをrebarというビルドツールに構成するように指示されます。
その結果、rebar.configを以下のように構成します。
{project_plugins, [rebar3_proper]}. {profiles, [ {test, [ {erl_opts, [nowarn_export_all]}, {deps, [proper]} ]} ]}. {erl_opts, [debug_info]}. {deps, []}.
rebar3では、依存ライブラリをプロファイル毎に管理できるようになっています。
そして、 proper
は test
プロファイルでのみ参照されます。
ダウンロードされた依存ライブラリは、プロジェクトのルートディレクトリにある _build
ディレクトリ以下に格納されています。
この状態だと、rebarによるビルドは成功するのですが、エディタ上で can't find include lib "proper/include/proper.hrl”
といったエラーが出力されます。
このエラーを解決するためVS Codeのエディタ上でも、testプロファイル以下にダウンロードされたライブラリを参照するように設定を追加します。
変更した後のdevcontainer.json は以下のようになります。
{ "name": "devcontainer-erlang", "image": "erlang:slim", "customizations": { "vscode": { "settings": { "editor.renderWhitespace": "all", "erlang.formattingLineLength": 200, "erlang.includePaths": ["_build/test/lib"], "[erlang]": { "editor.defaultFormatter": "pgourlain.erlang", "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll": true } }, "[json][jsonc]": { "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll": true } } }, "extensions": ["pgourlain.erlang", "esbenp.prettier-vscode"] } } }
まとめ
ここまで、Dev ContainerでErlangアプリケーションの開発環境を構築する方法について説明してきました。
普段あまり使っていないプログラミング言語でも、Dockerベースのコンテナ技術を使えば簡単に開発環境を構築できることがお分かりいただけたんじゃないでしょうか。
特に私が普段使っているWindowsではインストーラを使ったバイナリのインストールは後腐れが残り易いので、本を読み終わったら全てを片付けられて副作用のないDev Containerは非常に便利です。
この記事を読んでいただいたあなたも是非、クリーンな開発環境を構築してプロパティベーステストという応用可能性の高いテスト手法に習熟できることを願っています。
この記事で紹介している開発環境の構成ファイル
最後に作った構成ファイルを紹介します。
.devcontainer/devcontainer.json
{ "name": "devcontainer-erlang", "image": "erlang:slim", "customizations": { "vscode": { "settings": { "editor.renderWhitespace": "all", "erlang.formattingLineLength": 200, "erlang.includePaths": ["_build/test/lib"], "[erlang]": { "editor.defaultFormatter": "pgourlain.erlang", "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll": true } }, "[json][jsonc]": { "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll": true } } }, "extensions": ["pgourlain.erlang", "esbenp.prettier-vscode"] } } }
執筆:@sato.taichi
(Shodoで執筆されました)