Beeeat’s log

Beeeat’s log

プログラミングで出くわした知識やツール、日常生活、働き方その他色々なことをメモしていくブログ

Ruby のコードで見かける「&.」は safe navigation operator (ぼっち演算子)と呼ばれる演算子だった

 普段の業務で Ruby のコードを読んでいると,何箇所かobject&.fooという書き方を見かけました.

初めて見た時は「まぁこういう書き方もあるんだなぁ」とさらっと読んでいましたが,後々,「あれ?結局これどういう意味なんだろ?」と混乱したため今回はこの「&.」とは何かについてまとめていきます.

「safe navigation operator (ぼっち演算子)」

調べてみた結果,「&.」は「safe navigation operator 」と呼ばれる演算子でした. Ruby 2.3.0 がリリースされた時に導入されたメソッドのようです.

www.ruby-lang.org

Ruby の公式ドキュメントを読むと,「ぼっち演算子」とも呼ぶようです...(公式のリファレンスでの名称なんですね...)

docs.ruby-lang.org

「&.」の機能は公式リファレンスを見てみると...

object&.foo という形式のメソッド呼び出し形式が追加されました。
これは object が nil でないときにメソッド foo を呼び出します。

とのことでした.つまりどういうことでしょう?

実際に書いて試してみる

ということで,試しにコードを書いてみました.以下は,Human オブジェクトでgreetingメソッドを実行し,コンソール上に文字列を表示するコードです.まずは「&.」を使わずに実行してみます.

class Human
  def greeting(name)
    puts "こんにちは#{name}さん"
  end
end

obj = Human.new
name = "okabeeeat"
puts obj.greeting(name)

なんてことなく文字列が表示されました.

~ » ruby sample.rb
こんにちはokabeeeatさん

次は,objの値をnilにしてみましょう.

class Human
  def greeting(name)
    puts "こんにちは#{name}さん"
  end
end

-- obj = Human.new
++ obj = nil 
name = "okabeeeat"
puts obj.greeting(name)

予想通り,NoMethodErrorとなります.

~ » ruby sample.rb
Traceback (most recent call last):
sample.rb:9:in `<main>': undefined method `greeting' for nil:NilClass (NoMethodError)

それでは,objnilの状態で「&.」を使ってgreetingメソッドを実行してみましょう.

class Human
  def greeting(name)
    puts "こんにちは#{name}さん"
  end
end

obj = nil
name = "okabeeeat"
-- puts obj.greeting(name)
++ puts obj&.greeting(name)

なんとNoMethodErrorが発生せずに終了しました.公式リファレンスの内容を引用すると,objnilの場合はgreetingメソッドを実行せずに処理が終了したことになります.

~ » ruby sample.rb

どんな場面で使えるのか?

動きはこれでわかりましたが,はたしてどんな時に役に立つのかを考えてみました.

一言で言うとnilをチェックする処理を実装する書く手間が省けることが挙げられます.開発するプロダクトによっては,特定の条件で object がnilになることを考慮して,object の値がnilかどうかをチェックする処理を書く場合があります.

そこで,今回調べた「&.」を利用すると object がnilの場合ならメソッドを実行しないで済むため,object がnilになることでの Error が発生せずに済みます.

まとめと所感

今回は「&.」,「safe navigation operator (ぼっち演算子)」について調べてみました.調べる前は「&.」がなんて呼ばれるものなのかわからず調べるのに少し苦労しましたが,何とか調べることができて良かったです.

「&.」はもっと使い所がある演算子だと思うので,どんな時に役立つかをもう少し意識して,コードを書いてみようと思います.

他にも Ruby を書いてて気になる文法があるので,今回の記事のように気になったら随時まとめていこうと思います.

Puppeteer で Basic 認証が掛かったページにアクセスする方法をまとめてみた

先日 Jest + Puppeteer の導入が完了した.その過程で Basic 認証が掛かったページに対して E2E テストを実行する必要があった.そのため,Basic 認証が掛かったページにアクセスする方法を調べ,対応したのだが,想定よりも時間が掛かったためまとめておく.

設定方法

調べた所,2つの方法を見つけた.

page.authenticate を利用する方法

