LoginSignup
4
3

More than 3 years have passed since last update.

プッシュ時にRSpec+Rubocopを自動でするようにCircleCIでbuildする【Rails】

Last updated at Posted at 2020-12-01

はじめに

Railsでアプリを作っている初学者です。
アプリ内にCircleCIを使った自動テストを入れたい!と思い、導入してみましたので、その時に詰まったことをまとめました。

同じようにアプリにCircleCIを入れたいなと思っている方の参考になれば嬉しいです!!

また、間違い等がありましたらご指摘いただけますと幸いです。

バージョン

Ruby:2.6.6
Rails:5.2.4
Mysql:5.7
環境構築にDocker使用

前提

以下は題名のことをしたい場合&CircleCIを理解する上で必要です!

・Dockerを使用したことがある
・Rspecを導入済
・Rubocopを導入済
・Githubアカウントがある

まず、CircleCIの公式入門ガイドをすることをおすすめします!自分は実際の挙動があまりイメージ出来なかったのですが、これでざっくり理解することができました。

CircleCI入門ガイド:https://circleci.com/docs/ja/2.0/getting-started/

そして入門ガイドをしたところで、CircleCIをアプリに加えてみます。
ルートディレクトリに .circleci フォルダを作成してコンフィグを作る。
そしてデータベースを作る、とできるはず!

うまくいかなかったパターン

参考:CircleCIでSystemSpec(RSpec)とRubocopを走らせる
https://qiita.com/YK0214/items/bbed63ea7ca5367dae2f

まず、こちらのQiitaの記事を参考にしましたが、自分の環境ではうまくいきませんでした。
ですが、こちらの経緯も記録しておきます。

config.ymlを作る

.circleci\config.yml
version: 2.1

orbs:
  ruby: circleci/ruby@1.1.0

jobs:
  build:
    docker:
      - image: circleci/ruby:2.6.6-node-browsers
        environment:
          BUNDLER_VERSION: 2.1.4
    steps:
      - checkout
      - ruby/install-deps

 test:
    parallelism: 3
    docker:
      - image: circleci/ruby:2.5.1-node-browsers
        environment:
          DB_HOST: 127.0.0.1
          RAILS_ENV: test
          BUNDLER_VERSION: 2.1.4
      - image: circleci/mysql:5.7
        command: --default-authentication-plugin=mysql_native_password
        environment:
          MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
          MYSQL_ROOT_HOST: '%'
    steps:
      - checkout
      - ruby/install-deps
      - run: mv config/database.yml.ci config/database.yml
      - run:
          name: Wait for DB
          command: dockerize -wait tcp://localhost:3306 -timeout 1m
      - run: bundle exec rake db:create
      - run: bundle exec rake db:schema:load
      # Run rspec in parallel
      - ruby/rspec-test
      - ruby/rubocop-check

workflows:
  version: 2
  build_and_test:
    jobs:
      - build
      - test:
          requires:
            - build

引用:CircleCIでSystemSpec(RSpec)とRubocopを走らせる
https://qiita.com/YK0214/items/bbed63ea7ca5367dae2f

database.yml.ciを作る

すでにconfig内にdatabase.ymlがあるけど、それとは別で新規で作ります。
新規のDockerfileを使うのでデータベースも新しくなります。

config\database.yml.ci
test:
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: 'root'
  port: 3306
  host: '127.0.0.1'
  database: ci_test

引用:CircleCIでSystemSpec(RSpec)とRubocopを走らせる
https://qiita.com/YK0214/items/bbed63ea7ca5367dae2f

Githubへプッシュして、マージするとCircleCIで自動でBuildされます
失敗している!!!

Qiita用画像CircleCI1.png

Bundleのバージョンが違うみたい。

ちょっと変更

.circleci\config.yml

version: 2.1

orbs:
  ruby: circleci/ruby@1.1.0

