LoginSignup
6
3

More than 5 years have passed since last update.

コンポーネント間結合テスト自動化目的でのTurnipの利用検討

Posted at

はじめに

そこそこの規模のシステムのコンポーネント間のテストにTurnipがどの程度適合するか試しています。各コンポーネント間でのデータはHTTP APIコールやファイルなどでやりとりするようなシステムが前提です。筆者はRubyについては初心者に毛が生えない程度ですがその他よさそうなツールがないので見よう見まねで使おうという算段です。

目的

  • (1)テストケース作成→(2)テスト準備→(3)テスト実行→(4)テスト結果記入 のステップを極力自動化したい
    • (1)(4)のためにExcelでテスト仕様書を書くのをやめたい
      • (2)のアウトプットが(3)で直接実行可能なように記述できる
      • (2)のアウトプットが可読性が高く(1)の代わりになる
      • (3)のアウトプットがそのまま(4)の代替になる

利用ツールの検討

上記目的を満たすものとして、受入テストに使うような、要求仕様にたいしてブラックボックステストをするようなツールの利用について検討をしました。

各ツールについての検討

ということで日本語でシナリオが記述できて目的とも合致しやすそうなCucumberの利用を検討しましたが、以下の記事を読んで、さらにとっつきやすそうなTurnipを利用することにしました。

Turnip のインストールとテスト

こちらを参考にインストールを進めます。
Turnip について (1) / まずは動かす

環境

  • Amazon Linux AMI release 2016.09
    • kernel: 4.4.41-36.55.amzn1.x86_64

手順

rubyのバージョン確認

$ ruby -v
ruby 2.0.0p648 (2015-12-16) [x86_64-linux]

事前準備

Gemfile

$ mkdir turnip_example
$ cd turnip_example/
$ mkdir spec
$ cat > Gemfile
Gemfile
source 'https://rubygems.org'

gem 'turnip'

.rspec

$ cat > .rspec
.rspec
-r turnip/rspec
--color
--format documentation

spec_helper.rb

$ cat > spec/spec_helper.rb
spec/spec_helper.rb
require 'rubygems'
require 'bundler/setup'

Dir.glob("spec/steps/**/*steps.rb") { |f| load f, true }

Bundle Exec Rspec spec//.featureが失敗する件
のよう .rspec に turnipだけしか記載しないと実行に失敗しました。
rspecのフォーマットについては RSpecを斬る > フォーマット指定 を参考にしました。

bundleがないのでインストール

$ gem install bundler
Fetching: bundler-1.14.3.gem (100%)
Bundler and RubyGems.org are free for anyone to use, but maintaining them costs more than $25,000 USD every month. Help us cover those costs so that we can keep the gem ecosystem free for everyone: https://ruby.to/support-bundler
Successfully installed bundler-1.14.3
Parsing documentation for bundler-1.14.3
Installing ri documentation for bundler-1.14.3
Done installing documentation for bundler after 5 seconds
1 gem installed

ただインストールしただけでは動かないので以下を参考に追加インストール

EC2でBundle Installすると、io/consoleエラーになる
Amazon Linuxでbundle installのエラーに対処する

$ sudo yum install -y ruby-devel
$ gem install io-console

ようやくturnipのインストールができます

$ bundle install --path vendor/bundle
Fetching gem metadata from https://rubygems.org/............
Fetching version metadata from https://rubygems.org/..
Resolving dependencies...
Rubygems 2.0.14.1 is not threadsafe, so your gems will be installed one at a time. Upgrade to Rubygems 2.1.0 or higher to enable parallel gem installation.
Installing diff-lcs 1.3
Installing multi_json 1.12.1
Installing rspec-support 3.5.0
Using bundler 1.14.3
Installing gherkin 2.12.2 with native extensions
Installing rspec-core 3.5.4
Installing rspec-expectations 3.5.0
Installing rspec-mocks 3.5.0
Installing rspec 3.5.0
Installing turnip 2.1.1
Bundle complete! 1 Gemfile dependency, 10 gems now installed.
Bundled gems are installed into ./vendor/bundle.