公式ドキュメントにある page.authenticate を使って Basic 認証のユーザとパスワードをセットし, page.goto でページにアクセスする.

await page.authenticate({username: 'Basic 認証のユーザ名', password: 'Basic 認証のパスワード'});
await page.goto('Basic 認証が掛かったページのURL', {waitUntil: "domcontentloaded"});

実際は,Basic 認証のユーザとパスワードをハードコーディングするのではなく,以下のように定数を利用した.定数は dotenv をインストールし,.env ファイルで値を設定した.

require('dotenv').config();

await page.authenticate({username: process.env.USER, password: process.env.PASS});
await page.goto('Basic 認証が掛かったページのURL', {waitUntil: "domcontentloaded"});

page.setExtraHTTPHeaders を利用する方法

page.setExtraHTTPHeaders を利用する方法も見つけたため,試してみた.この方法でもページにアクセスすることが確認できた.

await page.setExtraHTTPHeaders({ Authorization: `Basic ${new Buffer.from(`${'Basic 認証のユーザ名'}:${'Basic 認証のパスワード'}`).toString('base64')}`});
await page.goto('ベーシック認証が掛かったページのURL', {waitUntil: "domcontentloaded"});

最初は Buffer() を使って Basic 認証の設定をしていたが,実行すると以下のように Buffer() は非推奨である旨がコンソールに表示されたため,代わりに Buffer.from() を使っている.

DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe()
, or Buffer.from() methods instead.

どちらのメソッドを利用すれば良いの?

どちらのメソッドを利用しても Basic 認証が掛かったページにアクセスすることがわかった.そのため,どちらを使うかは実装者の判断で決めれば良いと思う.

私の場合はpage.authenticateを利用する方法を採用した.理由としては,公式ドキュメントの説明文を見たところ page.authenticate はHTTP認証の情報を提供するために用意されたメソッドである旨が書いており,こちらを利用した方が目的と合致していると思ったからだ.

まとめと所感

今回は,Puppeteer で Basic 認証が掛かったページにアクセスする方法についてまとめてみた.知ってしまえば何てことない内容だが,それ故に想定より時間が掛かったため色々悔しかった(まぁ,他に Typo とか色んな理由もあったけど).

Jest + Puppeteer の導入は完了したが,テストケースはまだまだ足りないため,これから他のタスクと併行して増やしていく.

Advent Calendar を作ってから埋まるまでに学んだことについて LT しました

この記事は マイナビ Advent Calendar 2019 25日目の記事となります.

23日に開催された「エンジニアの成長を応援する忘年LT大会2019」で LT 登壇しました.イベントでは参加者の皆さんと一緒に今年を振り返ることができ,充実した時間を過ごすことができました.

LT では私が所属企業の Advent Calendar を作成し,枠が埋まるまでに学んだことについてお話しました.

今回は,登壇した資料についての補足や登壇してみての所感などについてまとめていきます.

「Advent Calendar を作ってみたけど中々埋まらなかった」,「来年は所属企業の Advent Calendar を作ってみたい」という方に少しでも参考になれば嬉しいです.

engineers.connpass.com

登壇資料

Advent Calendar はすぐに埋まるとは限らない

f:id:bake0937:20191225203003p:plain

Advent Calendar の文化が醸成されている企業はカレンダーが作られたら,早い者勝ちで枠が埋まるかと思います.

しかし,現在私が所属しているマイナビは,今年からエンジニアブログやテックイベントなど社外へ技術発信する手段を増やしてきた状態.つまりアウトプットの文化は醸成している最中です.

そのため,沢山のメンバーが参加し,様々な内容の情報発信をするには,参加してもらうまでの過程で少し工夫を加える必要があると考えました.

全然埋まってねぇ!!

f:id:bake0937:20191225203029p:plain

社内の知り合いや書いてくれそうな人から個別に声を掛けてみましたが,11月の下旬でまだこのレベルの埋まり具合...流石にヤバいと感じました(枠を必ず全部埋めることが正解ではないかもしれませんが...).

Advent Calendar を作ったのは私のため,残りの空いた枠は私が全部埋めることも考えましたが,これだとカレンダーの枠が半分以上が私になり,それはそれでどうなんだろう...と悩んでいました.

「なぜ埋まらないのか?」を考える

