とーますメモ

Ruby on Rails / Goなどの学習メモ

【RSpec】テスト時に他のDBと同じデータを使いたい!

結論から書くと以下。

1)seed_dumpでDBからデータを抽出
2)db:seed用のrakeタスクを作成
3)1)で作成したファイルを指定し、データを挿入

FactoryBot(旧:FactoryGirl)では面倒くさい時、
開発用などデータが入っているDBのデータを、
そのまま利用したい時は、この方法が役立つ。

1)seed_dumpでDBからデータを抽出

インストール

gem 'seed_dump'

seed_dumpをデフォルトで使用するとdb/seeds.rbを上書きするので、
以下のように書き出し先を指定して、DBからseedファイルを作成する。
※seedsディレクトリは予め作成しておく。

$ bundle exec rake db:seed:dump FILE=db/seeds/20171212_all.rb

デフォルトだと、全テーブルを抽出するが
もちろん、抽出するモデルを指定したり、件数を指定することもできる。
詳細は以下。

github.com

2)db:seed用のrakeタスクを作成

やり方は下記のサイトさんのやり方をそのまま利用すればよい。
qiita.com

lib/tasks/seed.rakeを作成

Dir.glob(File.join(Rails.root, 'db', 'seeds', '*.rb')).each do |file|
  desc "Load the seed data from db/seeds/#{File.basename(file)}."
  task "db:seed:#{File.basename(file).gsub(/\..+$/, '')}" => :environment do
    load(file)
  end
end

3)1)で作成したファイルを指定し、データを挿入

後はファイルを指定して、流すだけ。(注: [.rb]は不要)

$ bundle exec rake db:seed:20171212_all RAILS_ENV=test

【CircleCI2.0】Rspecの並行テストの設定

RailsのCircleCIのサンプルyml(Sample.yml)を見ると
以下のような記述がある

# run tests!
- 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 \
                      --format progress \
                      "${TEST_FILES}"

初見では、正直何をやってるのかわからなかったが
rspecでテストを行っているコードなのはわかる。

試しに動作させてみると、こんなエラーがでたが

LoadError: cannot load such file -- rspec_junit_formatter

よく調べてみると、これは「rspec_junit_formatter」というgemを
入れてないから発生していたエラーだった。

とりあえずインストールしたら、

gem install rspec_junit_formatter

ちゃんと動作した。


[参考]
discuss.circleci.com
codenote.net

【CircleCI2.0 ✕ Rails】database.ymlはpushしたくないけど、CircleCIを使うにはpushしないといけない問題

自社の開発では、database.ymlは
.gitignoreに追加し、リポジトリにpushしない方針にしている。

そしてチームメンバーは各々のユーザ名やパスワードを
database.ymlに設定し、各環境のDBを使用する。
※チームメンバーの開発環境(VM)が全て同じものであるならば不要だと思う。

しかし、CircleCIを使用する場合、
database.ymlをpushしないとCircleCI上でDB設定ができないっぽいので
pushしないといけない。

そんなとき、便利なのが
「config」っていうgem。

設定は以下のページを参考にする。
qiita.com

settings.local.ymlにはローカル環境の設定を書いておき、
settings.ymlにはCircleCI用の設定を書いておく。

※settings.local.ymlはコマンドで自動作成されたときに
自動的に.gitignoreに設定されるので、pushしてもgitHubには転送されない。

そして以下のように設定すれば、公開したくない情報を公開せず
database.ymlをpushできる。

settings.local.yml

db:
  username: 'dev_user'
  password: 'dev_password'


settings.yml

db:
  username: 'root'
  password: ''


database.yml

default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  socket: /tmp/mysql.sock

test:
  <<: *default
  password: <%= ENV['DB_PASSWORD'] || Settings[:db][:password] %>
  host: <%= ENV['DB_HOST'] || 'localhost' %>
  database: dummy_test


config.yml

...
     docker:
        - image: circleci/ruby:2.4.1-node-browsers
          environment:
            RAILS_ENV: test
            DB_HOST: 127.0.0.1
            DB_PASSWORD: ''

        - image: circleci/mysql:5.7
        ...

