📖

Ruby on Lambdaをローカル環境でRSpecテストする方法

2022/03/13に公開

概要

業務でLambdaをRubyで実装したのですが、テストをどう実装すればいいのかわかりませんでした。

Dockerを使ってLambdaにイベントを流す方法もあるようですが、内部ロジックを簡単にテストしたい場合ちょっと大変だなという印象を持ちました。

そこでRubyだけを用いてテストを実行する方法を調べたので方法をまとめたいと思います。

https://therubyist.org/2021/01/19/rspec-testing-with-ruby-aws-lambda-functions/

主にこの記事に書かれていることを参考に書いていきます。

AWS LambdaのRubyをテストする方法

ディレクトリ構成

.
├── .rspec
├── .ruby-version
├── Gemfile # Lambda + テスト用のGemを記載
├── Gemfile.lock
├── README.md
├── Rakefile
├── spec
│   ├── hoge_service_spec.rb
│   └── spec_helper.rb
└── src
    ├── function
    │   └── .ruby-version
    │   ├── Gemfile # Lambdaに必要なGemのみを記載
    |   ├── Gemfile.lock
    │   └── lambda_function.rb
    │   └── hoge_service.rb # テストしたいロジックをクラスに分離

Gemfile

Lambda上でGemを使う場合、Gemも含めてソースコードとしてZIPファイル化してアップロードする必要があります。
しかしテスト用のGemをLambda実行環境では不要なため、

  • Lambdaが本当に必要なGemfile
  • 上記 + テスト/開発中に必要なGemfile

を分けて管理する必要があります。

src/function/Gemfile
source 'https://rubygems.org'

# gems needed in lambda runtime
gem 'hoge'
gem 'fuga'
Gemfile
# src/function/Gemfileを読み込む
eval_gemfile('./src/function/Gemfile')

gem "rake"
gem "rspec"
gem "rubocop"

参考: https://qiita.com/yohm/items/d32f01ac5a8e1d612d92#方法

こうすることでLambdaの実行環境には必要なgemのみをアップロードしつつ、開発/テスト時には必要なGemを使うことができるようになります

RSpec(minitest)の実行

Rakefile
# frozen_string_literal: true

require 'rspec/core/rake_task'

RSpec::Core::RakeTask.new(:spec)
task default: %i[spec]
src/lambda_function.rb
def lambda_handler(event:, context:)
  # ...
  HogeService.do_something # テストしたいロジックは適当なクラスに分離する
  # ...
end

この状態で HogeService に対するSpecを書くことでテストを実行することが可能になります

ソースコードのZIP化

$ pwd
src
$ rm -rf ./vendor
$ docker pull lambci/lambda:build-ruby2.7
$ docker run -it --rm -v "$PWD":/var/task -v ~/.ssh:/root/.ssh lambci/lambda:build-ruby2.7 bundle install --path=vendor/bundle
$ zip -r9 ../hoge.zip . -x \*/.git/\*

Lambdaの実行環境でビルドする必要があるため公式のDockerイメージを使ってビルドしています。

また.gitは不要なのでZipからは取り除いています。

Discussion