f:id:bake0937:20191225203120p:plain

「うわぁぁ参加者少ない...もうウチはダメなんだぁ〜」と考えるのはまだ早いと判断し,一旦自分が取り組んだことを振り返り,原因が何かを考えてみました.

個別に声を掛けるのと併行して,もっと早く全体に告知すれば良かったというのが大半の理由だと思いましたが,個別に声を掛けた時に Qiita の Organization の参加方法や Advent Calendar の参加方法について何個か質問されたのを思い出しました.

そのため,これから告知をする時は単に「Advent Calendar 作りました〜 登録お願いします〜」という簡素な内容ではなく,「Advent Calendar とは何か?」についての説明や魅力,参加するまでに必要な手順含めて告知し,Advent Calendar を初めて知った人が参加できるように工夫しました.

そして,声を掛けた時に一番受けた「ネタに困っている」という相談.ここに関しては,社内で各々が今までに投稿した社内ブログや Wiki の記事を今回用に少し書き換えて投稿する提案をしました.

これは Advent Calendar に限らず,個人のブログやエンジニアブログのネタ切れ問題を解決する方法の一つにもなります.

この時に社内で利用している DocBase の記事数を確認したのですが,記事数が 3000 を越えているのにはかなり驚きました(社内用の記事も含めてにはなりますが...).これから投稿する記事のネタには困らない...はず!.

ついに枠が埋まった!!

f:id:bake0937:20191225210030p:plain

Slack で告知後は参加者の何人かに告知文のリマインドをお願いしたり,引き続き知り合いが通り掛かったら声を掛けてみるようにしました.

役職・職種関係なく声を掛けていたので事業部長にも声を掛けていました笑.そうすると次第に参加者が増えていき,12月の第一週の後半ぐらいには全部の枠が埋まりました!

Advent Calendar から学んだこと

f:id:bake0937:20191225212456p:plain

作った直後は「え?適当に告知したらすぐ埋まるでしょww」というような気持ちでいましたが,Advent Calendar を作ってから埋まるまでの過程を通して,参加者をどのように集めるかや協力の仰ぎ方,巻き込み方などを身を持って経験することができました

今回経験したことは,これから新しい技術や制度・文化を組織やチームに導入する時にも活きていくと感じました.

発表中

会場は合同会社 DMM.com さんのイベントスペースでした!めちゃくちゃオシャレで東京タワーも一望できて最高でした.

LT 登壇中は参加者の皆さんから良い感じにリアクションを頂き,話しやすくて助かりました.また実況ツイートも頂き,登壇後のフィードバックにもなったためとても嬉しかったです.

まとめと所感

「エンジニアの成長を応援する忘年LT大会2019」で LT 登壇しました.一時はどうなるかと思いましたが,「Advent Calendar へ参加する文化を醸成した企業でも,最初に誰かが導入したという段階が必ずある」と考えると,その「導入の段階」を経験できたのは貴重だと感じました.

Advent Calendar の枠が無事全部埋まったといっても今回は私が 4 枠入れていたりもするので,次回は参加者(ユニーク)25人による様々な技術や知見を発信する Advent Calendar になることを目指します💪

懇親会では,参加者の皆さんの今年の振り返りを共有することができ,来年の目標の決めるためのヒントを沢山見つかりました.参加者・スタッフの皆さん,ありがとうございました!

最後になりますが,マイナビアドベントカレンダーはこちらです.

qiita.com

Slack通知 と GitHub の Releases・Tags を自動生成するツールを作っています

この記事は,Slack Advent Calendar 2019 18日目の記事です.

現在,slack-ruby-client と octokit.rb を使って,Slack通知 と GitHub の Releases・Tags の自動生成を一気に実行するツールを作っています.今回はそのツールについて紹介します.

github-slack-release-notification

github.com

slack-ruby-client と octokit.rb を利用して,Slack APIGitHub API を実行し,Slack通知や GitHub の Releases と Tags が自動生成するようにしました.

Slack通知では Block Kit を使って最新のプルリクエストの情報を表示するようにしています.今の所,名前がそのまんまのため,どこかのタイミングで名前を再検討するかもしれないです.

使い方