かなり回りくどいが現在はこの設定で対応している。
もっと他によりやり方が、あるようだったら是非教えて頂きたい。。

【CircleCI2.0】困った!RailsとMySQLのconfig.yml設定

CircleCI2.0の公式サイトを見ると、PostgreSQLについての設定例はあるのだが
一番知りたいMySQLの設定例が無い。

circleci.com

そして、自分は今回初めてCircleCIを利用する初心者。

そして色んなサイトを参考にしようと、調べては見るものの
自分がよくわかっていないからか、設定ができるまでに
凄い時間がかかった。

最終的に設定したものがこれ。

config.yml

...
     docker:
        - image: circleci/ruby:2.4.1-node-browsers
          environment:
            RAILS_ENV: test
            DB_HOST: 127.0.0.1
            DB_USERNAME: 'root'
            DB_PASSWORD: ''

        - image: circleci/mysql:5.7
        ...


database.yml

default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  socket: /tmp/mysql.sock

test:
  <<: *default
  username: <%= ENV['DB_USERNAME'] || 'xxxxxxxxxx' %>
  password: <%= ENV['DB_PASSWORD'] || 'ppppppppp' %>
  host: <%= ENV['DB_HOST'] || 'localhost' %>
  database: dummy_test


ポイントは以下の2点

  1. rubyのimageに設定するenvironment(環境変数)は、railsのdatabase.yml内で使用できるという点
  2. database.ymlのhostには「127.0.0.1」が設定されるようにする。localhostだとエラーになる。

またdatabase.yml内の'xxxxxxxxxx'と、'ppppppppp'の箇所には、
それぞれローカル環境で使用する「ユーザ名」と「パスワード」を設定する。
そうすれば、この設定だけでローカルでもCircleCIでもテストができる。

[参考リンク]

discuss.circleci.com
discuss.circleci.com

【CircleCI2.0】config.ymlのworking_directoryの設定と、Gemのキャッシュ

working_directoryを設定することで
リポジトリをチェックアウトする場所を設定するが
何も設定しない状態だと、

デフォルトのチェックアウト場所は

「home/circleci/project」

になる。

将来的に複数のプロジェクトを利用するなどの場合を想定すると
それぞれのプロジェクト毎にworking_directoryを設定したほうが良いだろう。

その場合、以下のような設定になるかと思う。

version: 2
jobs:
   build:
     working_directory: ~/my_project
     docker:
        - image: circleci/ruby:2.4.1-node-browsers
     steps:
        - checkout

        - restore_cache:
            name: Restore bundle cache
            key: my_project-{{ checksum "Gemfile.lock" }}

        - run:
            name: Run bundle install
            command: bundle install --path vendor/bundle

        - save_cache:
            name: Store bundle cache
            key: my_project-{{ checksum "Gemfile.lock" }}
            paths:
              - vendor/bundle

        ...

上記の設定の場合だと、リポジトリがチェックアウトされる場所は
「/home/circleci/my_project」になる。

また上記のように設定することで、
gemがキャッシュされ、
CircleCIが回るたびに、「bundle install」が走らなくなる。

ただし注意してほしいのは、必ずbundle installのコマンドには
「-- path vendor/bundle」を設定することと
save_cacheのpathsにvendor/bundleを設定すること。

自分の場合、bundle installに「-- path vendor/bundle」を付けておらず
毎度bundle installが実行され、かなりの時間を無駄にした。

【CircleCI2.0】入れておきたいGem

Rubocop

書かれたRubyコードが「コーディング規約」通りに
書かれているかチェックしてくれる。

チェックさせないファイルを指定したり、
一部チェックを無効化したりすることもできる。

また既存のプロジェクトに導入した場合などで
大量に直さないといけない項目がある場合の
対応法(.rubocop_todo.ymlの仕様)もある。

[参考]
blog-ja.sideci.com

Brakemen

セキュリティチェックに使用できる。
セキュリティが怪しいコードを場所を洗い出してくれる。

[参考]
wonderwall.hatenablog.com