Robolectric 4.2の変更点とアップデートできずに詰まっている点について

f:id:shaunkawano:20190312231526p:plain

Robolectricとは

RobolectricとはAndroidのためのオープンソースのユニットテストフレームワークです。レミュレータや実機を起動してテストを実行せずとも、JVM内の擬似的Android環境上でテストを実行することで、テスト実行時にActivityなどのAndroidプラットフォームのクラスを利用・テストできます。

github.com

Robolectric 4.2

一ヶ月弱前に、最新バージョンとして4.2がリリースされました。

※詳しくはrobolectricのreleaseページを御覧ください。

今回のリリース含め、DeprecatedになったAPI一覧はこちらです:

robolectric.org

デバイス上での実行時と挙動を同じにする

Robolectric 4.2からは、Robolectricテスト実行時の挙動とデバイス上でテストを実行した時の挙動を統一するような変更が行われています。

具体的には、今までRobolectricを使ってActivityを起動するようなテストやContextを用いたテストを実行するためにActivityを起動する際のテストを記述する際には、下記のようにしていました。

val scenario = ActivityScenario.launch(FragmentActivity::class.java)
...

scenario.onActivity {
  ... // assert some text with activity as `it`
}

今回の変更から、Robolectricを用いたテストではこのようなActivit起動の指定の仕方はNPEで落ちるというような挙動となっています。そしてこれは、Robolectric側の意図した挙動となっています。

どういうことかというと、今まで上記のような指定でActivity起動をしていた際には、Robolectricでは暗黙的かつ自動的にAndroidManifestのエントリーを作成しテストが実行できるように制御してくれていたのですが、それはRobolectric独自の挙動でありデバイス上での実行時と挙動が異なるものであったため、バージョン4.2からは自動でそのような自動生成だったり独自制御をせず、基本的にはAndroidFrameworkの挙動に準拠するようになった、ということになります。

デバイス上での実行と仮想環境での実行を統一するという流れは理にかなっているかと思います。

なので今後RobolectricでActivitを用いたテストを実行する際には、実際のAndroidManifest.xmlにテストで利用するActivityを定義しておいて、それをテスト時に参照する、ということが必要となります。

未解決の課題

ただ、執筆時点では、最新バージョンに上げるためには、まだ課題が残っています。どういう課題かというと、現状のAndroid Gradle Pluginの課題(もしくはRobolectric側で解決できる課題?)として、testImplementationで指定したモジュール内のAndroidManifest.xmlをマージしてくれないというものです。

https://issuetracker.google.com/issues/127986458

この解決策として、Robolectricのレポジトリのissueには、テスト専用のモジュール(たとえばtestsupportモジュール)をプロジェクト内で定義した場合には、そのモジュールをapp/build.gradle側でimplementationしつつ、testsupport/build.gradleではimplementation project(':app')することで暫定対応できるとの紹介がされています。

github.com

ただ、素直にこの解決策をサンプルレポジトリを作って試してみたのですが、自分ではうまく解決できなかったため、今のところアップデートできずに詰まっているという状態です。

具体的にどういう実装になっているかご覧になりたい方は下記をご覧ください。

github.com

自分の指定の方法が間違っている、勘違いしている箇所がある、ということはかなりありえるので、なにか気づいたことなどあればコメントなどでご教授いただけると幸いです🙏

アップデートに成功した際には、下に追記していく形でこの記事を更新していく所存です。

以上、詰まってアップデートできていない、という話でした。

2019年1月を振り返る

あっという間に1月が終わりましたね(゚∀゚)キタコレ 執筆時点では、なんと2019年、90%を切りました [壁]ョ゚ω゚;)))ガクブル

それでは1月を振り返ります。

年明けからの初詣

f:id:shaunkawano:20190304003655p:plain

代々木八幡宮へ。

f:id:shaunkawano:20190304003658p:plain

中吉。去年は小吉だったと思うので、良き。

実家帰省

タイミングずらしたほうが飛行機代が安いので、年が明けて少し経ってから実家に一時帰省ました。

f:id:shaunkawano:20190304003701p:plain

写真は阿蘇神社内にて。

Matching Dev Meetup#2 - ServerSide開催

f:id:shaunkawano:20190304003703p:plain

写真はMatching Dev Meetup会場のEureka, Inc.にて。

弊社からはSREチームのエンジニアのるいさんと、エンジニアリングマネージャーの河野さんが登壇しました!次回もまた別テーマで開催予定なので乞うご期待・・!もうすぐconnpassページ公開かも?

その他

I Feel Prettyを観た

自分の体型が気になる女性が頭を打ったことで自分が理想の見た目を手に入れたと錯覚し(実際の見た目は何も変わっていない)、それがきっかけで他の人との接し方や環境が変わっていく、という物語でした。

www.youtube.com