git cloneをしてからプロジェクト直下に.envを作成し,以下の定数を設定していきます.

GITHUB_PERSONAL_ACCESS_TOKEN=GitHub の個人アクセストークン(repo)
GITHUB_REPOSITORY=Githubのユーザ名/リポジトリ名
SLACK_API_TOKEN=Bots の Slack API トークン
PRODUCT_PAGE=プロダクトのWebページのURL
RELEASE_POST_CHANNELS="random,general"
ERROR_POST_CHANNELS="random,general"
SUCCESS_EMOJI=":kirakira:"
FAIL_EMOJI=":guttari:"

○○_EMOJIには,Slack の好きな絵文字を設定できます.Slack のチャンネルは複数選択が可能です. SLACK_API_TOKENは Bots の API トークンを利用しました. f:id:bake0937:20191218224040p:plain

プロジェクト直下でapp.rbを実行します

github-slack-release-notification - [master] » ruby app.rb

Slack を見ると通知が来ています.(検証用のスクショとは言え,このPR内容はちょっと恥ずかしい...)

f:id:bake0937:20191218221715p:plain

設定した GItHub リポジトリを見てみると,Releases・Tags も作られています. f:id:bake0937:20191218222006p:plain

作ろうと思ったきっかけ

普段は Ruby on Rails (以下,Rails)でのWebサービス開発を通して Ruby を書いているのですが,もっと Ruby 力を高めたいと思っていました.すると,Rails というフレームワークから離れた Ruby のコードを最近はあまり書いていないことにふと気がつきました.

そこで,今年の7月に ootemachi.rb で Rubotyを触ってみたという内容でLTをしてみたのですが,LT が終わって数分後に「ん?今度は Ruboty という Botフレームワークに乗っているのでは?」と気づいてしまいました.

enechange-meetup.connpass.com

そんな中,この勉強会の会場が Slack Japan のオフィスで,私のLTの前に@seratchさんの「Ruby で始める Slack App 開発」というセッションの内容を思い出していると「slack-ruby-client と Ruby で何か作れば,フレームワークに縛られずに何か役立つ楽しいツールが作れるかもしれない」と思いつきました.

そして,その頃は業務でデプロイ時に Slack通知 をする Capistarano のプラグインReleases・Tags を自動生成する Capistarano のプラグインの導入を終えていたタイミングで「この2つの機能を Slack と GitHubAPI を組み合わせて表現したら面白くなりそう」と思って作ってみた感じです.

ここまで作ってみての感想

一言で言うと「オブジェクト指向を自分で納得しながら Ruby を書くことができた」です.Ruby を始めたての頃,入門書でクラスについての章で車クラスや車輪クラスを作ってオブジェクト指向を学んだ記憶があったのですが,「これが開発業務にどのように結びつくのか?」ともやもやしていました(正直これは大学時代に Java を勉強していた頃から感じていた...).

勿論,普段の開発でもオブジェクト指向は活用していますが,あくまで「フレームワークのルールに沿ったオブジェクト指向」なので「オブジェクト指向をやっている感」をあまり強く感じていませんでした.あまり上手く説明できていませんが,他に「Active Record にだいぶ助けられているのでは?」と思っているのも関係あるかもしれないです.

しかし,今回のツール作成を通して,「1つのファイルに処理をひたすら書く」→「冗長になってきたのでメソッド化」→「それでも長くなってきたので,メインの処理やAPIを操作する役割毎にクラスを作る」というオブジェクト指向の流れを自分で納得しながら自然に進めることができました.

また,Rails のようなディレクトリ構成も決まっていないため,どのような構成にするかも自分で決められるため.設計の本を読みながら色々試行錯誤ができます.また, 現在のコードが再設計やリファクタリングしがいがある状態なので Ruby の勉強するモチベーションがだいぶ上がりました.

今後

再設計(.envで設定する値も多いし...)やテストコードの導入など,やること沢山ありそうです.最終的には CI での自動デプロイ後に AWS Lambda で実行できるようにしたいと考えています.

まとめと所感

Slack通知 と GitHub の Releases・Tags を自動生成するツールを作っています.今までオリジナルの Webサービス を好んで作っていて,Ruby でツールを作成するのが久しかったですが,Slack や GitHub の Web API を組み合わせると,とても面白くなることを実感しました.業務でのちょっとした不便を解消するアイデアが出てきているので,ドンドン作っていこうと思います.

