52
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

超シンプルなRuby向けテスティングライブラリ、TestRocketを使ってみた

Last updated at Posted at 2019-10-05

今週のRuby Weeklyで TestRocket というテスティングライブラリが紹介されていたので、試しに使ってみました。

対象となるバージョン

  • testrocket 1.0.0

セットアップ

gemをインストールすればOKです。

gem install testrocket

Bundlerを使う場合は、Gemfileに追加してbundle installしてください。

Gemfile
gem 'testrocket'

使い方

testrocket は Refinements を利用するので、次のようにテストを書きたいファイルでrequire&usingします。

# テストを書きたいファイルでrequire&using
require 'testrocket'
using TestRocket

Fizz Buzzプログラムをテストするならこんな感じになります。

fizz_buzz.rb
def fizz_buzz(n)
  if n % 15 == 0
    'Fizz Buzz'
  elsif n % 3 == 0
    'Fizz'
  elsif n % 5 == 0
    'Buzz'
  else
    n.to_s
  end
end

require 'testrocket'
using TestRocket

+-> { fizz_buzz(1) == '1' }
+-> { fizz_buzz(2) == '2' }
+-> { fizz_buzz(3) == 'Fizz' }
+-> { fizz_buzz(4) == '4' }
+-> { fizz_buzz(5) == 'Buzz' }
+-> { fizz_buzz(6) == 'Fizz' }
+-> { fizz_buzz(15) == 'Fizz Buzz' }

実行してみましょう。

$ ruby fizz_buzz.rb 
     OK
     OK
     OK
     OK
     OK
     OK
     OK

はい、実行できました。

試しに失敗させてみましょう。

+-> { fizz_buzz(1) == 'Hoge' }
$ ruby fizz_buzz.rb 
   FAIL @ fizz_buzz.rb:16
     OK
     OK
     OK
     OK
     OK
     OK
     OK

こんな感じで失敗します。

なお、テスト結果のサマリ(何件パスして、何件失敗したか、といった情報)は表示されないようです。

構文

テストを書くための構文は必要最小限です。
+-> {}でブロックが真を返せばパスするテストを、--> {}でブロックが偽を返すか、例外が発生したらパスするテストを書きます。

# ブロックが真を返せばパス
+-> { 1 + 1 == 2 }

# ブロックが偽を返すか、例外が発生したらパス
--> { 'abc'.nil? }
--> { 1 / 0 }

~-> {}でpendingするテストが書けます。

# このテストはpending
~-> { 1 + 1 == 2 }
$ ruby sample.rb
PENDING 'true' @ sample.rb:4

!-> {}はテストの説明(description)を書くために使います。

fizz_buzz.rb
# テストの説明
!-> { "test fizz buzz" }
# テスト本体
+-> { fizz_buzz(1) == '1' }
$ ruby fizz_buzz.rb
   FIRE 'test fizz buzz'!
     OK

用意されている構文はこれだけです。

応用

READMEの中ではクラスファイルの中でクラスの読み込みと同時にテストを実行する例が示されています。

user.rb
require 'testrocket'
using TestRocket

class User
  def initialize(name:, age:)
    @name = name
    @age = age
  end

  def greet
    if @age <= 12
      "ぼくは#{@name}だよ。"
    else
      "僕は#{@name}です。"
    end
  end
  # クラスファイル読み込み時にgreetメソッドのテストを実行する
  +-> { User.new(name: 'たろう', age: 12).greet == 'ぼくはたろうだよ。' }
  +-> { User.new(name: 'たろう', age: 13).greet == '僕はたろうです。' }
end
$ ruby user.rb
     OK
     OK

ただし、ENV['RACK_ENV']ENV['RAILS_ENV']が"production"を返したり、Rails.env.production?trueになる場合はテストを実行しません。(つまり、本番環境ではテストは実行されません)

また、テストを実行するためには、対象となるメソッドがすでに定義されている必要があるので、greetメソッドよりも手前にテストを書くとテストが失敗します。

user.rb
  # この時点ではgreetメソッドが定義されていないので、テストが失敗する
  +-> { User.new(name: 'たろう', age: 12).greet == 'ぼくはたろうだよ。' }
  +-> { User.new(name: 'たろう', age: 13).greet == '僕はたろうです。' }
  def greet
    if @age <= 12
      "ぼくは#{@name}だよ。"
    else
      "僕は#{@name}です。"
    end
  end
$ ruby user.rb
   FAIL @ user.rb:10
   FAIL @ user.rb:11

技術的な解説

+->{}-->{}はProcオブジェクトの単項演算子として定義されています。
つまり、Rubyの文法的には、+3-2と同じように、プラスのProcオブジェクト(+-> {})や、マイナスのProcオブジェクト(--> {})を書いていることになります。

ソースコードも超シンプル!

testrocket 1.0.0のソースコードは1ファイルのみで、わずか37行です。
実装も大変シンプルなので、コードリーディングの題材としてみるのも面白いかもしれません。

まとめ

というわけで、この記事では超シンプルなテスティングライブラリ、TestRocketを紹介してみました。

これでRailsアプリのテストを書け、と言われるとかなり難しいと思いますが、ごく単純なプログラミング問題をテスト駆動開発したりする場合は便利かもしれません。

興味を持った人はTestRocketで一度遊んでみてください!

52
29
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
52
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?