どんなに自分が羨む人や自信たっぷりに見える人でも、きっと不安なことがあるだろうし、みんな自尊心を持っているわけではない。自信がなかったり自分のことを褒めれない人は、自分の考え方をちょっと変えれば、もしかしたら自信が少しずつでも生まれてくるかも、ということが伝わりました。

あとボヘミアン・ラプソディも観ました。映画館で見てよかった映画でした!

文喫に行った

六本木にある「文喫」という本屋さんに行ってきました。

bunkitsu.jp

一回1500円でWi-Fi / 電源 / ロッカーがあり、コーヒーなどは飲み放題です。本持たくさんおいてありもちろん手にとったり席で読み漁るのも自由なので、1500円は少し高いかなと思いましたが、お金を払ったのでちゃんと読まねばという気持ちになり、一気に読み切るのが苦手な自分ですが、その場で一冊読み終えることができました。

イーロン・マスク完全に理解した。

f:id:shaunkawano:20190304003708p:plain

こんな感じで本がずらっとあります。

f:id:shaunkawano:20190304003711p:plain

作業スペースやゴロンとしながら本を読めるスペースもあり、よさそうでした。

月2くらいで来たいな〜というくらい集中できる場所でした。

あとは27歳になったり、ひたすらDroidKaigiの資料作りについて考えていました。

点での振り返りが多いですが、1月はこのような形でした。 雑だな💩

1月もお疲れ様でした!!

27歳になりました

f:id:shaunkawano:20190304003356p:plain

このまえ27歳になったので、26歳の振り返りと、27歳の抱負についてざっくり、ささっと書きます。

26歳の振り返り

26歳の振り返りを3つだけにまとめるするとすると、下記の3つとなりました:

  • 登壇数をとにかくこなす、として、とにかく登壇回数を意識した
    • speakerdeckの資料数は前回誕生日の頃から数えて10スライドでした
  • 毎月ブログを書くということを継続した
    • 振り返りだけの月もあったけど、なんとか、数だけは、、という形
  • 本当にいろいろなことを経験させていただけた(業務)
    • 新規立ち上げが終わり運用フェーズから、別子会社出向からの、いわゆるマネージメントの分野まで今年はチャレンジさせていただきました

振り返りをすると反省点だらけです。

以前、勉強会でお会いした著名なAndroidエンジニアの方が、「アウトプットの数を意識しすぎて資料や内容の質が下がってきたので、一旦アウトプットやめる」と言っていたのは今でも鮮明に覚えていいます。自分はこの一年、質を低下させずに数をこなすことができていたかな?と思うと、質は低下していたこともあったと感じています。

ブログに関しても、同じように、振り返りブログを書くことで、その月やっていたことはもちろん、「あのときはああいう状態で、ああいうふうに感じていた時期だったな〜」と、その当時感じていたことだったりも一緒に思い出せたり振り返りができてすごく良いと思う半面、技術的な記事は減ってしまいました。

業務に関しては、贅沢なまでにチャンスをいただけたと、その時々でも、振り返ってみても、思えるくらいに充実しているとおもいます。(冗談でも誇張でもなく)

仕事は、富豪な裕福ニートでもない限り、1日1日の中で大部分の時間を占めるものだと思っていて、その仕事が充実していると思えているのは幸せなことだと思っています。このように思えるのは、紛れもなく、優秀、そして優秀であること以上に、優しく尊敬できる社内の方々に支えられているからだと思います。本当にありがとうございます。

恩返し、というわけではないかもしれませんが、そういう方々に自分もなにかを与えれるように、初心を忘れずに、また0から精進できればと思っています。

--

27歳は、

  • Android以外の技術
  • 量<質にを意識して、ブログでのアウトプット
  • 個人でなにか作る

を特に意識します。

今年も元気に、そして上にも書きましたが、尊敬できる方々に自分がなにかを与えれるように、初心を忘れずまた0から精進します。

(誰向けかわからないし、変に真面目になっちゃった)

うんち💩💩

DroidKaigi 2019にて「アプリをさらに成長させるための技術戦略」というタイトルで登壇をしました

DroidKaigi 2019とは?

Androidの技術情報の共有とコミュニケーションを目的としたカンファレンスです。2015年から毎年開催されており、2019年は、2月7日〜2月8日の二日間、開催されました。

droidkaigi.jp

登壇内容

「アプリをさらに成長させるための技術戦略」というタイトルで、初めての50分枠で登壇しました。

内容としては、今担当している絶賛成長中のプロダクトを、技術でさらに成長させることを目的に弊社の技術組織が行っている「技術戦略」についての紹介を主として、そこから自分個人の反省、振り返りを共有させていただく、というものでした。

speakerdeck.com

登壇までの準備

今回のような、エモかエモくないかでいったらどエモな内容の資料作りは初めてでした。そういうこともあり、自分としてはある種のチャレンジでした。発表資料を作る際には、とにかくどういう構成にしようか、ということが一番悩みました。

