2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Cloud FunctionsのCloudEvent関数でRSpecする

Last updated at Posted at 2022-12-12

この記事は、Ateam LifeDesign Advent Calendar 2022 カレンダー1の13日目の記事です。

CloudEvent関数でRSpecがしたかった

Cloud FunctionsのCloudEvent関数のロジックに手を加える機会があったのですが、本番へデプロイするまで動作確認をする術がありませんでした。

CloudEvent関数への改修は初めてでしたので、普段業務で使用しているRSpecでテストコードを書いて安心してリリースが行えるようDockerでのテスト環境の構築から行いました。

この記事ではCloudEvent関数でのRSpecを使ったテストコードの記述例が当時見られなかったので、備忘録を兼ねて書き残したいと思います。

CloudEvent関数のRSpecの書き方

以下のようなCloudEvent関数を例とする。
内容としてはeventデータが存在したときにFirehoseへデータレコードを配信ストリームに書き込むというもの。

require 'functions_framework'
require 'aws-sdk-firehose'

FunctionsFramework.cloud_event "function" do |event|
  any_datas = event.data['any_datas']
  firehose_client = Aws::Firehose::Client.new(
    access_key_id: 'xxxxx',
    secret_access_key: 'xxxxx',
    region: 'xxxxx'
  )

  any_datas.each do |any_data|
    next if any_data.nil?

    resp = firehose_client.put_record_batch({
      delivery_stream_name: 'xxxxx',
      records: any_data
    })
    logger.info("faild count: #{resp.failed_put_count}")
  end
end

RSpecでは以下のようにCloudEvent関数をテストすることが出来ます。

require 'rspec'
require 'functions_framework/testing'

describe 'CloudFunction' do
  include FunctionsFramework::Testing
  let(:event) { FunctionsFramework::Testing.make_cloud_event({ 'any_datas' => ['hoge'] }) }
  let(:firehose_client) { double('firehose_client double') }
  let(:file_path) { File.join __dir__, '../app.rb' }
  let(:resp) { double('resp double') }
  before do
    allow(Aws::Firehose::Client).to receive(:new).and_return(firehose_client)
    allow(firehose_client).to receive(:put_record_batch).and_return(resp)
    allow(resp).to receive(:failed_put_count).and_return(0)
  end

  context 'When data exists' do
    it 'function is called' do
      FunctionsFramework::Testing.load_temporary file_path do
        FunctionsFramework::Testing.call_event('function', event)
        expect(firehose_client).to have_received(:put_record_batch).once
      end
    end
  end
end

FunctionsFramework::Testingが提供するメソッドについて説明します。

FunctionsFramework::Testing.make_cloud_event

FunctionsFramework::Testing.make_cloud_eventでCloudEvent関数に渡すためのcloud eventを作成できます。

FunctionsFramework::Testing.load_temporary

FunctionsFramework::Testing.load_temporaryでテストするCloudEvent関数のパスとブロックを渡します。

FunctionsFramework::Testing.call_event

FunctionsFramework::Testing.call_eventでテストするCloudEvent関数の名前とcloud eventを渡してCloudEvent関数のテストが出来ます。

躓いたところ

最初、FunctionsFramework::Testing.call_eventをsubjectしてCloudEvent関数の結果をテスト出来るだろうと思っていました。

# CloudEvent関数は成功か失敗かが分かるよう実行結果を返すよう修正したうえで
subject { FunctionsFramework::Testing.call_event('function', event) }
it { is_expected.to eq('xxxxxx') }

しかし、FunctionsFramework::Testing.call_eventはCloudEvent関数を呼ぶだけで実行結果を返してくれるものではありませんでした。

これに対してhave_receivedマッチャを使用してメソッドが呼ばれることを検証することでCloudEvent関数が期待通りの動作することを確認できるテストコードを書くことが出来ました。

have_receivedマッチャは使用したことがなく存在も知らなかったので以下記事を参考にさせていただきました。:pray:

まとめ

テストコードがあると不具合を未然に防ぐことが出来るだけでなく、安心して今動いている既存機能に手を加えたり、新たな機能を追加することが出来ます。それでけではなく、リファクタリングを促進できたり、メソッドの結合度を下げたテストコードの書きやすいコードを書きやすくなるなどと多くのメリットがあります。

この記事がCloudEvent関数へのテストの導入に少しでもご参考になれば幸いです。:pray:

今回記事を書くにあたって用意したサンプルコードは以下となります。

参考文献

2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?