このあとbundle exec rspecするとインストールされたmulti_jsonが毎回WARNINGを吐いてうっとおしいのでvendor/bundle以下のファイルを直接コメントアウトしました。
MultiJson is using the default adapter (ok_json). We recommend loading a different JSON library to improve performance.

featuresファイルの作成

$ mkdir spec/features
$ cat > spec/features/aggregation.feature

テストとして、以下のようなウェブサーバにユーザからリクエストが飛んで、そのリクエストのログが集計用の別コンポーネントで正常に集計されているかどうかを確認する機能のシナリオを作成しました。

aggregation.feature
Feature: リクエスト集計

  Background:
   Given 各サービスが正常動作

  Scenario: 1リクエストが正常に集計される
    Given 1ユーザが1リクエスト
    When 集計処理が完了
    Then 集計結果に反映

  Scenario: 複数リクエストが正常に集計される
    Given 3ユーザが各々5リクエスト
    When 集計処理が完了
    Then 集計結果に反映

  Scenario: 不正なリクエストは集計から除外される
    Given 不正なリクエスト
    When 集計処理が完了
    Then 集計結果に反映されない
$ mkdir spec/steps
$ cat > spec/steps/aggregation_steps.rb

各ステップは以下のように定義しました。

aggregation_steps.rb
# coding: utf-8

step "各サービスが正常動作" do
  # ウェブサービスの正常動作確認
  # 集計サービスの正常動作確認
end

step "1ユーザが1リクエスト" do
  # 期待する結果の差分は1リクエスト
  @expected_diff = 1
  # 現在のリクエスト数を取得する処理
  @original_count = 1323
  # サーバへのHTTPリクエスト実施
end

step "3ユーザが各々5リクエスト" do
  # 期待する結果の差分は1リクエスト
  @expected_diff = 15
  # 現在のリクエスト数を取得する処理
  @original_count = 1309
  # サーバへのHTTPリクエスト実施
end

step "不正なリクエスト" do
  # 期待する結果の差分は0リクエスト
  @expected_diff = 0
  # 現在のリクエスト数を取得する処理
  @original_count = 1324
  # サーバへのHTTPリクエスト実施
end

step "集計処理が完了" do
  # 集計処理完了待ち
  # 集計処理完了後結果取得
  @current_count = 1324
end

step "集計結果に反映" do
  @actual_diff = @current_count - @original_count
  expect(@actual_diff).to be == @expected_diff
end

step "集計結果に反映されない" do
  @actual_diff = @current_count - @original_count
  expect(@actual_diff).to be == 0
end

実行します

$ bundle exec rspec

リクエスト集計
  1リクエストが正常に集計される
    Given 各サービスが正常動作 -> Given 1ユーザが1リクエスト -> When 集計処理が完了 -> Then 集計結果に反映
  複数リクエストが正常に集計される
    Given 各サービスが正常動作 -> Given 3ユーザが各々5リクエスト -> When 集計処理が完了 -> Then 集計結果に反映
  不正なリクエストは集計から除外される
    Given 各サービスが正常動作 -> Given 不正なリクエスト -> When 集計処理が完了 -> Then 集計結果に反映されない

Finished in 0.0047 seconds (files took 0.22233 seconds to load)
3 examples, 0 failures

意図的にエラーを起こすようにした例(長い)

"集計処理が完了"の@current_count値をいじって意図的にエラーを出すようにします。

$ bundle exec rspec

リクエスト集計
  1リクエストが正常に集計される
    Given 各サービスが正常動作 -> Given 1ユーザが1リクエスト -> When 集計処理が完了 -> Then 集計結果に反映 (FAILED - 1)
  複数リクエストが正常に集計される
    Given 各サービスが正常動作 -> Given 3ユーザが各々5リクエスト -> When 集計処理が完了 -> Then 集計結果に反映 (FAILED - 2)
  不正なリクエストは集計から除外される
    Given 各サービスが正常動作 -> Given 不正なリクエスト -> When 集計処理が完了 -> Then 集計結果に反映されない (FAILED - 3)

