Satoryu's Diary

Rubyが好きなプログラマーの日記。日々の生活、開発に関するメモとか考えとか。


2014年04月24日

_ 俺が考えたさいきょうのRSpecコーディング規約 - 構造編

自分が、真面目にテストコードを書きはじめて、だいたい4年くらい経ちました。 その間、いろんなgemとか、アプリケーションのソースを読んできたけど、

見やすい構造があるなぁ

と思ったので、自分なりに見やすいと思えるものを、ここに書いてみる。

実装本体だけでなく、テストコード自体の読みやすさも大切だと思う。

前提

  • テストコードはテストするためだけでなく、実装を理解する助けになるものであるべき。
  • ここに書いてあることは決定事項ではないので、改善されるべきことがらである。
  • 規約はみんなのために

なぜ読みやすいテストを心がけるべきか

  • レビューし易いから
  • 仕様を理解しやすいから
  • 読みづらいと、仕様が複雑なのかテストの実装が複雑なのかがわからないから
  • メンテナンスしやすいから

規約

ディレクトリ構造

ディレクトリの階層、命名は、実装に合わせる。例えば、プロジェクトのルートディレクトリ直下で、

project/
  bin/
  lib/
    my_app/
      implementation.rb

というソースコードがあった場合、そのテストは、

project/
  spec/
    my_app/
      implementation_spec.rb

とする。 これは、

テストは仕様書である。

という考えに基づいて、実装とそれに対応する仕様が書かれている場所を類推しやすくするためである。

テストの構造
1つのspecファイルで取り扱うべきクラス、またはモジュールは1つのみ

実装においても、もともと1つのファイルに含まれている対象となるクラスはなるべく少ない方が分かりやすい。 行数が少なく、他に比べて関連性の高い複数のクラスまたはモジュールが1つのファイル内に納められることもあるが、この場合は、1つ前の規約を優先し、ファイル内。

一番外側のdescribeで対象となるクラスまたはモジュールを指定する。

例えば、my_app/implementation.rb に、

class MyApp::Implementation
end

spec/my_app/implementation_spec.rb 内では、

describe MyApp::Implementation do
  # examples 
end

のように書く。上述の通り、複数のクラスまたはモジュールが1つのファイルに実装されている場合、

describe MyApp::Implementation do
  # examples 
end

describe MyApp::Implementation::InnerModule do
  # examples 
end

のように実装する。

describeの内側には対象となるメソッドを書く。

以下のような実装にあるそれぞれのメソッドについて単体テストを書くとき、

class MyApp::Implementation
  def self.bar
  end

  def foo(arg1, arg2=nil)
  end
end

対象のメソッドごとにdescribe で宣言する。

describe MyApp::Implementation do
  describe '.bar' do
  end

  describe '#foo' do
  end
end

複数の条件をごとにテストする際には、contextを使いそれぞれの条件について宣言し、before を用いて前提条件を表現するコードを記述する。

describe MyApp::Implementation do
  describe '#foo' do
    let(:myapp) { MyApp::Implementation.new }

    context 'When given 1 arg' do
       before do
         myapp.foo('str')
       end
    end

    context 'When given 2 args' do
       before do
         myapp.foo('str', 1234)
       end
    end
  end
end
記述
記述の順序

describe ないし context の内部は、

  1. let または let!
  2. beforeafter または around
  3. もしあれば、 subject
  4. itまたはspecify
  5. describe または context

の順で記述する。

  • 各項目について連続して記述する場合、それぞれの記述の間に空行は入れず、
  • 異なる項目間に空行を入れる。
  • 項目2については、
    • beforeafteraround の順に、
    • それぞれ、:all、そして:each の順で記述する。
  • subject を用いる場合はitを、それ以外ではspecifyを使う。
describe MyApp::Implementation do
  describe '#foo' do
    let(:args1) { [:aaa] }
    let(:args2) { [:aaa, 1234] }

    subject { MyApp::Implementation.new }

    its(:foo) { should be_present }

    context 'Given 1 argument' do
    end

    context 'Given 2 arguments' do
    end  