また,Ruby に限らず JavaScriptgolang など他の言語でのツール開発にもチャレンジしていこうと思います.

「GoRails」は Ruby on Rails と英語を勉強するのにピッタリなサービスだった

この記事は,Ruby on Rails Advent Calendar 2019 17日目の記事です.

普段から Ruby on Rails(以下,Rails)で開発をしているのですが,キャッチアップする方法が書籍がメインでした.

そんな中,「GoRails」という動画で Rails を学べるサービスを見つけました.今回はその「GoRails」について自分なりにまとめていこうと思います.

f:id:bake0937:20191217060150p:plain

GoRails とは

Chris Oliver さんが運営している Rails に特化したチュートリアルサイトです.現在では2万人以上の開発者が利用しているそうです.

twitter.com

少し前までは,Railsチュートリアルではお馴染みの「RailsCasts」というサービスがありましたが,現在は更新が止まってしまいました.

そこで「GoRails」の登場したことにより「新たな RailsCasts だ!」とブログや Twitter で一部のエンジニアから評されているようです.

railscasts.com

blog.mah-lab.com

入門してみた理由

他にも「Udemy」や「Pluralsight」という動画で Rails を学ぶサービスを見つけました.

どれにしようか考えた時に,「GoRails」の方がカリキュラムの数と定期的に更新されていることやメドピアさんが「テックサポート制度」というエンジニア向けの社内制度に「GoRails」を導入している事例を知り,入門することにしました.また,英語に触れる機会をもう少し増やしたい気持ちもありました.

tech.medpeer.co.jp

ただ,「Pluralsight」は JavaScriptPython など Rails 以外のコンテンツが充実しており,Udemy は Rails の英語でのコンテンツで面白いものを何個か見つけたので,どちらも今後の動向はチェックしていこうと思います.

内容

※以下は会員登録しなくても見ることができます.

Rails そのものを学べるだけではなく, Rails を基点に Vue.js や Twilio など Rails でのWebサービス開発で利用される技術についても学ぶことができます・

f:id:bake0937:20191217064001p:plain

Rails & Vue.js Trello Clone」という Rails と Vue.js を使った Trello のクローンを作る動画で勉強してみました.動画のプラットフォームは YouTube のため,困ったら自動翻訳が使えます.

進捗としてはまだ序盤の段階のため完成までもう少し掛かりそうです.

f:id:bake0937:20191217081953p:plain

gorails.com

まとめと所感

「GoRails」で Rails の勉強をしてみました.説明が英語のため最初は慣れが必要そうですが,自動翻訳の力と実装したソースコードを自分なりに解釈していけば進めていけそうでした.

何点か質問事項も生まれ,質問するには英語でコメントする必要があります.そのため,英語力を勉強するきっかけやモチベーションの一つになりそうです.

現状,有料プランは 月額 19$ とちょっと手を伸ばせば払えそうな金額のため検討してみても良いなと思いました.

「もう少し検討してみたい!」という人は Free のコンテンツがあるのでこちらを見てみるのも良さそうです.

gorails.com

シス担ミートアップ#3 で AWS CodeBuild を CI 環境として使ってみた話をしました

9月頃になりますが「シス担ミートアップ」という社内イベントに登壇しました.イベント自体は3回目で,グループイン企業や投資先企業のエンジニアも参加し,様々な知見の共有や交流し,充実したイベントとなりました.

このイベントで私は, AWS CodeBuild(以下,CodeBuild) を CI として使ってみた話をしました.今回は登壇した資料についての補足や発表時にあまり話せていなかった内容を書いていこうと思います.

登壇資料

CircleCI のテスト実行待ち問題

f:id:bake0937:20191215170316p:plain

当時のマイナビニュースでは CircleCI の「コンテナ課金プラン」を利用していました.CircleCI は GitHub.com の Organization 単位で利用することができます.Organization には他チームのリポジトリもあるため,CircleCI のコンテナを他チームと共同で利用することになります.

これにより,マイナビニュースで CircleCI を利用している時に他チームのテストの実行待ちが頻繁に発生し,開発の進捗が遅れるという問題が発生しました.