jobs:
  build:
    docker:
      - image: circleci/ruby:2.6.6-node-browsers
        environment:
          BUNDLER_VERSION: 1.17.2
    steps:
      - checkout
      - ruby/install-deps

  test:
    parallelism: 3
    docker:
      - image: circleci/ruby:2.5.1-node-browsers
        environment:
          DB_HOST: 127.0.0.1
          RAILS_ENV: test
          BUNDLER_VERSION: 2.1.4
      - image: circleci/mysql:5.7
        command: --default-authentication-plugin=mysql_native_password
        environment:
          MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
          MYSQL_ROOT_HOST: '%'
    steps:
      - checkout
      - ruby/install-deps
      - run: mv config/database.yml.ci config/database.yml
      - run:
          name: Wait for DB
          command: dockerize -wait tcp://localhost:3306 -timeout 1m
      - run: bundle exec rake db:create
      - run: bundle exec rake db:schema:load
      # Run rspec in parallel
      - ruby/rspec-test
      - ruby/rubocop-check

workflows:
  version: 2
  build_and_test:
    jobs:
      - build
      - test:
          requires:
            - build

BUNDLER_VERSION: 1.17.2に変更して再Push

Qiita用画像CircleCI3.png

これでできた!!!と思ってshow all checkをクリックして確認すると、
途中でbuildが止まっています...!

qiita circleCI1.png

よくよく見たらこんな記載が。

Qiita用画像CircleCI.png

これは有料枠にしろということですね!?
無料枠ではコンテナ1つでないと動かないのですが、このコードは2つのDockerを起動させようとしています。
なので途中で止まっていたんだなあということがわかりました...

というわけで修正を行います

うまくいったパターン

今度はこちらの記事を参考に、config.ymlを作成します。
エラーがいくつか出たので最終的には細かく修正を加えています。

参考:CicleCIでRspecとRubocop通すまでにつまずいたところとその解決法
https://qiita.com/naota7118/items/056770bcf53136e94788

.circleci/config.yml
# CircleCIのバージョンのことで、「2」、「2.0」、「2.1」のうちのどれかを指定します。
version: 2.1

orbs:
  ruby: circleci/ruby@1.1.0

# jobsは、実行処理の単位です。
jobs:
  build:
    # DockerでRubyのイメージを作成します。Dockerfileもしくはローカル環境とVersionは合わせること。
    docker:
      - image: circleci/ruby:2.6.6-node-browsers
        environment:
          # Dockerで作った、circleCI上で'bundle install'します
          BUNDLER_VERSION: 1.17.2
    steps:
      - checkout
      - ruby/install-deps

test:
    parallelism: 3
    docker:
      - image: circleci/ruby:2.5.1-node-browsers
        environment:
          DB_HOST: 127.0.0.1
          RAILS_ENV: test
          BUNDLER_VERSION: 2.1.4
      - image: circleci/mysql:5.7
        command: --default-authentication-plugin=mysql_native_password
        environment:
          MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
          MYSQL_ROOT_HOST: '%'
    steps:
      - checkout
      - ruby/install-deps
      - run: mv config/database.yml.ci config/database.yml
      - run:
          name: Wait for DB
          command: dockerize -wait tcp://localhost:3306 -timeout 1m
      - run: bundle exec rake db:create
      - run: bundle exec rake db:schema:load
      # Run rspec in parallel
      - ruby/rspec-test
      - ruby/rubocop-check

workflows:
  version: 2
  build_and_test:
    jobs:
      - build
      - test:
          requires:
            - build

引用:CicleCIでRspecとRubocop通すまでにつまずいたところとその解決法
https://qiita.com/naota7118/items/056770bcf53136e94788

公式:CircleCI-Public/circleci-demo-ruby-rails
https://github.com/CircleCI-Public/circleci-demo-ruby-rails/blob/master/config/database.yml

参考:【CircleCI】Railsアプリに導入(設定ファイルについて)
https://qiita.com/Daiki-Abe/items/d90599d904c2b1370d10

というわけで修正

①bundle exec rake:db migrateを追加

マイグレーションされていないというエラーが出ているので、上記のファイルの中に
bundle exec rake:db migrateを追加します

②細かすぎるgemまで見ているのでRubocopを編集

