BASE開発チームブログ

Eコマースプラットフォーム「BASE」( https://thebase.in )の開発チームによるブログです。開発メンバー積極募集中! https://www.wantedly.com/companies/base/projects

EarlGreyを使ってiOSのUIテストを自動で行う

f:id:tomo358:20180417191124j:plain:w600

こんにちは。ショッピングアプリ「BASE」のiOSアプリを担当している竜口です。

背景:あの改修の効果測定用のログ、送られてる?

ショッピングアプリ「BASE」内で、施策の効果測定やKPIの経過観察で様々なログを使用しているのですが、細かい改修などで特定のログが送られない事象があり、効果測定が出来ずに多部署の作業が止まるということがありました。

そこでアプリ(今回はiOSのみ)でログが正しく送られていることを保証するために、ログのテストをするようにしました。

全体の流れ

次のことをしました。

  1. EarlGreyでUITestを実装
  2. テストの中で送られるログをMockに保持
  3. テスト完了後、Mockにあるログの有無を確認
  4. テストをCircleCIで自動化

これで改修によるログの影響を保証出来るようになります!!

1. EarlGreyでUITestを実装

EarlGrey Referenceは、Googleが作っているiOSのUI automation test フレームワークです。

書き方は、簡単で以下の例の場合UIButton.accessibilityIdentifierに特定のIDを指定して、テストではselectElementで指定したIDの要素を取得し、要素の有無の確認、要素をタップ等できます。

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        button.accessibilityIdentifier = "BTN"
    }
}
class UIAutomationSpec: XCTestCase {
    func testTapButton() {
        EarlGrey
            .selectElement(with: grey_accessibilityID("BTN"))// 要素を指定
            .assert(grey_sufficientlyVisible())// 存在するかを確認
            .perform(grey_tap())// 指定した要素をタップする
    }
}

2. テストの中で送られるログをMockに保持

UITest内でログを送る際に、Mockにログを保存する処理を追加します。

class ViewController: UIViewController {
    @IBAction func didTouchUpButton(_ sender: UIButton) {
        LogManeger.send(log: Log(name: "tap_button"))
    }
}
struct LogManeger {
    static func send(log: Log) {
        isTest {
            LogMock.store(log)// Mockに保存
        }
        
        // Logを送る
    }

    static func isTest(_ doForTest:() -> Void) {
        #if DEBUG
            if ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] != nil && enabledUITest {
                doForTest()
            }
        #endif
    }
}

3. テスト完了後、Mockにあるログの有無を確認

テスト開始前に保証するログを指定して、終わった段階でログが揃っているかを確認する。

class UIAutomationSpec: XCTestCase {

    override func tearDown() {
        super.tearDown()
        LogMock.removeAll()
    }
    
    func testTapButton() {
        LogMock.addExpect(Log(name: "tap_button"))// 期待するログを指定
        
        EarlGrey
            .selectElement(with: grey_accessibilityID("BTN"))
            .perform(grey_tap())
        
        XCTAssert(LogMock.verify(), "Logが揃っていません。")// ログが揃っているか確認
    }
}

4. テストをCircleCIで自動化

実装したテストをCircleCIで動かすようにして、変更があってもログが送られることを保証できるか確認できるようにしました。 なかでもハマったところがいくつかありましたので紹介します。

ローカル環境では通るけどCircleCIでは通らなかった

一番長く戦った凡ミスです。 ローカル環境で実機確認してテスト通るのに、CircleCIで行うと通らないし何故か画面が真っ黒になっていました。

原因は、ローカル環境とCircleCIで実行している環境が違うので、UITestの結果が環境に依存する場合、結果が変わってしまうことでした。 CircleCIは、どこかの場所でこちらが指定したOS,端末のSimulatorで初回インストールとして起動されテストしています。 なのでローカル環境で確認する時に、CircleCIの環境を揃える必要があり、今回のようにローカル環境で実機確認していると結果が変わる場合があります。

テスト通らなかったのはわかるがなぜ通らなかったのかわからない

CircleCIでテスト通らなかった際に、どこの箇所で通らなかったのかはわかりますが、どの画面でなぜ通らなかったかはわかりません。 なので EarlGrey.setFailureHandler(handler: ) で通らなかった時のErrorMessageとその画面のスクショをSlackに送るようにしました。

f:id:tomo358:20180416192531p:plain

まとめ

まだカバーしてる部分は一部重要機能のみですが、テスト導入し今の所ログの不具合も起こらず、何よりUIの保証も最低限できるので安心して開発できるのが良いです!

BASEを日本一のサービスに成長させる仲間を募集しています!

