コードレビューの補助に、Dangerを導入しているチームも多いと思います。
プラグインも簡単に作れるので、半分覚え書きですが、解説したいと思います。
プロジェクトの生成
ローカルにdanger
が入っていない場合は、事前に入れておきます。
sudo gem install danger
最初に、テンプレートからプロジェクトを生成します。
命名は、snake caseのプラグインが多いようです。
わかりやすいように、sample_plugin
という名前で進めます。
danger plugins create sample_plugin
この場合、danger-sample_plugin
というディレクトリが生成されます。
ファイルの構成
基本的に触る部分は、プラグインのソース(lib
以下)とテストコード(spec
以下)です。
プラグインのソースはlib/sample_plugin/plugin.rb
が中心です。
Dangerfile
から触るプロパティなどは、ここに記述します。
テストコード(RSpec)はspec/sample_plugin_spec.rb
に記述していきます。
テストコードは書かなくても動作には問題ないですが、Dangerプラグインという性質上、ローカルでのデバッグがしづらいので、テストを書きながら開発するのを推奨します。
プラグイン本体の書き方
最初の状態ではこのようになっています。
module Danger
class DangerHoge < Plugin
attr_accessor :my_attribute
def warn_on_mondays
warn 'Trying to merge code on a Monday' if Date.today.wday == 1
end
end
end
attr_accessor
でmy_attribute
というアクセサが公開されています。
Dangerfile
から指定するプロパティはここで公開します。
メソッドはwarn_on_mondays
が公開されています。
Dangerfile
からは、
sample_plugin.my_attribute = ["hoge"]
sample_plugin.warn_on_mondays
のように利用することが出来ます。
RSpecの書き方
spec/sample_plugin_spec.rb
は、最初はこのような内容です。
require File.expand_path("../spec_helper", __FILE__)
module Danger
describe Danger::DangerHoge do
describe "with Dangerfile" do
before do
@dangerfile = testing_dangerfile
@my_plugin = @dangerfile.hoge
end
it "Warns on a monday" do
end
end
end
end
it
ブロック一つひとつがテストケースにあたり、それぞれの実行前にbefore
ブロックに書かれた内容が実行されます。
各ケースは、よくある単純比較の場合は、expect(<実際の値>).to eq 期待値
のように書きます。
expect(@dangerfile.status_report[:messages]).to eq ["Hello hoge!"]
実際の例
試しに、ダンプされたファイル出力をパースして、その中から警告を抽出するプラグインを作ってみます。
分かりづらいかもしれませんが、ご容赦ください。
テストの記述
先にテストを書いておくTDD的な進め方をすると、検証が楽になります。
テスト対象のファイルを事前に書き出しておいて、specのbefore
でそれを読み込む処理を書きます。
静的ファイルは、spec/fixtures
に配置します。
describe "with Dangerfile" do
context "enable linker warnings" do
before do
@xcode_warnings.show_build_warnings = true
@sample_plugin.analyze_file "spec/fixtures/log_with_4_errors"
end
end
end
プラグインにshow_build_warnings
とanalyze_file
はまだ実装していませんが、TDDの考え方では最初に失敗するようなテストを記述するので、問題ありません。
テストケースを実装していきます。
今回は、「警告が4つ出ること」と、「メッセージが表示される」ことを期待する結果とします。
describe "with Dangerfile" do
context "enable linker warnings" do
before do
@xcode_warnings.show_build_warnings = true
@sample_plugin.analyze_file "spec/fixtures/log_with_4_errors"
end
it "warn 4 lines" do
expect(@dangerfile.status_report[:warnings]).to eq [
"警告文1",
"警告文2",
"警告文3",
"警告文4"
]
end
it "put a single message" do
expect(@dangerfile.status_report[:messages]).to eq [
"メッセージ"
]
end
end
end
それぞれ警告とメッセージは、@dangerfile.status_report[:warnings]
と@dangerfile.status_report[:messages]
に入ります。
これらのテストケースが通るように、プラグインの実装をします。
プラグインの実装
show_build_warnings
とanalyze_file
を実装していきます。
パーサーの実装は省略しますが、テキストをパースして警告を抽出するクラスです。
module Danger
class SamplePlugin < Plugin
attr_accessor :show_build_warnings
def show_build_warnings
@show_build_warnings.nil? ? true : @show_build_warnings
end
def analyze(log_text)
parser = LogParser.new
parser.show_build_warnings = show_build_warnings
parsed = parser.parse_warnings(log_text)
parsed.each do |warning|
warn MessageFormatter.new.format(warning)
end
message "メッセージ" unless parsed.empty?
end
def analyze_file(file_path)
File.open(file_path) do |f|
analyze(f.read)
end
rescue Errno::ENOENT, Errno::EACCES => e
puts "Couldn't open the file: #{e}"
end
end
end
attr_accessor
でshow_build_warnings
を定義します。
def show_build_warnings
@show_build_warnings.nil? ? true : @show_build_warnings
end
とすることで、デフォルトでtrue
にすることが出来ます。
次にanalyze_file
(analyze
)の中でテキストをパースして、警告とメッセージを出す処理を書きます。
警告とメッセージの出し方はDangerfile
と同じで、warn
とmessage
です。
先程書いたテストに対して実際に、テストが通るかを、
bundle exec rake spec
で確認しながら実装を進めていきます。(bundlerも入れておいてください)
Travis CIの設定
.travis.yml
が若干古いので、更新が必要です。
一例ですがこんな感じです。
language: ruby
cache:
directories:
- bundle
rvm:
- 2.3.1
- 2.4.5
- 2.5.3
branches:
only:
- master
script:
- bundle exec rake spec
gemspec
を書けばgemとして登録することも出来ます。