マイナビニュースが他の CI サービスに移行

f:id:bake0937:20191215171914p:plain CircleCI の契約コンテナ数を増やす案や DroneCI などの CI 環境を構築する案など,調査・検討をしましたが,その中で CodeBuild を CI として利用する事例があることを知りました.

他の企業での事例は少なかったですが,従量課金制で並列実行できる点やマイナビニュースでは既に AWS をインフラとして利用していたため導入が早いと判断し,CodeBuild を CI として利用することにしました.

CodeBuild では CircleCI のような複数のコンテナ指定ができない...

f:id:bake0937:20191215173050p:plain 設定用の yml ファイル(buildspec.yml)の書き方が少し異なることや CI のログは CloudWatch Logs が必要になるなどの変更点はありましたが,ここまでで CircleCI との大きな違いはありませんでした,

しかし.一番の大きな違いは CodeBuild で設定する yml ファイルや CodeBuild のコンソール画面で複数のコンテナを指定することができないという点でした.CircleCI を利用していた時は Web や DB など複数のコンテナがある構成であったため,CodeBuild ではどのように表現すれば良いのか?というところでとても悩みました.

Docker in Docker で 複数のコンテナを利用することを表現する

f:id:bake0937:20191215173857p:plain 複数コンテナを指定する方法についてさらに調べたところ,コンテナの中にさらに複数のコンテナを指定する Docker in Docker (以下,dind) を使った方法を知りました.

Docker 社が Docker Hub で配布している dind 用のコンテナイメージ CodeBuild のコンソールで指定し, 設定用の yml ファイルにdocker pullコマンド記載し,テストの実行に必要なコンテナイメージを pull する方法です.

hub.docker.com

他の企業での事例が少ないこともあり,挑戦するのがとても不安でしたが,何とか上記の構成で CI 環境を構築することができました.CodeBuild のコンソールでのコンテナの指定方法や設定用の yml ファイルの書き方については,スライドを見てみてください.

こうして現在では,CI 環境としてマイナビニュースは CodeBuild,他チームは CircleCI を利用しています.

CI の速度改善を試みる

f:id:bake0937:20191215175658p:plain 「CodeBuild で CI 環境を構築できた!!めでたしめでたし...」という訳にもいかず,今度は CI の実行時間が遅いという課題が発生しました.

速度改善には色々な方法があるのですが,一番効果が高かったのは,CodeBuild のローカルキャッシュ機能の一つである「DockerLayerCacheをオン」する方法でした.この機能をオンにすることで,ビルドで利用した Dockerfile レイヤーを再利用することでき,結果として約9分短縮されました.

他のローカルキャッシュ機能やコンピューティングタイプを上げ,最終的には約25分→約13分代まで CI の実行時間を短縮することに成功しました.

この速度改善から数ヶ月後にソリューションアーキテクトの方とお話をする機会がありました.その時に今回やったことについて話した所,ローカルキャッシュ機能はあくまでベストエフォートな機能で,ビルドの間隔が空いた場合やビルドの並列度が高い(同じ時間に複数のビルドが実行される)場合はキャッシュが効かない時があるという話を聞きました.

これは実際に利用している私自身も「あれ?今回のビルドはキャッシュが効いてないな」と思う場面が何度かあり,納得しました.

その他運用していて遭遇したこと

他に遭遇したこととして,Codebuild 側で Linux コマンドなどのバージョンが上がった時に設定用の yml ファイルにあるコマンドのオプションの指定方法が変わったことで,CI が落ちることが何度かありました.その一例として過去に記事を書いております.

bake0937.hatenablog.com

CodeBuild を利用するようになって,開発メンバーが約4人で月額の平均が約2000円とだいぶコストカットすることに成功しました.

しかし,上記のような管理コストも考えると,新たなプロダクトがリポジトリに追加され,そのプロダクトでも CI が必要になった時は,CircleCI や TravisCI などの CI サービスを利用することや DroneCI や Jenkins など違う種類の CI 環境の構築することなどを再検討してみても良いと考えました.

最近,CircleCI に 「Performanceプラン」という新しいプラン*1が登場したため気になっています.