BASEでは、Web、アプリ、SRE、データ解析など幅広い職種を募集しています。 ご興味を持った方、カジュアルな面談もできますので、一度オフィスに遊びに来てみませんか?

base.ac

入社半年でCakePHP本体にcontributeした話

こんにちは、BASE株式会社 BASE Product div サーバーサイドエンジニアの東口です。主にサービスの決済部分とPHP・CakePHPのバージョンアップをしています。

CakePHP2.10.9のリリースに対して、Koji TanakaさんとKazuki Higashiguchiがcontributeいたしました。

Release 2.10.9 · cakephp/cakephp · GitHub

f:id:khigashigashi:20180326093526p:plain

自分自身は、BASEに入社してからCakePHPを仕事で使い始めて半年、初のコントリビュートでした。備忘録としてコントリビュートに至った経緯を残していきます。

何をしたのか

Release 2.10.9 · cakephp/cakephp · GitHubを引用すると下記のBugFixを行いました。

CakeTestCase::getMockForModel() now correctly handles secondary connections.

github.com

だいたいの流れ

きっかけは、テストコードを書いていた際になぜか意図しない挙動をすることに同僚が出くわしたことでした。 実際に起きていたことはIssueに書いた内容ですが、テストケース内で、メインではないDBに接続するModelをmockするメソッドを使用した際に下記のエラーが発生していました。

MissingConnectionException: Database connection "Mysql" is missing, or could not be created.

Issueを出すところまで、既にプルリクを何度も送っている同僚のKoji Tanakaさんにざっくり教えてもらいながらやりました。おおまかな流れは以下です。

  • 調査
  • いけそうな修正方針決める
  • Issueを出す
  • 機能修正する
  • テストを修正する
  • Pull Requestを出す
  • マージしてもらう

今回は、既にテストコードが書いてあり通っていたのでなぜ通っているのかという原因調査が少し大変でした。

マージされた

今回のバグの原因調査にあたり、中のコード読んだりデバッグログを仕込んだりしているうちにCakePHPの中身が見えてきたのが良かったです。

最後に

今回のcontributeはちょっとしたBug Fixでしたが、今後も自社が使っているOSSが発展していくようコントリビュート頑張っていきます!

エンジニア募集中

BASE株式会社では、OSSにコントリビュートしていきたいエンジニアの方募集中です!

jobs.binc.jp

ヒカ☆ラボでBASEのPHP/CakePHPアップデートについて発表しました

BASE Back-End Engineerの田中 ( @tenkoma )です。アプリケーションのPHPアップデートなどを担当しています。

3/14 (水)に開催された技術勉強会ヒカ☆ラボにて、アプリケーションで利用しているPHP/CakePHPアップデートの取り組みについて発表しました。

【 ヒカ☆ラボ 】【Laravel5、CakePHP3など】ベンチャー企業のリアルなPHP事情 : ATND

サービスの裏側の話であり、今まで特に公開はしていませんでしたが、機会をいただいたのでこれまでの取り組みを振り返ることにもなると思い、発表することにしました。

BASEのPHPアプリケーションは2016年末までほぼPHP 5.3で動作していました。2017年にPHP/CakePHPのアップデートを推し進めるプロジェクトが立ち上がり、アプリごとに段階的にアップデートをリリースしています。 今回の発表では何を・どの順番でアップデート作業したかをお話しいたしました。同様のプロジェクトを検討中、実施中の方の参考になれば幸いです。

登壇資料

BASE の PHP アプリ アップデートについて // Speaker Deck


エンジニア募集中!

BASE株式会社ではモダンな開発環境をつくっていくエンジニアを募集しています。

jobs.binc.jp

PHPerKaigi 2018にプラチナスポンサー・LTスピーカーとして参加いたしました!

こんにちは、BASE株式会社 BASE Product div サーバーサイドエンジニアの東口です。主にサービスの決済部分とPHP・CakePHPのバージョンアップをしています。

下記の記事でも公開いたしましたが、BASE株式会社はPHPerKaigi 2018にプラチナスポンサーとして協賛いたしました。 devblog.thebase.in また、私自身もLTを採択いただいたので、スポンサー担当者兼LTスピーカーとして参加いたしました。

PHPerKaigi 2018

phperkaigi.jp  PHPerKaigi 2018は今年初開催のPHPエンジニアのためのカンファレンスです。 TrackA・Bの2つレーンがあり、TrackAがトーク、TrackBはコミュニケーション中心の企画が行われていました。   トークが1レーンだったこともあり、みなさんレベルの高い厳選されたトーク内容でした!また、TrackBで行われた「Interactive Round Table」等のコミュニケーションの場もとても盛り上がっていました。