Failures:

  1) リクエスト集計 1リクエストが正常に集計される Given 各サービスが正常動作 -> Given 1ユーザが1リクエスト -> When 集計処理が完了 -> Then 集計結果に反映
     Failure/Error: expect(@actual_diff).to be == @expected_diff

       expected: == 1
            got:    -2
     # spec/steps/aggregation_steps.rb:40:in `block in <top (required)>'
     # ./vendor/bundle/ruby/2.0/gems/turnip-2.1.1/lib/turnip/execute.rb:25:in `step'
     # ./spec/features/aggregation.feature:9:in `run_step'
     # ./vendor/bundle/ruby/2.0/gems/turnip-2.1.1/lib/turnip/rspec.rb:44:in `instance_eval'
     # ./vendor/bundle/ruby/2.0/gems/turnip-2.1.1/lib/turnip/rspec.rb:44:in `run_step'
     # ./spec/features/aggregation.feature:8:in `block (4 levels) in run_feature'
     # ./spec/features/aggregation.feature:7:in `each'
     # ./spec/features/aggregation.feature:7:in `block (3 levels) in run_feature'
     # ./spec/features/aggregation.feature:9:in `集計結果に反映'

  2) リクエスト集計 複数リクエストが正常に集計される Given 各サービスが正常動作 -> Given 3ユーザが各々5リクエスト -> When 集計処理が完了 -> Then 集計結果に反映
     Failure/Error: expect(@actual_diff).to be == @expected_diff

       expected: == 15
            got:    12
     # spec/steps/aggregation_steps.rb:40:in `block in <top (required)>'
     # ./vendor/bundle/ruby/2.0/gems/turnip-2.1.1/lib/turnip/execute.rb:25:in `step'
     # ./spec/features/aggregation.feature:14:in `run_step'
     # ./vendor/bundle/ruby/2.0/gems/turnip-2.1.1/lib/turnip/rspec.rb:44:in `instance_eval'
     # ./vendor/bundle/ruby/2.0/gems/turnip-2.1.1/lib/turnip/rspec.rb:44:in `run_step'
     # ./spec/features/aggregation.feature:13:in `block (4 levels) in run_feature'
     # ./spec/features/aggregation.feature:12:in `each'
     # ./spec/features/aggregation.feature:12:in `block (3 levels) in run_feature'
     # ./spec/features/aggregation.feature:14:in `集計結果に反映'

  3) リクエスト集計 不正なリクエストは集計から除外される Given 各サービスが正常動作 -> Given 不正なリクエスト -> When 集計処理が完了 -> Then 集計結果に反映されない
     Failure/Error: expect(@actual_diff).to be == 0

       expected: == 0
            got:    -3
     # spec/steps/aggregation_steps.rb:45:in `block in <top (required)>'
     # ./vendor/bundle/ruby/2.0/gems/turnip-2.1.1/lib/turnip/execute.rb:25:in `step'
     # ./spec/features/aggregation.feature:19:in `run_step'
     # ./vendor/bundle/ruby/2.0/gems/turnip-2.1.1/lib/turnip/rspec.rb:44:in `instance_eval'
     # ./vendor/bundle/ruby/2.0/gems/turnip-2.1.1/lib/turnip/rspec.rb:44:in `run_step'
     # ./spec/features/aggregation.feature:18:in `block (4 levels) in run_feature'
     # ./spec/features/aggregation.feature:17:in `each'
     # ./spec/features/aggregation.feature:17:in `block (3 levels) in run_feature'
     # ./spec/features/aggregation.feature:19:in `集計結果に反映されない'

Finished in 0.01192 seconds (files took 0.18849 seconds to load)
3 examples, 3 failures

Failed examples:

rspec ./spec/features/aggregation.feature:6 # リクエスト集計 1リクエストが正常に集計される Given 各サービスが正常動作 -> Given 1ユーザが1リクエスト -> When 集計処理が完了 -> Then 集計結果に反映
rspec ./spec/features/aggregation.feature:11 # リクエスト集計 複数リクエストが正常に集計される Given 各サービスが正常動作 -> Given 3ユーザが各々5リクエスト -> When 集計処理が完了 -> Then 集計結果に反映
rspec ./spec/features/aggregation.feature:16 # リクエスト集計 不正なリクエストは集計から除外される Given 各サービスが正常動作 -> Given 不正なリクエスト -> When 集計処理が完了 -> Then 集計結果に反映されない

まとめ

作成中

6
3
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
6
3