まぁ CodeBuild の方が金銭コストが低く CI 環境を構築できることがわかってしまったので,開発効率を優先するのか,それとも金銭コストを優先するのかなどを開発チームや事業部全体で議論する必要があるかと思います.

circleci.com

まとめと所感

シス担ミートアップ#3 に登壇しました.当時の私の AWS の利用経験は Amazon S3 を少し使ったことあるくらい(前職では OpenStack によるプライベートクラウドをメインで利用していました)で,「そもそも AWS について色々調べないと!」みたいな状態でした.そのため,今回経験したことを通して AWS についてもよく知ることができたため,とても良い経験になりました.

また, CI 環境...というより,技術選定はパフォーマンスや開発効率を優先するだけではなく,選定したサービスやツールの金銭コストや運用コストについても考慮する必要があることを思い知らされました.

その点では技術選定の経験もできたため,これからも「発生している問題や課題に対して,解決をする方法」についての考え方やセンスを磨いていこうと思います.

*1:当時(CodeBuild への移行作業をしている時)は「Performanceプラン」が出るらしいというのを噂で聞いた状態でした.

環境変数によって実行するE2Eテストを変えられるようにする

引き続き Jest × Puppeteer でのE2Eテストのキャッチアップをしている.進めていくうちに,本番環境の他にステージング環境や検証環境に対してもE2Eテストを実行できるようにしたくなってきた.

そのため,今回は環境変数によって実行するE2Eテストが変えられるようにする方法を調べたのでまとめておく.

ソースコードはこちら github.com

やり方

環境変数を使いたい時はよく「dotenv」というnpmライブラリが登場するが,今回はE2Eテストを実行時に環境変数を指定し,特定のE2Eテストを実行できるようにした. www.npmjs.com

今回の記事用に本番環境やステージング環境が用意できなかったため,あくまでENVIRONMENTという環境変数の内容によって実行するE2Eテストが変わるように書いてみた.process.envを使って環境変数の内容を確認し,if文で実行するE2Eテスト変えるようにしている.

e2e-env.spec.js

describe('環境変数別にページが遷移するか', () => {
  if (process.env.ENVIRONMENT == 'GOOGLE') {
    beforeAll(async () => {
      await page.goto('https://www.google.co.jp/');
    });
    it('should be titled "Google"', async () => {
      await expect(page.title()).resolves.toMatch('Google');
    });
  } else if (process.env.ENVIRONMENT == 'YAHOO') {
    beforeAll(async () => {
      await page.goto('https://www.yahoo.co.jp/');
    });
    it('should be titled "Yahoo! Japan"', async () => {
      await expect(page.title()).resolves.toMatch('Yahoo! JAPAN');
    });
  } else {
    beforeAll(async () => {
      await page.goto('https://www.bing.com/');
    });
    it('should be titled "Bing"', async () => {
      await expect(page.title()).resolves.toMatch('Bing');
    });
  }
});

実行してみる

実行する時は以下のように環境変数を指定して実行する.ENVIRONMENTGOOGLEを指定したため,Google のトップページに遷移するE2Eテストを実行してみた.

$ ENVIRONMENT=GOOGLE npx jest ./e2e-env.spec.js
 PASS  ./e2e-env.spec.js
  環境変数別にページが遷移するか
    ✓ should be titled "Google" (8ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.476s, estimated 3s
Ran all test suites matching /.\/e2e-env.spec.js/i.

もし,本当にアクセスされているのかを見たい場合はjest-puppeteer.config.jsheadless:falseにした状態でE2Eテストを実行するとブラウザが自動で立ち上がり,目で見て確認することができる.

jest-puppeteer.config.js

module.exports = {
  launch: {
--    headless: false,
++    headless: true,
  },
};

まとめと所感

環境変数によって実行するE2Eテストが変えられるようにしてみた.過去に RSpec × Capybara で似たようなことをやったので Jest × Puppeteer でも実現できて良かった.検証時は意味もなく「dotenv」をインストールしたり,.envを作成してしまっていたが,結果的に新たなライブラリをインストールせずに実現できた.

今後はif文の部分を Rails の部分テンプレートのように共通化し,これから書くE2Eテストで呼び出すような使い方をしていこうと考えている.