会場の様子

TrackAを行っていたメイン会場の雰囲気です。

f:id:khigashigashi:20180311162427j:plain
TrackAの様子

f:id:khigashigashi:20180311182553j:plain
スピーカーが登壇する場所には豪華なバックパネル

会場には、PHPerKaigi 2018とスポンサー各社のロゴが乗ったバナーが設置されていました。

f:id:khigashigashi:20180311181112j:plain
会場バナー

また、参加者全員にカンファレンスのハンドバッグが配布され、弊社は5周年ノベルティ・ステッカー・チラシの3つを配布させていただきました。

f:id:khigashigashi:20180311183646j:plain
5周年ノベルティ・ステッカー・チラシ

LTの内容

私も恐縮ながら「レビューをもらいやすい細かいプルリクの切り分け方」というタイトルで発表させていただきました。

f:id:khigashigashi:20180311181830j:plain
発表中の様子

普段、やっている人は無意識のうちにやっているけどそれに対するノウハウが無いなと感じていたので、改めて整理したという内容です。

スポンサー担当をしてよかったこと

ここからは、私個人が申込から当日まで一貫してスポンサー担当をしていてよかったと思うことです。

カンファレンスに対する主体的な達成感がある

スポンサー担当者として参加すると、カンファレンス成功 = スポンサーをしたことの成功になるので、主体的に取り組むことになると思います。 当日までのスポンサー準備も含めて、カンファレンスが無事終わった際に「やり遂げたぞ!」という達成感がありました。もちろん、運営されているスタッフの方々の大変さに比べれば大変さはそこまでですが、一人の参加者として参加していた時とは違う気持ちの良い達成感が有りました。

ディレクションの経験になる

カンファレンスのスポンサー窓口をされている方とのやり取りや配布物などの準備の段取り、制作が必要であればデザイナーチームとの連携が必要になります。カンファレンス当日に向けてToDoを整理して進行していくため、普段開発のみの方であればディレクターと呼ばれるような方が行っているお仕事を体験できます。

最後に

今回は、記念すべき第一回開催にスポンサーとしてPHPerKaigi 2018に貢献出来たことを光栄に思います。 引き続き、PHPコミュニティの発展に貢献していきます。

エンジニア募集

BASE株式会社では、PHPerを募集しています! jobs.binc.jp

DroidKaigi2018にスタッフとして参加したらいろいろとすごかった

Androidアプリエンジニアの鈴木 (G_devi) です。 今まで何回かDroidKaigiに参加はしていたのですが、今回のDroidKaigi2018は初めてスタッフとして参加させていただきました。 その中で、運営・進め方・情報管理・当日の動き・臨機応変な対応など、いろいろとすごいなーとか、このやり方いいなーとか思ったことがあったのでお伝えしたいと思います。(書ける範囲で)

すごかったこと・いいなと思ったやり方etc...

どれが一番とか選べないので順番は特に関係ないです

globalチームがある

簡単に言うと、英訳してもらいたい文をここにお願いすると分かる人が翻訳してくれる感じです。

DroidKaigiは海外からも参加者や登壇者が来ますし、グローバルな対応が必要になってくるので何にでも英語が必要となります。 登壇者とのメールのやりとり、アンケートなど全体に投げるもの、海外サービス(Sessionizeなど)への質問など英語を用いるところはたくさんあるのですが、担当している人が必ずしも英語ができるわけではありません。(自分もできません)

slackの専用のchannelで英訳できる人のグループ(@english)宛に、こんな用途でいつまでにお願いしたいという感じで投げると、誰かがシュッと英訳してくれるという初めて見たときは感動するような流れ! 何よりみんなslackを使い慣れているので引用など諸々見やすく投げるし、感謝と謝罪もキッチリしているし、緊急度と重要度をみんながある程度把握しているため流れがいい。

こんなに素晴らしい流れができてる企業とかないんじゃないか?と思ったくらいです。

こういうのほしいなーという話が出たら誰かが作り始める

多分、いろいろ作られてたとは思うけどとりあえずパッと思い出したのは一つ。 github issueのMilestoneからもうすぐ期限が来そうなものをまとめてslackに投げて教えてくれるというもの。 全体で見ると結構な数のissueが作成されてるうえ、期限遵守しなくてはいけないものもあるため非常に見やすく気づきやすく素晴らしかった。

恐らくスタッフの大半が簡単なスクリプトを書いてシュッと投げるくらいのものはそれほど手間なくできると思うので、誰かに作業が集中してしまわないのが素晴らしい。まあ、忙しい人ほど自分で作ってちゃっちゃと済ませちゃうものな気がするけども。

用語集がある