migrateが無事されましたが、今度はRubocopでエラーがでました。
エラー文は以下。

For more information: https://docs.rubocop.org/rubocop/versioning.html 
vendor/bundle/ruby/2.6.0/gems/msgpack-1.3.3/.rubocop.yml: Lint/Eval has the wrong namespace - should be Security 
Error: RuboCop found unsupported Ruby version 2.3 in `TargetRubyVersion` parameter (in vendor/bundle/ruby/2.6.0/gems/msgpack-1.3.3/.rubocop.yml). 2.3-compatible analysis was dropped after version 0.81. 
Supported versions: 2.4, 2.5, 2.6, 2.7, 3.0

Rubocop.ymlでrubyバージョンの指定をすることで解決しました

AllCops:
  # Rubyバージョン指定
  TargetRubyVersion: 2.6

参考:原因と対応「Error: RuboCop found unsupported Ruby version 2.1」
https://blog.mothule.com/ruby/rubocop/ruby-rubocop-found-unsupported-ruby-version

buildには失敗してるけどRubocopは通っています!

次はRSpecですがここでもエラーが出ています。

③RSpecのmysql2::Error::ConnectionError:を解消する

②のエラーを直したあとにrspecを実行すると、エラーがでるようになりました
rspecの実行結果は以下です。

PS C:\Users\> rspec
An error occurred while loading ./spec/features/toppage_spec.rb.
Failure/Error: ActiveRecord::Migration.maintain_test_schema!

Mysql2::Error::ConnectionError:
  Unknown MySQL server host 'db' (0)
# ./spec/rails_helper.rb:28:in `<top (required)>'
# ./spec/features/toppage_spec.rb:1:in `<top (required)>'

Top 0 slowest examples (0 seconds, 0.0% of total time):

Finished in 0.00009 seconds (files took 3 minutes 27 seconds to load)

0 examples, 0 failures, 1 error occurred outside of examples

databese.ymlに以下を加えることで解決しました。

databese.yml
test:
  <<: *default
  database: Music-record_test
  host: <%= ENV['MYSQL_ROOT_HOST'] || '127.0.0.1' %>

参考:ローカル環境のCircleCIでMysql2::Error::ConnectionError: Unknown MySQL server host 'db' (-2)が出る
https://qiita.com/mitsu1208g/questions/c9681d1204a1b878f987

④RSpecのエラー LoadError: cannot load such file -- rspec_junit_formatterの解消

次はCircleCIでのRSpecでエラーがでました。