目次、伝えたいことなどを書き出したりもしたのですが、いざスライドを作り始めると、「この流れは伝わりやすいのかな?」と思ったり、ある一定のところまで書き出すと、「この発表、興味ある人いるのかな。」と急にネガティブになったりもしました。そんなこともあり、発表で伝えたい内容を一旦メモ帳に書き出しても、どうスライドに落とし込むのがいいのかなぁ、前提の話もある程度したほうが伝わりやすいかなぁ、など考える時間が多くなってしまっていました。

着地、終盤になってガガガっと無理やり進めるような(全く理想ではない)、慌ただしさは、今までと同じでした。

当日の振り返り

反省点として、やはり何度も言い直したりしっくり来る言葉がその場で見つからず1秒くらい止まってしまうようなことが何度かありました。 (当日聞きに来てくださった皆様で聞き苦しいと感じていた方、申し訳ありませんでした。🙇‍♂️ )これに関しては練習をするための時間が不足していたということに尽きるかと思います、、とはいえ、去年よりは良くなった、場数を踏み続けるしかない、とポジティブにも捉えて落ち込みすぎることはないようにもしたいと思っています。

良かったことは、自分が思っているよりも共感してくださる方や、リアクションをくれる方が多かったことです!登壇後、エクシビジョンホールやTwitter上で質問だったり共感の会話をしたり、去年よりもいろいろな方と自分の発表内容について話せたことが、なにより嬉しかったです。

また、同じ会社のエンジニアの方々も数人見に来てくださり、(正直弊社や弊社グループの方々は、他の方の発表を聞いていただいたほうがためになるでしょ!と思いつつ、)発表の場では励みになりました。 ありがとうございました 🙏

感謝

毎年、こうやってDroidKaigiを楽しめるのは、本当に運営の方々のおかげです。本当にありがとうございました。そしてお疲れ様でした!!

P.S. DroidKaigiはある意味、これからです。動画や資料を見返して、業務や個人開発で皆さんの知見を血肉化していきたいとおもいます。

2018年を振り返る

2018年をブログ記事で振り返ります。

1月

blog.shoheikawano.com

振り返りブログを書き始めました。いつまで続かわからないけど、という形ではじめました。振り返ったら1年(なんとか)続いてよかったです。

DroidKaigiの資料作りに精一杯になっていた月でした。

2月

blog.shoheikawano.com

DroidKaigiにて、Fluxについて発表しました。初めて30分という英語枠での登壇でした。緊張したし失敗もありましたが、それ以上に登壇する際に自信が少しつきました。

Okioについて調べ、@stsn_jpさんと一緒にDroidKaigi Rejectonにて発表しました。あれだけライブラリのソースコードを読み漁った夜はなかったです。楽しかった。。!

3月

blog.shoheikawano.com

Droidcon BostonにてFluxについて発表しました。DroidKaigiでの発表内容をベースに修正を加えたものを発表しました。米国での発表ということで、DroidKaigi同様初めてのことだったので、とても緊張しました。。もちろんこちらも反省点がありましたが、運良くプロポーザルが通り、登壇できて嬉しかったです。発表後、オーディエンスの方から声を発表スライドについて褒められたことも忘れられません。

社内では、別子会社に出向となり、新たな転機となりました。

4月

blog.shoheikawano.com

初めて技術書典に出す本を執筆し、販売しました。内容はOkioの内部実装についてでした。総数は少なかったですが、無事完売できてよかったです。

5月はGoogle I/Oということで、Pre-Partyなどにも参加しました。

5月

blog.shoheikawano.com

Google I/O 2018に参加してきました。Google I/Oについての振り返りブログはこちら。また、Bitrise×Fastlaneを用いた自動化やマルチモジュール化を始めたりとしました。

6月

blog.shoheikawano.com

Kyash Meetupに参加したり、Bitriseについての発表をしたりしました!初Kyashオフィスきれいだった。

この頃は事あるごとにKyashで支払いしたい病でした〜!

7月

blog.shoheikawano.com

社員旅行に行ったり、「レビュー」という業務内の作業について社内の朝会で発表したりしました。

夏は、暑かったですね。

8月

blog.shoheikawano.com

motifについての発表や、Bitriseのキャッシュについてなどの発表をしました。

タイに旅行に行ったりしたのも良い思い出です。初タイ、良かった。

9月

blog.shoheikawano.com

DevFest Tokyo 2018にてパネルディスカッションに参加しました。授業参観のような形でした!AACはこれからもAndroidアプリ開発においては重要なコンポーネントになるはず。引き続き精進。

マッチング業界のエンジニア同士で集まって飲み会やって、勉強会開催しましょう!!とアツくなれた。

10月

blog.shoheikawano.com

