マークダウンのリストから spec の雛形に変換するツールを作ってみた
新しいクラスを追加するときなど、ある程度まとまった spec を書く必要がある場合、どんな感じでテストケースの設計をしているでしょうか?
マークダウンを使ったテスト設計
僕はマークダウンエディタ(notionなど)を使って、リスト記法でテストパターンを箇条書きにして設計することが多い。 リスト記法だと階層の深さで事前条件や期待値を表現できるし全体の構造を俯瞰しやすいし、改行時に入力補完されたりタブキーでの階層の上げ下げが容易だったりして試行錯誤するための敷居がとても低く感じる。 少なくともいきなりプログラミング言語で書き始めるよりはテスト設計に集中できる。
例えばこんな感じ。
- d: 新しいクラス - d: モード取得 - c: ほげの場合 - i: モード1が返ること - c: ふがの場合 - i: モード2が返ること - c: 上記以外の場合 - i: XXX例外をスローすること
各行にはマークダウンのリスト記法に独自のシンボルを付けて意味づけをしている。 (d は describe, c は context, i は it)
マークダウン上での試行錯誤がある程度済んだらそれを実際の spec ファイルにコピペして1行1行を言語に変換する。 ただこれが結構しんどい。単純作業で置換コマンドなどを駆使しても閉じ括弧とかもあるしなかなかのストレスフルな作業だ。
SpecDown
そこで、変換ツールがあったらいいなー、と思って探してみたけど、ありそうで意外と見つけられなかったので今回は SpecDown というWebアプリを作ってみた。
左側のテキストエリアにマークダウンを貼ると右側に実際の spec のコードテンプレートが表示される。 右上のセレクトボックスで言語の選択も可能で、今のところ良く使いそうな rspec と jest に対応してみた。
右上のボタンを押すとクリップボードにコピーされるのでそのままコードエディタに貼り付けられる。 これで、これまで多少時間のかかっていた「マークダウンでテスト設計」 → 「テストコードの実装」 がシームレスに移行出来るのでテストの実装が捗る!
対応言語の追加
各言語に依存した部分は、本体のロジックから分離しているので比較的容易に追加出来ると思う。
例えば rspec の場合は以下のような感じで、リストのシンボルに対応したコードを定義する。
{ name: 'rspec', format: 'ruby', symbols: { d: (body) => `describe '${body}' do`, c: (body) => `context '${body}' do`, i: (body) => `xit '${body}' do`, b: (body) => `before do ${body.length !== 0 ? '# ' + body : ''}`, a: (body) => `after do ${body.length !== 0 ? '# ' + body : ''}` }, comment: (body) => `# ${body}`, terminal: 'end' },
https://github.com/volpe28v/Specdown/blob/master/services/SpecRenders.js
このファイルに追加しておけば、実行時にセレクトボックスの言語に追加されて選択可能になる。
システム構成
構成は Nuxt のフレームワークで書いたシンプルな SPA で、 heroku に上げて運用している。 こういう単機能のシンプルツールは Nuxt + heroku だと簡単に作れて捗る。 Github と heroku を連携しておけば、master に push するだけで heroku へデプロイされてとても楽チン。
実はこのWebアプリを作る前に、rubyの練習がてらコマンドラインツールとして作ってみたんだけど、マークダウンを一旦ファイルに保存してからそのファイルを食わすというインターフェースだと変換までの手順が多くて実際にあまり使わなくなってしまった。 やっぱりWebインターフェースはいいですね。
実際に使えるデモページはこちら https://specdown.herokuapp.com/