はじめに
こんにちは、YOUTRUSTのしぶしゅん(YOUTRUST / X)です。
昨年Kaigi on Railsにブース出展し、「出張OPEN CODE」を行いました。 OPEN CODEはYOUTRUSTで定期的に開催しているYOUTRUSTで実際に利用しているソースコードを紹介するイベントです。 ブース出展の企画として出張開催しました。
Kaigi on Rails 2024 参加レポート!! - YOUTRUST Tech Blog
その際に、「rails statsの出力項目が足りていないのでは?」という質問をいただきました。 調査の結果、確かに出力項目が不足しており、正しい統計情報が得られていないことが判明しました。 今回はその調査内容と結果について紹介します。
rails statsとは
rails statsはRailsアプリケーションの統計情報を出力するコマンドです。 次のように実行することで出力できます。
$ bundle exec rails stats
このコマンドは、アプリケーションコードとテストコードをディレクトリ単位で統計情報として出力します。
YOUTRUSTのrails statsを出力した結果です。
Linesが行数、LOCがコメントなどを除いた行数を表します。
アプリケーションコードのCode LOCとテストコードのTest LOCの比率であるCode to Test Ratioはプログラムでどれだけテストが書かれているかの指標です。
Code to Test Ratio: 1:4.8
となっており、アプリケーションコードに対してテストコードが5倍ほどあることになります。
問題点とYOUTRUSTのディレクトリについて
YOUTRUSTは2025年1月8日時点でRails7系を利用しています。 Rails7系のstatsは次のように実装されています。
rails/railties/lib/rails/tasks/statistics.rake at v7.0.8.7 · rails/rails · GitHub
STATS_DIRECTORIES
で定義されたディレクトリのみを対象にしていました。
YOUTRUSTのapp
配下のディレクトリにはSTATS_DIRECTORIES
で定義されたディレクトリに加え、use_cases
やcommands
などのディレクトリがあります。
定義されていないディレクトリが計測できていませんでした。
YOUTRUSTがCQSアーキテクチャを採用しているためこのようなディレクトリとなっています。 CQSアーキテクチャについては過去のテックブログで紹介しています。
カスタムコップでCQSの運用を改善した話 - YOUTRUST Tech Blog
またYOUTRUSTではテストにRSpecを利用しています。
rspec-rails/lib/rspec/rails/tasks/rspec.rake at v7.1.0 · rspec/rspec-rails · GitHub
STATS_DIRECTORIES
で定義されたtest配下のディレクトリの代わりにspec配下のディレクトリをSTATS_DIRECTORIES
に追加します。
またTest LOCとして計算されるようにTEST_TYPES
にも追加します。
rails/railties/lib/rails/code_statistics.rb at v7.0.8.7 · rails/rails · GitHub
TEST_TYPES
の定義箇所です。
問題点の修正と修正後のrails stats
app配下のディレクトリをすべてSTATS_DIRECTORIES
に追加することでCode LOCを正しく数えるようにしました。
app以外のlibとspecは変更前と同じように追加しています。
namespace :custom_stats do desc 'Generate custom code statistics' task generate: :environment do require 'rails/code_statistics' def get_directory_pairs(*directories) pairs = directories.map do |directory| subdirs = Dir.entries(directory).select { |entry| File.directory?(File.join(directory, entry)) && !entry.start_with?('.') } # statsの出力と合わせるためにspecディレクトリの場合は複数形を単数形に変換してsuffixを調整する suffix = directory == 'spec' ? ' specs' : '' subdirs.map do |subdir| label = "#{directory == 'spec' ? subdir.singularize.capitalize : subdir.capitalize}#{suffix}" [label, File.join(directory, subdir)] end end.flatten(1) pairs end pairs = get_directory_pairs('app', 'spec') # statsの出力と合わせるためにlibディレクトリを追加 pairs << ['Libraries', 'lib'] # specのディレクトリ名をTEST_TYPESに追加してTest LOCとする pairs.select { |pair| pair[1].start_with?('spec') }.each do |pair| ::CodeStatistics::TEST_TYPES << pair[0] unless ::CodeStatistics::TEST_TYPES.include?(pair[0]) # rubocop:disable Style/RedundantConstantBase end stats = CodeStatistics.new(*pairs) puts stats end end
実行すると次のように出力されます。
$ bundle exec rails custom_stats:generate
修正後のrails statsではuse_cases
やcommands
などのディレクトリが出力されています。
appディレクトリにあってCodeとして計測できなかったものを数えるようになり、Code to Test Ratio: 1:2.7
となりました。
修正の結果4.8から2.7という結果になりましたが、他社と比較しても悪くない結果のようでした。
おわりに
YOUTRUSTのrails statsで正しい情報が得られるようになりました。 これからもアプリケーションコードだけでなくテストコードも充実させていきます。
次バージョンのRails8系ではregister_directory
を利用してより簡潔に実装できます。
バージョンアップ後にまた試してみます。
rails/railties/lib/rails/code_statistics.rb at v8.0.1 · rails/rails · GitHub
今回のrails stats出力項目修正のきっかけとなったOPEN CODEは次回開催に向けて準備中です。エンジニアの皆様と交流するのを楽しみにしております。
YOUTRUSTではエンジニアを募集しています。 興味のある方はぜひご応募ください。
参考文献
rails stats 2024 ~ Kaigi on Rails 2024 アフターイベント - connpass
rails statsで大解剖 🔍 “B/43流” のRailsの育て方を歴史とともに振り返ります - Speaker Deck
SmartHR の `rails stats`―― 良いところ・伸びしろ全部語り尽くしちゃいます - Speaker Deck
rails stats で紐解く ANDPAD のイマを支える技術たち - Speaker Deck
各社のrails stats実行結果を参考にさせて頂きました。
rails stats コマンドで app 以下のディレクリを全て計測できるようにする - Note
RSpecによる上書きについて参考にさせて頂きました。
ありがとうございます。