Error reading historical timing data: file does not exist
Requested weighting by historical based timing, but they are not present. Falling back to weighting by name.
No examples found.
bundler: failed to load command: rspec (/home/circleci/repo/vendor/bundle/ruby/2.6.0/bin/rspec)
LoadError: cannot load such file -- rspec_junit_formatter
  /home/circleci/repo/vendor/bundle/ruby/2.6.0/gems/rspec-core-3.9.3/lib/rspec/core/formatters.rb:235:in `require'
  /home/circleci/repo/vendor/bundle/ruby/2.6.0/gems/rspec-core-
・
・
・

  /home/circleci/repo/vendor/bundle/ruby/2.6.0/gems/rspec-core-3.9.3/lib/rspec/core/runner.rb:45:in `invoke'
  /home/circleci/repo/vendor/bundle/ruby/2.6.0/gems/rspec-core-3.9.3/exe/rspec:4:in `<top (required)>'
  /home/circleci/repo/vendor/bundle/ruby/2.6.0/bin/rspec:23:in `load'
  /home/circleci/repo/vendor/bundle/ruby/2.6.0/bin/rspec:23:in `<top (required)>'

Exited with code exit status 1
CircleCI received exit code 1

Uploading test results
0s

Uploading artifacts
0s

LoadError: cannot load such file -- rspec_junit_formatter
この1文がエラーの原因のようです。

rspec_junit_formatterがないということで以下の記事を参考にGemを追加します。

参考:CI/CD環境を作った時に起きたエラー備忘録[Rails + CircleCI +Capistrano +AWS]
https://qiita.com/orangeupup90027/items/6f83850d1842adf3c09a

① rspec_junit_formatterがないと言われる
テストを走らせた時に出たエラー

Error reading historical timing data: file does not exist
Requested weighting by historical based timing, but they are not present. Falling back to >weighting by name.
No examples found.
bundler: failed to load command: rspec (/home/circleci/circleci-demo-ruby->rails/vendor/bundle/ruby/2.5.0/bin/rspec)
LoadError: cannot load such file -- rspec_junit_formatter

結論としてはrspec_junit_formatterをgemfileに追加する。

Gemfileにrspec_junit_formatterを追加します。

Gemfile
group :test do
  # Adds support for Capybara system testing and selenium driver
  gem 'capybara', '>= 2.15'
  gem 'selenium-webdriver'
  # Easy installation and use of chromedriver to run system tests with Chrome
  # gem 'chromedriver-helper'
  gem 'rspec_junit_formatter' #追加
  gem 'webdrivers', '~> 3.0'
end

これでGithubにプッシュするとCircleCIの画面はこのようになりました。

CircleCIde.png

長くなりましたが、これでCircleCIでBuildができました!

最終的なコード

細かな修正を入れた結果が以下です。

※CircleCIはインデントに厳しい&文字列のブロックの別れ方がシビアなので、実際にコードをコピー・記載するときはコメントなしの方が良いです。

circleci\config.yml
# CircleCIのバージョンのことで、「2」、「2.0」、「2.1」のうちのどれかを指定します。
version: 2

jobs:
  build:
    docker:
      - image: circleci/ruby:2.6.6-node-browsers
        environment:
          - RAILS_ENV: 'test'
          - MYSQL_HOST: 127.0.0.1
          - MYSQL_USERNAME: 'root'
          - MYSQL_PASSWORD: ''
          - MYSQL_PORT: 3306
      - image: circleci/mysql:5.7
        environment:
          - MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
          - MYSQL_ROOT_HOST: '%'
    working_directory: ~/repo
    steps:
      - checkout
      - restore_cache:
          keys:
            - v1-dependencies-{{ checksum "Gemfile.lock" }}
            - v1-dependencies-
      - run:
          name: install dependencies
          command: |
            bundle install --jobs=4 --retry=3 --path vendor/bundle
      - save_cache:
          paths:
          - ./vendor/bundle
          key: v1-dependencies-{{ checksum "Gemfile.lock" }}
      - run: mv config/database.yml.ci config/database.yml
      - run: bundle exec rake db:create
      - run: bundle exec rake db:migrate
      - run: bundle exec rake db:schema:load
      - run:
          name: RuboCop
          command: bundle exec rubocop
      - run:
          name: RSpec
          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 \
              --format progress \
              $TEST_FILES

      - store_test_results:
          path: /tmp/test-results
      - store_artifacts:
          path: /tmp/test-results
          destination: test-results

config\database.yml.ci

test: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: <%= ENV.fetch("MYSQL_USERNAME") %>
  password: <%= ENV.fetch("MYSQL_PASSWORD") %>
  host: <%= ENV.fetch("MYSQL_HOST") %>
  port: <%= ENV.fetch("MYSQL_PORT") %>
  database: ci_test

ここまでお付き合いいただきありがとうございます!

参考

【circleCI】Railsアプリでgithubと連携してrubocopとrspecテストを走らせる
https://qiita.com/AK4747471/items/b2161784065f21cd1645

CicleCIでRspecとRubocop通すまでにつまずいたところとその解決法
https://qiita.com/naota7118/items/056770bcf53136e94788

【CircleCI】Railsアプリに導入(設定ファイルについて)
https://qiita.com/Daiki-Abe/items/d90599d904c2b1370d10#databaseymlci%E3%82%92%E4%BD%9C%E6%88%90

【初心者向け】deviseのユーザー登録をRSpecでテストする
https://qiita.com/HiMinmeg/items/37a59cd266c63330797a#%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B32!

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