桐生あんずです

日常やプログラミングについて書いています。

VSCodeのエディタからRailsのminitestをファイル/ブロック単位で任意に実行できるようにした

桐生あんずです。

今までRailsのminitestからテストする際に、ファイルやブロック単位で実行する際に以下のコマンドを流し見しつつ手打ちで頑張っていたのですが、流石に他の方法がありそうだな、と思い用意してみました。

rake test TEST=test/sample_test.rb TESTOPTS="--name=test_sample_2"

様子

ツイートの内容通り、最初は以下のような自作シェル関数を作ってテスト関連のファイルをfindしてpecoで一覧化して探索できるようにする方法にしたのですが、

function peco-test() {
        local files=$(find test | peco)
        if [ -n "files" ]; then
                BUFFER="bundle exec rake test TEST=${files}"
                zle accept-line
        fi
}
zle -N peco-test
bindkey '^T' peco-test

「一度コマンドを打ったらヒストリーから辿れば良いだけなので、そんなに実用性があるわけでは無い気がしてきた……」となり色々調べていて「エディタから実行したいテストの行をクリックして個別に実行する」という手法が便利そうだったので、参考になりそうな記事を探して作ってみることにしました。

参考にした記事

hakobe932.hatenablog.com

この方の記事ではPerlのテストを実行していますが、Rubyで同じように動かすとしても.vscode以下のフォルダにtasks.jsonを作成してブロック単位でテストを実行したい時に動かすwrapperスクリプトを用意するだけで再現可能だったので、Rubyで以下のように書いて実行したところ無事思った通り動かせることができました。

//.vscode/tasks.json

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "run Ruby test all",
            "type": "shell",
            "command": "bundle exec rake  test TEST=${relativeFile}",
            "group": "test",
            "presentation": {
                "reveal": "always",
                "panel": "shared"
            }
        },
        {
            "label": "run Ruby test here",
            "type": "shell",
            "command": "bundle exec ruby .vscode/exec/run_test_at.rb ${relativeFile} ${lineNumber}",
            "group": "test",
            "presentation": {
                "reveal": "always",
                "panel": "shared"
            }
        }
    ]
}
.vscode/exec/run_test_at.rb

filename = ARGV[0]
file_line_number = ARGV[1]
open(filename) {|file|
    lines = file.readlines
    file_line = nil
    file_line_number.to_i.downto(0) do |i|
        file_line = lines[i]
        break if file_line.match(/test\s+".+?"/)
    end
    return unless file_line
    file_block = file_line.slice(/test\s+".+?"/).gsub(" ", "_")
    cmd = "bundle exec rake test TEST=#{filename} TESTOPTS=--name=#{file_block}"
    puts cmd
    system(cmd)
}

これで普段よりテストの個別実行が楽になったので大変嬉しい……!と思いつつも世の人はこういう場面に出会ったときにどう対処しているのだろう?とふと疑問に思ったり。

このつぶやきに反応してくれたフォロワーは以下のようなやり方で対応しているとのことでした。