CircleCi上のみRspecテストが落ちる現象


概要

CircleCi初心者です。

今回はローカルではRspecのテストが正常にパスするのに、CircleCi上でのみテストに失敗してしまい解決するのにかなり時間がかかってしまいました。

こちらはとりあえずRspecを通す為だけの対応策で根本的な解決はできていません。
とりあえずCI時のRspecをパスしたい場合のみ適用してください。

また根本的な解決方法があればぜひ教えて下さい。


無事解決致しました!

環境

CircleCi 2
Rails 5.0.7
ruby 2.5.1
Mysql 5.6

コード

circleci/config.yml
version: 2 # use CircleCI 2.0
jobs: # a collection of steps
  build: # runs not using Workflows must have a `build` job as entry point
    parallelism: 3 # run three instances of this job in parallel
    docker: # run the steps with Docker
      - image: circleci/ruby:2.5.1-node-browsers # ...with this image as the primary container; this is where all `steps` will run
        environment: # environment variables for primary container
          BUNDLE_JOBS: 3
          BUNDLE_RETRY: 3
          BUNDLE_PATH: vendor/bundle
          RAILS_ENV: test
      - image: circleci/mysql:5.6
        environment:
          MYSQL_ALLOW_EMPTY_PASSWORD: true
          MYSQL_ROOT_PASSWORD: ''
          MYSQL_DATABASE: app_test
          MYSQL_HOST: 127.0.0.1
          MYSQL_ROOT_HOST: '%'
          MYSQL_USER: root
    steps: # a collection of executable commands
      - checkout # special step to check out source code to working directory

      # Which version of bundler?
      - run:
          name: Which bundler?
          command: bundle -v

      # Restore bundle cache
      # Read about caching dependencies: https://circleci.com/docs/2.0/caching/
      - restore_cache:
          keys:
            - rails-demo-bundle-v2-{{ checksum "Gemfile.lock" }}
            - rails-demo-bundle-v2-

      - run: # Install Ruby dependencies
          name: Bundle Install
          command: bundle check --path vendor/bundle || bundle install --deployment

      # Store bundle cache for Ruby dependencies
      - save_cache:
          key: rails-demo-bundle-v2-{{ checksum "Gemfile.lock" }}
          paths:
            - vendor/bundle

      - run:
          name: Yarn Install
          command: yarn install --cache-folder ~/.cache/yarn

      # Store yarn / webpacker cache
      - save_cache:
          key: rails-demo-yarn-{{ checksum "yarn.lock" }}
          paths:
            - ~/.cache/yarn

      - run:
          name: Wait for DB
          command: dockerize -wait tcp://127.0.0.1:3306 -timeout 120s

      - run: bundle exec rake db:create
      - run: bundle exec rake db:schema:load

      - run:
          name: Run rspec in parallel
          command: |
            bundle exec rspec --profile 10 \
                              --format RspecJunitFormatter \
                              --out test_results/rspec.xml \
                              --format progress \
                              $(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)

      # Save test results for timing analysis
      - store_test_results: # Upload test results for display in Test Summary: https://circleci.com/docs/2.0/collect-test-data/
          path: test_results
      # See https://circleci.com/docs/2.0/deployment-integrations/ for example deploy configs

このファイルでpushすると

エラー

ActiveRecord::StatementInvalid:
       Mysql2::Error: Incorrect string value: '\xE8\xA5\xBF\xE6\x9D\x91' for column 'username' at row 1: INSERT INTO `users` (`email`, `encrypted_password`, `created_at`, `updated_at`, `username`) VALUES ('[email protected]', '$2a$04$cFA1loXQT9LSz9Y6Jw053.hnTIvgaGChi3h86KRaP2AFLNCI15AVC', '2020-03-05 15:03:31', '2020-03-05 15:03:31', '西村')

こちらはローカルで bundle exec rspec を実行時には正常にパスするのですが、
CI時のみエラーが出てしまいます。

このMysqlエラー自体はDBの文字コードの設定によって起きるエラーで、日本語が全て読み込まれず起きているようです。

なのでRspecテストのダミーデータを作成していたFactoryBotの設定をすべて英語にするとひとまずCI上でもテストをパスすることができました。

以上、根本的には解決になっていないのですがひとまずの対応策として記しておきます。

追記

根本的な解決へと至りました。
予想通り文字コードによるエラーでした。
遭遇したエラーで検索をかけるとほとんどが、database.ymlの設定やmysqlに接続してターミナルから文字コードを変更する方法がヒットするのですが、今回の私の場合問題はschema.rbにありました。

db/schema.rb
  create_table "comment", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t|

もともとはこのようにデフォルトの文字コードはlatin1になっており、こちらはdatabase.ymlを変更しただけでは修正できません。

ではどのように変更するかというと、まずdatabase.ymlを以下のように変更します。

config/database.yml
  adapter: mysql2
  encoding: utf8
  #以下略

その後一度migrateを行います。

$ bundle exec rake db:migrate

そうするとschema.rbは

db/schema.rb
-  create_table "comments", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1" do |t|
+  create_table "comments", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|

このように文字コードを変更することができます。

はじめにrake db:createでdbを作成すると文字コードはlatin1が設定されるようです。

以上です。
たどり着くのにかなり時間がかかったので、同じエラーに遭遇した人の助けになれば幸いです。