以前、FitNesseなどによるSpecification By Exampleで少し示した keyword driven testingは、入力値とその操作まで変数としてテストコードに与えることができていました。
このような形式で記述するテストは、「テストしたい対象のメソッドの入力とその期待値が異なる組み合わでいくつも存在するが、それらのテストを可読性の高い状態、簡潔な表現で保ちたい」というような場合に使えます。実際、開発速度が速い場合、仕様書を別ドキュメントとして厚く保つことは難しいと思います。その対策として、可読性の高いテストで低レベル(メソッドの入出力レベル)のテストはテストを仕様書に見立てていく、というアプローチが重要な一手となります。
以下は、パラメタライズドテストと呼ばれます。rspec-parameterized’というgemを使ってます。
検証コード
class Calculator
def self.calculator arithmetic, num1, num2
case arithmetic
when 'plus'
num1 + num2
when 'sub'
num1 - num2
end
end
end
簡単ですね。単に、2つの値の和/差を計算して返すメソッドです。それに対して、以下のテストコードを実施します。
テストコード
calculator_spec.rb
# coding: utf-8
require 'rspec-parameterized'
require './calculator'
## parameterized test
describe '.calculator arithmetic, num1, num2' do
where_table(:arithmetic, :num1, :num2, :expect_value) do
'plus' | 1 | 2 | 3
'sub' | 2 | 1 | 1
'plus' | [1, 2] | [3, 4] | [1, 2, 3, 4]
'sub' | [1, 2] | [1] | [2]
end
with_them do
it { expect(Calculator.calculator(arithmetic, num1, num2)).to eq expect_value }
end
end
## pure RSpec
describe '.calculator arithmetic, num1, num2' do
it 'num1 plus num2 is answer' do
expect(Calculator.calculator('plus', 1, 2)).to eq 3
end
it 'num1 sub num2 is answer' do
expect(Calculator.calculator('sub', 2, 1)).to eq 1
end
it 'array of num1 plus array of num2 is answer' do
expect(Calculator.calculator('plus', [1, 2], [3, 4])).to eq [1, 2, 3, 4]
end
it 'array of num1 sub array of num2 is answer' do
expect(Calculator.calculator('sub', [1, 2], [1])).to eq [2]
end
end
テストコードにはやってることは全く同じ2種類の記述スタイルで表現しています。pure RSpecはRSpecをそのまま適用したもの、parameterized testが今回いうパラメタライズドテストに沿って記載したテストです。
こうみると、パラメタライズドテストのほうがSpecification by Exampleな感じで、テストコードを内部処理の仕様書として見立ててドキュメントとして扱うこともできそうなですね。
1 Comment