end

おわりに

悩んだらBetter Specsを読むと、参考になることがたいてい書いてあるのですが、構造については見たことがないのでまとめてみました。

あれやこれやという議論のネタにしていただければ幸いです。

参考

Tags: Ruby RSpec TDD

2016年04月24日

_ 東京フィルハーモニーオーケストに行ってきた。

会社が賛助会に入っていたおかげで無料招待状を頂いたので、娘と二人で行ってきた。 昨年夏から娘がピアノを習い始めたので、プロの演奏を聴かせたいという趣旨。ちなみに、自分もオーケストラ鑑賞は初めて。

劇付随音楽『ペール・ギュント』 という、演奏だけでなく語りが含まれて、1つの物語になっていた。6歳の娘にはストーリーがよくわからず、音楽が楽しいという感じだった。 散々好き勝手やって遊び歩いておきながら、年老いて何に情熱を注ぐのかわからず故郷に戻って、若い時に捨てた恋人がそこで待っていてくれたなんて、待っていた方はどんな想いで待っていたのだろう。そして、ペールを看取った後、彼女はどうするのだろうか。普段は考えないようなことを色々と考えながら聴いていた*1

これまでこういう音楽とか演劇とか食わず嫌いだったのだけど、面白いと感じる自分が良い発見だった。

*1 前半は寝てた。

_ tDiary15周年パーティー … に行けなかった。

当初はtDiary15周年パーティーに出席しようと思っていたのですが、東京フィルハーモニーオーケストラの無料チケットを頂いてしまったので、欠席してしまった。普段、日曜日は子どもたちと過ごす時間に必ず充てるようにしているというのもある。

tDiary 歴、おおよそ10年くらい

自分がRubyを使い始めたのが高専5年生の時、つまり20歳からで、学部に編入してからレンタルサーバーでCGIを書いたりしてたと思う。当時はRubyがインストール済みのサーバーなんて、XREA.COMくらいしかなく、そこでtDiaryを起動したのを覚えている。しかし、これが何かのオペミスでふっ飛ばしてしまった。 その後、院生になってからは、WordPressに浮気してた。研究で使う言語はJavaで、研究のメモとかはHikiで記録してたり、データの集計や簡単なテキスト処理などでRubyはどこかしらで使っていた。 就職してからは、Rubyをメインで使うようになって、はてダでブログを書いたりしてた。 個人的にPaaSに興味を持ち始めて、Google App EngineにJRuby on Railsを動かしてみたりとかやっているうちに、Cloud FoundryでPaaS環境を社内に展開する部署に移った。なんとなしにtDiaryを調べてみたら、Herokuで動くとか書いてあったので、勢いでCloud Foundryでも動かすための手順を書いた。これが初めてtDiaryへのコミットとなった。VMwareがホスティングしているCloud Foundryが無料で使えたので、またtDiaryで日記を書き始めた。しかし、無料ホスティング終了のお知らせが来て、課金情報を登録しなかったせいで、インスタンスが消されてしまった。 その後、Redhatが提供しているPaaSのOpenShiftでtDiaryをセットアップして運用し始めた。OpenShiftは無料で提供してくれているのだが、Rubyのバージョンは古いままだし、rbenvでRubyをインストールしたあとにバージョンアップしようとすると、ディスクのquota値を越えてしまってインストールがこけたりと、面倒が多かった。そこで今年の初めに、Herokuへ引っ越しした。

ということで、途中間が空いたりはしたものの、tDiaryを10年くらい使ってきた。 ただ使うだけじゃなくて、GFMで書く際に発見したバグの修正とか、プラグインを書いたりとかコミットしてきた。なんというか、自分の考えを受け入れてくれるから愛着が湧いてくるように思う。そして、これからも使い続けるだろう。

15周年、おめでとうございます。そして、残り10年、何かできることからお手伝いしようかと思います。

Tags: tDiary

最近の投稿

翻訳しました(ちょっとだけ)

follow us in feedly