この記事には広告を含む場合があります。
記事内で紹介する商品を購入することで、当サイトに売り上げの一部が還元されることがあります。
この記事ではRailsAPIをRspecとcircleCIで自動テストする方法を紹介します。
読者
そのような要望にお答えします!
経緯
弊社サービスは今までテストを全て手動で行なっていたのですが、細かいコード修正でもいちいちテストするのが面倒になってきたのでテストを自動化させようというお話しになりました。
というか自分が提案しました。多分提案しなければこの先も永遠と手動でテストしていたと思います…
皆さんの会社ではどうですか?テスト書いてますか?自動化してますか?
今時自動テストを導入してない会社なんてないんじゃね…?と自分は思ってますが実際どうなんでしょう。
テストを書くメリット
昔はテスト書かなくて良い派だったんですけど、今は書くべきだと思ってます。
テストを書くメリットは主に2つあります。
- テストコードが仕様書になる
- 長い目で見ると実装時間を大幅に削減できる
テストコードが仕様書になる
弊社はRailsをAPIとして使っていますが、人によってレスポンスの書き方がバラバラだったり返すべきものが間違っていたり統一感のないコードになっていました。(現在少しずつ修正しています)
例えばパラメータが不足していてエラーになる場合は400(不正なリクエスト)を返すべきなのに何も処理が施されておらず、コードエラー500が返る仕様になっていたり。
そういった細かな仕様をテストコードを書く時に決めておくことで、誰しもが最低限の正しい実装をするようになります。
実装前にテストを書いておくことで、何を返すべきなのか?どうするべきなのか?迷った時にテストを見れば分かるようになるので絶対テストコードは書いた方が良いと思います。
ただテストを書く分の工数はかかるので、プロジェクトによっては先に実装してからテストを書くというパターンもありますし、レアケースですが弊社のようにベンチャーで人が足りていない場合やスピード命!みたいなプロジェクトでは書かないこともあるみたいです。
実装時間を大幅に削減できる
自分はサーバーサイド担当でRailsのAPIを書くことが多いのですが、実装は速攻で終わってもテストでその何倍も時間をかけることが多かったです。
例えば検索機能で全パターン試す…なんて時はまじで面倒です。
テストコードは最初の工数がかかりますが、書いてしまえばそれ以降は自動化できるので長期的に見ると大幅な工数削減になります。
実際導入して1ヶ月ぐらい経ちますがめちゃくちゃ楽です。
ほろよい
それでは実際に導入した時の手順を以下にまとめておきます。
環境
- ruby 2.4.3
- Rails 5.1.6.1
Rspecの導入
gemの追加
$vim Gemfile group :test do gem 'rspec-rails' gem 'factory_bot_rails' end
bundle install
$bundle install
設定ファイルの生成
$bundle exec rails g rspec:install create .rspec create spec create spec/spec_helper.rb create spec/rails_helper.rb
設定ファイルの編集
$vim .rspec require --rails_helper
$vim spec/spec_helper.rb RSpec.configure do |config| #factory_botを使用するための設定を追加する config.before(:all) do FactoryBot.reload end end
テスト用データの意義
テストを始めるにはあらかじめデータが入っていなければなりません。
テスト用データのモデルを作ります。
$vim spec/factories/users.rb FactoryBot.define do factory :user do name{"テストユーザ"} auth_token{"auth_token"} end end
$vim spec/factories/feed_posts.rb FactoryBot.define do factory :feed_post do :user description{"テスト"} end end
テスト用ファイルを生成
$mkdir -p spec/requests/api $touch spec/requests/api/feed_posts_spec.rb
$vim spec/requests/api/feed_posts_spec.rb
describe "#show" do
let(:post){create(:feed_post, user: user)}
context "全てのパラメータが揃っている場合" do
it "200を返す" do
get api_feed_post_path(post.id), params: {auth_token:"auth_token", version: "ios_3.7.0"}
expect(response.status).to eq(200)
expect(JSON.parse(response.body).keys).to include("post_info","comment_info","user_info")
end
end
context "全てのパラメータが揃っているが、フィードが存在しなかった場合" do
it "404を返す" do
get api_feed_post_path(0), params: {auth_token:"auth_token", version: "ios_3.7.0"}
expect(response.status).to eq(404)
end
end
context "パラメータが不足している場合" do
it "400を返す" do
get api_feed_post_path(post.id), params: {auth_token:"auth_token"}
expect(response.status).to eq(400)
end
end
end
テスト実行
$bundle exec rspec spec/requests/api/feed_posts_spec.rb
circleCIの導入
GithubとcircleCIの連携
こちらhttps://circleci.com/signup/の「Sign up with GitHub」から登録します。
最初の方のセットアップはちょっと覚えてないので他記事を参考にしてください。でも確か特に設定は無かったと思います。
左のサイドバー「Add Project」からcircleCIと連携したいリポジトリを追加します。
circleCIで必要になるgem追加
group :test do gem 'rspec-rails' gem 'factory_bot_rails' gem "rspec_junit_formatter" //追加 end
bundle install
$bundle install
.circleci/config.ymlの作成
version: 2 jobs: build: docker: - image: circleci/ruby:2.4.4-node-browsers environment: BUNDLER_VERSION: 2.0.2 RAILS_ENV: test - image: circleci/mysql:5.7.22 working_directory: ~/repo steps: - checkout - run: name: setup bundler command: | sudo gem update --system sudo gem install bundler -v 2.0.2 - restore_cache: keys: - v1-dependencies-{{ checksum "Gemfile.lock" }} - v1-dependencies- - run: name: install dependencies command: | bundle install --path vendor/bundle - save_cache: paths: - ./vendor/bundle key: v1-dependencies-{{ checksum "Gemfile.lock" }} - run: mv config/database.yml.ci config/database.yml - run: name: database create command: | dockerize -wait tcp://127.0.0.1:3306 -timeout 120s bundle exec rake db:create bundle exec rake db:schema:load - run: name: run tests command: | mkdir /tmp/test-results TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | \ circleci tests split --split-by=timings)" bundle exec rspec \ --format progress \ --format RspecJunitFormatter \ --out /tmp/test-results/rspec.xml \ $TEST_FILES - store_test_results: path: /tmp/test-results - store_artifacts: path: /tmp/test-results destination: test-results
database.yml.ciの作成
test: adapter: mysql2 encoding: utf8 pool: 5 username: 'root' port: 3306 host: '127.0.0.1' database: ci_test test_slave: adapter: mysql2 encoding: utf8 pool: 5 username: 'root' port: 3306 host: '127.0.0.1' database: ci_test
Gitにプッシュ
これでリポジトリにプッシュする度、circleCI上でテストが実行されます!
まとめ
設定ファイルの書き方で少しつまづきましたが、日本語の公式ドキュメントがあるのでなんとかなりました。
終わってみると実装自体はむちゃくちゃ簡単だなーって感じです。
未経験でポートフォリオを作っている人はテスト自動化してみると面接で評価してもらえるかもしれないのでやってみることをお勧めします!
ほろよい