Android Weekendイベントを復活しました。英語で登壇したい人、練習したい人、ぜひ来年もやるのでチェックしてください!

www.meetup.com

また、技術書典にて再度本を出版しました。今回はPicassoの内部実装についてでした。このときも、全部売れてよかった。

あとは、秩父観光に行ったりとか。楽しかったです!

メイプルベースというお店がとても素敵でした。

11月

blog.shoheikawano.com

Matching Dev Meetup開催!自分で企画からやったイベントでした。楽しかった。。

DroidKaigiプロポーザル採択通知。チャレンジ。🙏

12月

blog.shoheikawano.com

チームだったり技術戦略とかに一番集中した一ヶ月だったと思う。

DroidKaigiの資料作りも頑張る!


振り返ってみると、たくさん新しいことや発表だったりができた一年でした。

社内では、新たなミッションだったりチャンスをいただけて幸せだと思っています。

2018年も大きな事故などなく、元気で過ごせてよかったです。

2019年も元気に過ごしたい。

今年もお疲れ様でした。お世話になりました。

来年も何卒宜しくおねがいします。

2018年12月を振り返る

2018年も残りあと数時間です。

それでは、12月を振り返ります!

12月やったこと

社内では、内定者アルバイトのAndroidエンジニアがチームにジョインしたり、職種ごとに定めた技術戦略を推進する日を設けてエンジニア全員で取り組んだり。

プロダクトとしては、アプリがGoogle Playフィーチャー枠に掲載されたりと、いろいろな嬉しいことがありました。

プロダクト開発では、大きめの機能開発に携わせてもらうこととなり、モックを作り始めたところです。来年頭は、こちらにさらに注力します。

そのほか、休日などは、代々木公園にある青の洞窟に行ったり、

GooglePixelコラボのカフェに行ってみたりしました。

「Search」という映画も見ました。噂通り、映画の内容すべてがPC画面上に映されるような描写となっていて斬新だなと思いました。斬新さだけではなくて、内容も申し分なく面白くてよかったです。また観たい。

www.youtube.com

そして今は、引っ越して初めてテレビをつけて、ふるさと納税のお礼品を堪能しながら、ガキ使を見てのんびりしています。

12月内容あんまり濃くないけど、こんな感じでした!(雑)

皆様、師走もお疲れ様でした!!🐗

Notes - Fun with LiveData (Android Dev Summit '18)

※Notes記事では、英語のセッション動画やポッドキャストの内容を(雑に)英語でメモに書き残すことを行っています。本記事は、あくまで動画を見ながら、参考程度に読んでいただくことを想定しています。Notes記事には雑メモ程度のものだったり、書き起こしのようなものもあります。これから実際の動画を見る際には、本記事の内容が少しでもお役に立てば幸いです。(内容において不備、誤字脱字等ありましたら気軽にご連絡いただけると嬉しいです。)

本記事は、Fun with LiveData (Android Dev Summit '18)の記事です。

f:id:shaunkawano:20181216213849p:plain

LiveData

Simple

Lifecycle-aware

  • In order to observe LiveData you need to provide lifecycle
  • LiveData is going to remove subscription on appropriate lifecycle event, for free

Observable

  • Activity and other view components have different lifecycle
  • Even Activity, when rotation changed, gets recreated and if some components have a reference to this activity then it leads to memory leak or worst, crash with NPE

=> Instead of letting something have reference of Activity, letting Activity observe live data is safe.

Data Holder

  • Live data is not a stream, data holder
  • If you want some stream concept use Rx

Transformations

  • If you use LiveData and ViewModel, you totally need to have transformations

Antipatterns

  • Storing big objects across Transformations
  • Sharing instances of LiveData
class SharedLiveDataRepository(val dataSource: MyDataSource) {
  private val result = MutableLiveData<Long>()

  fun loadItem(itemId: String): LiveData<Long> {
    result.value = dataSource.getData(itemId)
    return result // here we share the `result` LiveData
  }
}
  • Edge case: Activity Transitions
    • Two activities are active at the same time
    • If your class is a repository and you are creating a field of LiveData then maybe you are doing something wrong

When NOT to use LiveData

  • If you need a lot of operators or streams, use Rx.
  • If your operations are not about UI or lifecycle, use callback interfaces
  • If you have one-shot operation chaining, use coroutines

📝

  • LiveDataはデータホルダーなのでメモリに保持したくないようなオブジェクトは渡すべきではない
  • オペレーターやストリームの概念が必要なのであればRxJavaなどのリアクティブのコンセプトに特化したライブラリを使うべき
  • LiveDataのインスタンス共有は、(2つのAcitvity内のLiveDataが同時にActiveになる可能性があるため)極力避ける。そのような場合は都度、新しいLiveDataを生成。LiveDataの生成はそこまで重たい処理ではない。