まぁ、当然ですよね? ただこれがちゃんと存在してないと認識のズレや時間のムダにつながるのであることはとても重要だと思います。 用語が増えてきてメンテできずに人によって呼び方が違うものとか増えてくる現場にいた経験をするともう。。。

リアルタイムKPT

KPTを雑に書き込めるchannelがある。

確かに、思ったことはその場ですぐに記載したほうがいいですね。 DroidKaigi本番中もちょくちょく書き込まれていて、みんな結構slackのチェック頻度が高かったりもあるので、それを見て参考にもできるしとても良かったと思いました。 今更ながら、何でよくあるKPTの集まりでは時間区切って思い出しつつ書き出すことをするのだろうと。。 あのやり方だと後でこれもあったなと思うことが結構あるんですよね。

当然ながらslackに書き込んで終わりではなく、後で別途まとめると思いますが。 担当ごとに書き込むためのissueもありますし。

当日のインカム運用

当日はスタッフ全員がインカムをつけて緊急時の案内や共有などを行っていた。 slackでいいじゃんと思っていたが、結構動き回ってるうえ一般の人よりチェック頻度が高いと言ってもやはりリアルタイム音声連絡の便利さには敵わないものがありますね。 特に参加者から質問などを受けて自分が分からないときなどは急ぐ必要があるので非常に良かったです。

正直、撤収の途中からインカムを外したら不安になるし聞きたいことあるときに不便だなと思いました。 去年は全員がつけていたわけではなかったようなので、うまく改善がされていってるんだなという印象も受けました。 ただ、どうしても聞き取りづらいというのはよくあるので、いずれgoogle glassをつけて追加でも文字でも見れるようになるといいな〜。

2段階認証

当然だがキッチリしている。 当然ながら外に出せない情報もあるので重要なところですね。 何よりまだ設定していない人に対するリマインドがしっかりしていてよかったと思います。

最新情報の重要性の理解度

みんながみんな、情報が最新であることの重要性を強く認識しているため古い情報を見てズレたことをしてしまうという状況がほぼなかったと思う。 特に、セッションの司会や補助の割り当ては当日中にもちょくちょく更新されたので全員が最新情報をきちんと確認する必要があったが、通知もしっかりしていましたが問題なくみんなチェックしていたようでスムーズでした。 あとは、マニュアル類も都度更新されたりするのでそのチェックも重要でしたがデジタル主体の人が多いとなんと楽なことかと。(やはり便利なので印刷したものもありましたが) とりあえず手軽にgoogle docsは便利ですよね。

スタッフ用アプリ

なんと、スタッフが利用するアプリも作られていたのです!

マニュアル類へのリンク、Slack起動、Twitterで#DroidKaigi検索、各自の行動予定表、各ルームの進行中・休憩中表示の切り替え、そして何よりプッシュ通知でみんなへの連絡事項が文字で送られてくるというのは便利でした。(ちなみに最後の通知は打ち上げ会場についてでしたw)

半分くらい(?)はスタッフ初参加なようなので、このようにこれを開けばなんとかなるというものがあると迷わずに便利に動けて素晴らしかったです。

各種マニュアルの完成度

各種マニュアルの完成度がハンパないです!

上にも書いたように初めての人が多いというのもありますが、とりあえずこれを見れば大体のことは迷わずできるというレベルで作成されていました。 当日のことだけでなく、準備や撤収に関してもマニュアル化されているので非常に動きやすかったです。 しかも、こういうことも必要ではないかという話が出るとすぐに更新されて通知がくるのがまた素晴らしかったです。 いろいろな面で見習いたいところ。

責任の所在が明らか

全体、そして各担当の責任者が明確で(状況によって変わったりもありますが)その人に質問すれば大体何とかなるという状況。 もちろん質問だらけにならないようにいろいろ記載されているものがあるのですが。 何か発生した際の線引(これはやる。やらないなど)がすぐに分かるというのは素晴らしかったです。 まぁ、これもエンジニアらしく反応速度が早いからうまく回ってるというのもありますが。

やばい問題が起こらないように、そして確実に間に合わせるためにきっちりと内容を把握している責任者がハンドリングしているのは素晴らしかったです。 責任者が自分の担当範囲をキッチリ把握している。できない場合でも周りがフォローできるという体制は普通なようでなかなかできてなかったりしますからね。

受付アプリまで作られている

ついに1000人規模になったDroidKaigiですが、その人数の受付を回すとなるとものすごく大変なのは目に見えている。 参加者が提示したQRコードをスタッフの受付アプリで読み取ることによってスムーズな受付が可能だった模様。 "模様"というのも、自分は受付時に別の作業をしていたので現場は見ていないもので。。。 ただ、この辺も前回の反省を踏まえて作るという流れがいいですね。 何より特別な機器を用いなくてもスマホのカメラで可能であり、そのアプリをシュッと作れる人たちというのが強い。

