ジョギング
- 香椎浜 x 2 周
- ほぼほぼ 30min を切るくらい
- 足の痛みは少し落ち着いた感
日課
- (腕立て x 50 + 腹筋 x 50) x 3
ダイレックス
朝からダイレックスに買い物, お昼も夕飯の買い出しでダイレックス.
俺クラスだとダイレックスまでチャリで 3min
— Yohei Kawahara(かっぱ) (@inokara) 2018年4月2日
今日二回目のダイレックス。
— Yohei Kawahara(かっぱ) (@inokara) 2018年4月2日
一日に二回も行くと顔も覚えられているんだろうなあ.
今日のるびぃ ~ 最近, awspec に送ったプルリクエスト ~
awspec に送ったプルリクエストの振り返りと, そこで得た知見をメモる.
fix have_lifecycle_rule #360
s3_bucket リソースの have_lifecycle_rule のテストを走らせると, fail しないという issue の対応.
主に, 以下のような対応を行った.
ライフサイクルルールの取得は, lifecycle_configuration_rules というプライベートメソッドで行われていて, 以下のような情報を has_lifecycle_rule? で処理することになる. 以下, ドキュメントより抜粋.
resp.rules #=> Array resp.rules[0].expiration.date #=> Time resp.rules[0].expiration.days #=> Integer resp.rules[0].expiration.expired_object_delete_marker #=> Boolean resp.rules[0].id #=> String resp.rules[0].prefix #=> String resp.rules[0].status #=> String, one of "Enabled", "Disabled" resp.rules[0].transition.date #=> Time resp.rules[0].transition.days #=> Integer resp.rules[0].transition.storage_class #=> String, one of "GLACIER", "STANDARD_IA" resp.rules[0].noncurrent_version_transition.noncurrent_days #=> Integer resp.rules[0].noncurrent_version_transition.storage_class #=> String, one of "GLACIER", "STANDARD_IA" resp.rules[0].noncurrent_version_expiration.noncurrent_days #=> Integer resp.rules[0].abort_incomplete_multipart_upload.days_after_initiation #=> Integer
この処理を実装する際に, 配列に入っている Types::NoncurrentVersionTransition のような構造体を丸っと Enumerable#map と &:to_h
を併用して hash 化してから hash 同士を比較するという小技を覚えた.
if value.is_a?(Array) return false if r[key].map(&:to_h) != value end
当初は, r[key]
を each で回してとそれぞれの要素を比較するようなコードを書いていたけど, 汚いよなーと 2 時間くらい悩んでいたら何かが降りてきた感じで &:to_h
でシンプルに書き直すことが出来た.
あと, 手元でテストを回した時には, PASS するものの, Travis でテストを回すとドキュメントのテストで必ずコケるという現象に遭遇してしまったので, 改めて Fork し直してからプルリクエストした.
extend matcher for have_db_parameter_group and have_option_group #361
RDS の DB パラメータグループとオプショングループのステータス (in-sync
or pending-reboot
) をテストしたい, リクエストが社内から上がっていたので, 既存の have_db_parameter_group と have_option_group マッチャを拡張した.
- lib/awspec/matcher/have_db_parameter_group.rb
- lib/awspec/matcher/have_option_group.rb
- lib/awspec/type/rds.rb
Rspec のマッチャは RSpec::Matchers.define を利用して, 以下のように,独自のマッチャを定義出来るが, 今のところ, この書き方についてちゃんと理解出来ていない... すんません.
require 'rspec/expectations' RSpec::Matchers.define :have_string do |expected| match do |actual| actual.include?(expected) if @num.nil? actual.include?(expected) else actual.split('-').count(expected) == @num end end chain :count do |num| @num = num end end RSpec.describe 'foo-bar-bar' do it { is_expected.to have_string('foo') } end RSpec.describe 'foo-bar-bar' do it { is_expected.to have_string('foo').count(1) } end RSpec.describe 'foo-bar-bar' do it { is_expected.to have_string('bar') } end RSpec.describe 'foo-bar-bar' do it { is_expected.to have_string('bar').count(2) } end
ざっくりと解説すると...
- RSpec::Matchers.define でカスタムマッチャを定義することが出来る
- RSpec::Matchers.define に続く, シンボルで書かれている
:have_string
がマッチャの名前となる - match ブロック内で実際の値 (actual) とあるべき値 (expected) を比較する処理を書く
- chain ブロックを利用することで, チェーンするメソッドを定義することが出来て,
have_string('foo').count(1)
みたいな書き方をすることが出来る
フムフム