ミーティングはハングアウトでも参加可能

スタッフもほとんどの人が普段の仕事をしているうえで夜に集まるので、どうしても参加できない人もいる。 また遠方の人もいるので、行くことはできないけどハングアウトで参加できるというのはすごく便利。 あと、議案・議事録もしっかりしているため参加できなかったとしてもある程度はきちんと把握できるようになっていました。 (自分もいろいろあってあんまりミーティングの場に行けなかったので非常によかった)

直接会って話すというのも重要なのですが、普段テキストベースでのやり取りに慣れている人が多いのもあり、議事録のチェックでも情報格差がそれほど発生しないようになっているのは非常によかったです。 経緯はともかく結果はしっかりとどこかに明記されているので。

そして、それほど回数も時間も確保できるわけではないのでミーティングのための準備もしっかり行われており、極力無駄な時間を使わないようにしていたのが素晴らしかったです。 これも非常に見習っていきたいところです。

急遽対応すべきことが発生したときの流れが良い

1000人もの人を動かすと、予期できなかったことなどが発生し急遽対応を入れたりします。 うまく人を流すために誘導を配置する必要がでてきたなど。 その作業タイミングで手が空いていそうな人をみつけ簡単に流れを説明するだけで動けるのは非常に良かったです。 何か分からないことがあればインカムで聞けますし。 エンジニアだからとは必ずしも言えないですが、ある程度自分で考えて行動できる人が多かったように思えます。

オープニング動画がかっこいい!!!

これはしびれた (まぁ、自分は準備でウェルカムトーク出てないし終わってから見たんですが)

www.youtube.com

その他感想

ひたすらに物理作業がツライ!!!

普段座ってばかりいる自分なので、、前日の電源を机に配置してテープで足をひっかけないように留めていく作業で疲労困憊。 セッションの司会補助で立ち続けてるだけでも脚がプルプル。 撤収作業で疲労困憊。 最初のほうは緊張もあり相当疲れました。 やはり体力は必要だなーと。

朝が早い!

と言っても、8:50厳守なので一般的に見たらそんなに早くはないのですが。 自分は朝に弱すぎるうえ、疲労困憊なので本当に心配でした。。 現地が西新宿で家が池袋なので結構近いのに本気で現地近くに泊まろうかと考えていました。 けど、参加者も泊まる人多いでしょうし、そんな近くに宿泊施設が多そうに見えなかったので断念。 少し歩けばいくらでもあるだろうけどそれなら帰っても変わらないかなーと。 最終的に知り合いに電話で起こしてもらうというリスクヘッジをして何とか乗り切りました。

スタッフの顔と名前が分からない。一致しない。

自分がミーティングにあまり参加できなかったというのもありますが、当日結構みんな初めましてという感じが多かったです。 slackやtwitterのアイコンや表示名は分かるけども実際の人と結びつかないというのはよくありますよねー。 人が増えてくると会社でもそうだったりしますよねー。 とはいえ、それでもうまく回るような感じではあったのですが、やはり顔と名前が一致するとだいぶやりやすくはなると思います。 (覚えるの苦手なんですが。。。) あと、みんなほとんどslackの表示名で呼んでいるのですが、どう読むのか分からなかったりw

スタッフ打ち上げ会場に人権(ネット接続環境)がなかった…

ほぼネット前提であるAndroidのイベントスタッフの打ち上げにこの状況は驚きましたねw 地下だったのもあり電波がほぼ届かず、現地WiFiもなかったです。(あったとしてもこれだけアクティブな人が80人?くらい集まってたらパンクするでしょうが…) まだ外部と連絡とる必要のある人もいたでしょうしせめて繋がる環境だったほうがよかったのでは?とは思いました。 何より自分が欲しかった。。。w

最後に

個人的に非常に為になり、参考になり、楽しかったです。 他にも良かったと思うところはたくさんあるのですが、とりあえずパッと思いつくところを書きました。

やってみたい人や組織運営に悩んでる人なども一度スタッフとして参加してみると為になるかと思います。 元の仕事や準備など諸々で時間がなくアプリ開発のほうには関われなかったのが残念だったので、来年は多少手を付けられるといいなと思いました。

スタッフのみなさん、登壇者のみなさん、そして参加者のみなさん、ありがとうございました!!

(文字だけで寂しいのでスタッフ名札写真でも載せようと思ったら無くしてしまったようだ…泣)