「テストが書きやすくなる」の意味を紐解く
Androidアプリの話です。MVPアーキテクチャをAndroidにいれることでどういうリターンがあるんだろう?というのがもやもやしていて、「テストがしやすくなる」というメリットについてあまり実感持てずにいた。単体テストコードを書いていてなんとなくこういうことかなーと考えたことをまとめてみる。当たり前じゃん&間違ってるかもしれないけど、そこはご指摘いただければ…。
notMVPケース
前提
- FragmentやActivityでAPIをたたいてたりDaoの呼び出しも書くケース
- コールバックのinnerClassもFragmentに書いたり(privateで)
- privateのinnerClassで持っているメソッドをテストしたい。
public class SampleFragment extends Fragment{ private static class hogeCallback { public void onSuccess(boolean ishoge){ String testCase = ABテスト値取得; if(testCase==isA() && ishoge){ hugaView.setVisibility(GONE) } } }
書こうとするときにぶちあたる壁
その時確かめたいテストケースは「testCaseがhogeで、ishogeがtrueの時、hugaViewが表示されていること」だった。これを実現しようとして考えたことが以下。
- privateのinnerクラスってどうやって呼ぶんだろう
- assertは何でしたらいのだ?Espressoで表示中かどうかを確かめたらいいのか?
- テストしたいケースはAPIを叩いた後のコールバック時のメソッド。どうやってその状況を再現する?
- 単純なテストケースに見えるけど、なんか大変そうだということはわかった。
結局どう書いたのか
- privateだったinnerClassをpublicにした
- testCase変数の値によってテスト結果を確かめたかったので、testCase変数をメンバ変数でもたせる(コンストラクタで渡す)か、引数に追加する
@Test public void hogeTest(){ String testCase = "A"; ViewGroup viewGroup = mock(ViewGroup.class); when(viewGroup.getVisibility()).thenReturn(View.GONE); SampleFragment.HogeCallback hogeCallback = new SampleFragment.HOgeCallback(context, viewGroup, 0, testCase); countCallback.onSuccess(0, true); verify(viewGroup, times(1)).setVisibility(View.VISIBLE); }
だいたいこんな感じでテストケースを先輩に習いながら書いた。 正直、自分がこれを書こうと思ったら結構時間かかりそう。実際悩んだし。 結局、テストのためにプロダクトのコードを変える必要があってなんとなく良くないんじゃないか?と思っていた。
MVPで分けてみる
じゃあこれをMVPに書き換えて書いてみるとどうなるか? 簡単に、Viewじゃないところはpresenterにやってもらうようにした。
HogeCountTask task = new HogeCountTask(this).execute();
Fragment内で、API叩いてcallbackをもらう処理はpresenterに移す。
presenter.executeHogeCountTask();
presenterにlistenerをimplementsさせて、presenterの中でコールバックを受け取る
@Override public void onSuccess(int count, boolean ableMoreSelect) { String testCase = getHelpMessageTestCase(); boolean isShowHogeView = isShow(count, testCase); view.setVisibleHHogeView(isSHoe); } @Override public void onError(ResultDto resultDto) { }
こんなかんじ。で、ここでそもそも今回のケースではlistenerを継承したinnerClassは使わなくてよかったのでは?じゃあFragmentの中に書いてあってもテストの書き方は変わらないのでは?と思ったり。けどそれが気づけてシンプルにできたのならそれもまたいいところということで。
Presenterにロジックを移すということ
AndroidでFragment,Activityのテストをするのは気が億劫だ。(私だけなのだろうか) 正直正解がわからないし、どう立ち上げるのが正解かわからない。 presenterに移しておけば、Viewをモック化するだけでなんだかすごそうなツールを使わなくてもできる。
@Before public void setUp() throws Exception { context = InstrumentationRegistry.getTargetContext(); view = mock(SampleView.class); presenter = new SamplePresenter(view, context); } @Test public void 正常_isHelpMessageView() throws Exception { Method method = JobTypeSelectNewPresenter.class.getDeclaredMethod("isHelpMessageView", boolean.class, String.class); method.setAccessible(true); boolean result = (boolean) method.invoke( true, "SHOW"); assertTrue(result); }
だいたいこんなかんじ。privateメソッドだということ以外は結構スラスラかける。
結果「テストが書きやすい」ってこういうことなのでは?
- 「これを渡したらこれが返ってくる」って思考をそのままコードにしやすい
- viewのギリギリまでテストができる、しかも単純な。
- とりあえずあんま難しいこと考えなくていい
雑なまとめになっちゃった。新しいアーキテクチャいれるって時、何が目的なんだろう、いれたらどんないいことがあるんだろう、って自分は今までアーキテクチャを理解するだけで考えられなかったので、少し違う側面が見えてきたかも?というお話でした。まる
ばあちゃんが残した800枚の絵をフォトブックにするまで
1年とちょっと前の8月15日、朝起きたらばあちゃんが亡くなってた。 葬儀や納骨が終わって少しだけ儀式が落ち着いた頃、母が部屋を掃除したところ、油絵が出てきた。しかも大量に。ばあちゃんの絵の部屋、倉庫、押入れ、どこ開けても絵が出てきた。だいたい800枚くらい。 まだまだばあちゃんの死を受け入れられなくて、何かこの絵をこのままにしておくのはもったいなくて、フォトブックにすることにした。
11月~2月 絵の撮影
まずは絵を写真ですべて撮影をする。 なるべく写真そのまま使えるよう、お家撮影セットを作った。 ホームセンターでベニア板と壁紙、何かをひっかけるアレを買ってきて、デスク用のライトで照らす。これで絵を撮影した。
だいたいばあちゃんが描いたジャンルは花、人物、人形、モノ(静物)、風景みたいだったので、ジャンルごとに撮っていくことにした。何に使えるかわからないけど一応番号をつけながら。
一枚ずつ番号をつけながら撮影していく過程で「この絵いいね」「これひいおばあちゃんのこと?覚えてる?」なんてひとつひとつ絵を見れた。 月1,2回実家に帰って少しずつ撮影していった。なかなかかかって結局ずいぶんかかってしまった。
6月~ 絵の整理・加工
だいぶ時間が空いてしまった。ちょっと絵を撮り終えて気が抜けてしまったがまだ仕事は終わってない。 写真を整理してみると、明るさはバラバラ。朝撮ったものもあれば夜撮ったものもあって。お家スタジオには入らない大きさの絵もあって、電球の暗い玄関で頑張って撮ったのもあった。 それに歪みがひどい。私が撮ったやつまじひどい。綺麗な正方形になってない。 ということで明るさ調整&歪み調整が必要になった。800枚。 明るさを調整した写真を… 切り取る 歪みを調整して 長方形に修正。
photoshopで機械のように処理した2週間。 本当はスクリプトとか書いて自動化できたのだろうか?と思ったが私の実力ではわけわからず、ショートカットを設定するしかできなかった…。 なかなかに辛い&気が遠くなる作業だったが、また絵を一枚ずつ眺める機会ができてよかったと思う。
7月~ レイアウト&発注
気の遠くなる作業が終わった後は、レイアウトを作る作業だ。 発注はapple photobookサービス。 www.apple.com
apple photobookサービスは自動でレイアウトが組まれたのを選べるのだが、キャンバスのサイズが縦横比が自由すぎて、絵をだいぶ削る必要がありそうだった。また、7月末の一周忌に間に合わせたいという母の要望を叶えるため結構なタイトスケジュールであったため、自分でレイアウトを組んだ方が早いと判断し一枚ページとして作ることにした。 イラレでなんとなくレイアウト組み… こんな感じにして入稿!
混んでいる時期だと2週間くらいかかると聞いたので早めに急いで出したけど、結局5日で来てappleすごい。
完成
150ページくらいの大作になった。(デフォルトは20ページ) 同じページを2枚入稿してしまったことと若干の日付を間違えてしまうドジっ子は許してもらった。
手元にコンパクトで置いておけるフォトブックにできたこと、なによりばあちゃんの油絵キャンバスをデータ化できたことはちょっとホッとしたかもしれない。 結構好きな絵がみつかったこと。家に絵を飾るって結構いいかも。なんて。 せっかくだからもらってくれる人がいないかな、なんて。 せっかくたくさん家にある絵を活用したいななんて思う夏の終わりなのでした。
アラサーの女子力をslackで監視する
事の始まりは「20代女子は肌に投資すべし」というツイートに煽られエステのお試しに行った私が彼氏に「エステ通いたい…」とつぶやいたところから。 「それって効果あるの?」から始まり、「KPIは?」「どうやって効果あるって測るの?」「きちんと数字でモニタリングして効果があったらいいんじゃない?」と煽られた。くそう!その通りである ということで肌の調子をモニタリングできる環境を整えることにした
測定ツールの導入
今まで肌の調子を測るものは私の感覚であった。なんとなく化粧のノリがいいぞ、つるつるしてるぞ、と自分の感覚値でしかなかったので、客観的にわかる数値を出せるものを探した。 すべての肌の調子は水分量に宿ると信じてこちらを購入。
https://www.amazon.co.jp/gp/product/B008N4KKKA/ref=oh_aui_detailpage_o02_s00?ie=UTF8&psc=1
毎日の測定
朝起きてからこれで毎日同じ位置で測定。 これをスプレッドシートにでも記録してグラフにでもしてやろうと思っていた。 amazonのレビューを見てると、夜スキンケアした後だと高く出たりで安定しないので、朝起きた時がよいとのこと。ということで朝起きた直後に毎日測ることにした。
パックした次の日とかは水分量が高く出たけど謎。
こんな感じで測定できます
めんどくさい
朝スプレッドシート開くわけがない 朝メモまでは頑張ってするけどその後、スプレッドシートに記録することなく一週間が過ぎていった。
つぶやいたら記録しておいてほしい
ということで、slackでつぶやく→スプレッドシートに自動で記入されたら負担が楽になるのでは?と思いスクリプトを作った。
ボット作成 http://qiita.com/kyo_nanba/items/83b646357d592eb9a87b
ライブラリ http://qiita.com/soundTricker/items/43267609a870fc9c7453
slackのchannelIdを取得 http://qiita.com/Yinaura/items/bd28c7b9ef614696fb7e
ほぼこれでいけた。ありがとうございます。
ハマったところ
GASで何かを書くのがなかったのでちょこちょこ初心者のハマりしたかと思う。
slackからのコマンドを受け取る
- ウェブアプリケーションとして導入
アプリケーションにアクセスできるユーザー:全員(匿名ユーザーも含む)
にしていないと届かない。
- コードを変更した後→ウェブアプリケーション導入 バージョン情報をあげないとコード内容が変更されない
受け取ったデータをスプレッドシートに移す
http://qiita.com/nurburg/items/744ec53477f4ae328555
仕様としては以下。
次ごとにシートを分ける
結構日毎だとあまり変化がなくて効果がわからないので6月分のシート、7月分のシートなどに分けて月次で数値も出したらわかりやすいのでは?と思い、新しい月になったら新しいシートを作るようにちょっと手直し。
結果
slackで朝測定した値をつぶやくとbotが返ってきて成功。 こんなかんじで記録されます。
感想
- slackの可能性無限大。
- 毎日知らずのうちに溜まっていってるのが楽しい。
- スチーマあてて結構頑張った時は次の日の水分量高い(飲み会後とかで適当に寝た時は低い)
- 6月の平均値:40.29411765 7月の平均値:40.58823529 微妙すぎる
- 女子力あげたい!!!!!
おわり
文系からエンジニアになって1年が経っちゃったよ
文系でバックグラウンドなかったけど、新卒入社でエンジニアとして配属、働いて1年経った区切りなので振り返ってみます。
何エンジニアか
(ちなみに、学生時代はHTML,CSSをちょろっと書いていたくらい。webのフロントに必要なJSも少しだけ。)
1年間の仕事内容
JavaでWebアプリ開発(研修)
研修でJavaを学習、フルスクラッチでWebアプリを1本書いた。 今まで「ちょっとかじってきましたー」がいい感じに叩き潰されて一からJava勉強できてよかった。
新規アプリ開発①
OJT的なプロジェクト。1ヶ月ほどのAndroid学習期間の後アサイン。 ベテランの先輩のサポートもたくさんあってAndroidアプリってこうやって開発してリリースするんだぁ、って一連の流れがわかったという感じだったと思う。コーディング規約に沿ってないとか超基本的なところを指摘されてた。
新規アプリ開発②
1つめのアプリをベース&ちょっとアレンジしたアプリで、ベテラン先輩なしで1ヶ月ちょっとで開発。 少しずつできることも増えたけど不具合お化けである。 iPhoneアプリがすでに先にリリースされていたので、「iOSが正で!」的な要件だった。 iOSではできるけどAndroidでは実装つらい挙動とかにぶつかってAndroidのデザインとは?みたいなことを考えていたような気がする。
新規アプリ開発③
もうひとつ新規アプリ開発をした。規模は小さかったけど、MVP設計を取り入れて開発したアプリ。 設計とは?みたいなところも初めて考えるきっかけにもなった。結局何が嬉しいの?ってところをよく議論・考えたような気がする。 この時にかなり細かいところまでガッツリコードレビューをしてもらったのがとてもよかった。 そのお陰で「こういう書き方にした方がいいのでは?」みたいな意志がやっと芽生えた気がする。
既存アプリのエンハンス
すでに数万のアクションをもっている既存のアプリチームに入った。 スクラムな体制で開発を進めていて、いくつかエンハンスの案件をやらせてもらった。 エンハンスで入るのは初めてだったのと、今までとは比較にならない規模の大きさ&ソースコードの複雑さで最初はかなり大変だった。あまり新しくコードを書いて機能を追加したりはしなかったが、プロダクトオーナーからの要求に対して最適な手段を提供するにはどうしたらいい?みたいなことを考えていた気がする。既存のコードがあるから、Howが一筋縄ではいかない、じゃあどうする?みたいな壁にたくさんぶつかれた気がする。
資格など
1年目に会社から課された資格が以下の3つ。ギリギリだったりしたけど3つ全部受かった。
Oracle Java Silver
研修でも業務でもやっていたので、良い復習&穴を埋める機会になってかなりよかった。 それまで「やさしいJava」みたいな本しか読めなかったけど、この資格きっかけに「Perfect Java」のありがたさを知る。今までなんとなくでしか理解していなかったものを色々発見しながら深められたのは楽しかったし、ベースアップにもなったと思っている。 いつでも受けられるけど受験料がクソ高いのが難点。
応用情報技術者試験
ここから業務とはあまり関連のない分野もたくさんで辛かった。 2ヶ月くらいガッツリ土日の時間を割いて勉強していた。半年に一回しか試験がないし、落ちてもごまかしようがなくてかなりのプレッシャーだった。 情報系の全般知識を広く学べたのはよかったと思う。名前でも聞いたことがある&なんとなくあそこらへんの言葉だ、というのが今後に生きると信じてる。
LPIC レベル1
これも業務との関連性はなし。3月ギリギリまで残してしまった。 試験に受かるための勉強になってしまったことが反省。 コマンドのオプションなどかなり細かいところまで聞かれる自分にとっては鬼畜試験だった。 内容はとても楽しかったけどね。101に関しては一回落ちたんだけどね。受けなおしてなんとか取ることができました。
業務以外
プロコン
同期と何人かでやっているプロコン勉強会。 蟻本を参考に毎週1問ずつ解いてきてAOJ,POJに通すというもの。 最初は何回やってもWA(Wrong Answer:そもそもロジックが間違っている・パターンが網羅されていなかったり)で通らなかったけど、少しずつ通るようになってきたり、 TLE(Time Limited Exceeded:制限時間内に返ってこない)になってなんでだろう!!とか少しずつ悩みの内容が変わっていくのがうれしかった。 CodeFestivalの予選を解いてみたり、などなど新しい世界を同期には教えてもらって結構楽しかった。
AIZU ONLINE JUDGE: Programming Challenge
(おまけ)動画編集
副産物的な話ですが、 1年目で懇親会や忘年会などなどで新人芸をやる機会などが多くて、動画を作る・編集することが多かった・・・。結構楽しくてハマったところもあったので動画編集も新しい世界だったかも。
その他
などなど少し興味の幅も変わってきたり、手を出せる幅も変わったのかなぁと感じています。
1年を総じて感じたこと
時間の使い方が大事
本当に時間がない(というか使い方が下手だとあっという間に過ぎていく)。できる人は家でも努力している。まだまだ時間の使い方が下手だったと思う。 そういうのを感じて「もっと頑張らなきゃ・・・私できてない・・・」と奮起&鬱にもなったり。 飲み会も選んで行くようになった。 以下の記事にはハッとさせられた・・・ life.libinc.jp
深ぼる癖をつける
私がこの世界に入った時は「これは呪文だからそういうものだと思って覚えようね」などと言われたりした。これが染み付いていて、必要になったらその分の知識をつけるという流れになっていた。 普段から調べる・深ぼる癖をつけておかないと、いつまでたっても活躍できるエンジニアにはなれないなと感じた。
指摘されなくても気づける能力がほしい
もはや願望ですが、今年1年は新人だから指摘される機会が多かったのもあって気づいたこともあったと思う。技術力に関してもコードレビューしてもらえないとスキルアップできないとなると困る。 自ら成長するとか簡単にいうけど、そして今まであんまり意識していなかったけど色々方法を模索していかなきゃいけないと感じた。2年目怖い。
最後に
1年間通して「どうしても勝てなさそうな相手」がいるということがわかったり、自分のできなさにかなり悩んだところもあった。「やっぱり私向いてない」とか「無能って思われるの辛い」とか色々感じていたけど、「できないけどこれからどうしていくか」について前向きに捉えられるようになったのはよかったと思う。まだ頑張れる。 書き始めたらどんどん書くことが湧いてきてこんなに長くなったし、それだけ新しい世界には出会っているんだな! 1年後これを振り返って「こんなちょろいことしてたのかーーーーー!」って思えるくらい成長できるといいな。
【Android日誌】2016_02_08週_Collectionとは
Javaでまだまだわかってない部分もあるので、改めて調べる機会などもありました。 今週のアウトプット少ない。
Collectionとは
Collection * List * ArrayList * LinkedList * Vector * * Set * SortedSet * HashSet * TreeSet * * Map * Hashtable * HashMap * TreeMap * SortedMap
LinkedList
LinkedListとArrayListの違い d.hatena.ne.jp
LinkedListの特徴 www.javadrive.jp 特にできることは同じだが、
- 読み出し性能重視はArrayList
- 挿入や削除の性能重視はLinkedList
Set
重複を許さないコレクション。 o1.equals(o2)が成り立つものはaddしてもaddされないし例外も吐かれない。
Set set = new TreeSet<>(); set.add(3); set.add(6); set.add(0); set.add(1); Iterator iterator = set.iterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } //0,1,3,6
独自にcomparator()をセットすれば自分で並び順を変えることができる。デフォルトは要素の自然順序付け
によって行われる。
【Android日誌】2016_02_01週_Invalid Gradle JDK configuration found他
コーディング以外にも調べる機会があったのでアウトプットしていきます。
ディープリンクとは
Topページ以外のページへのリンクのこと。元々はWebサイトについての言葉だが、アプリに対しても使う。 アプリをインストールしているユーザーだった場合は、アプリの該当画面(詳細画面など)に遷移する方法。 インテントフィルターで受け取る方法などの公式。
https://developers.google.com/app-indexing/android/app?hl=jadevelopers.google.com
AppIndex
検索結果画面からアプリに飛ばされるアレ。Rettyとかよく飛ばされるイメージだけど、結構使いづらくてあまり印象よくない。
アンバンドリング
複数機能を持ったアプリを1アプリ1機能に分割すること。最近のトレンドらしい。 facebookのメッセンジャーなどが代表的な例みたい。元々はアプリ都合の部分もあったみたいだが、アプリは何かの目的別のもの、と見ると機能(目的)ごとに分割するのは合理的なのかもしれない。 www.gizmodo.jp newspicks.com
Android Studioの設定ファイルimport
- File>import Settings で設定ファイルを読み込めるし、Export Settingsで吐き出すこともできる
Invalid Gradle JDK configuration found?
- チームで使われていた設定ファイルをimportしてからか?のタイミングでgradleが走らなくなった。
JDK Locationのjdkのverがローカルにあるのがjdk1.8.0_51
だったが、プロジェクトに設定してあるのはjdk1.8.0_31
だった。1.8は一緒だったため、なかなかきづけなかった。
At first update your java. Then check your JDK version. for example: jdk1.8.0_51. Then go to android studio and then go to File ---->Project Structure----> JDK Location (If you install update version of JDK, android studio JDK Location hold older versions jdk url.For example: C:\Program Files\Java\jdk1.8.0_45).
Android Studioのアップデート
Updateする時、こんな警告が出て、Updateできなかった問題が発生。
qiita.com この記事を参考にしていて以下のファイルを触ったことが問題みたい。
/Applications/Android Studio.app/Contents/plugins/android/lib/templates/gradle-projects/NewAndroidProject/root/project_ignore
消すだけじゃダメ、空ファイルでもダメみたい?
結局初期のファイルのままを置いてやるとやっと大丈夫に。
solutionの欄がNONE
がなくなれば、proceedのボタンが出現し、無事updateが進む。
vim系のtips
DDMSとは
- Androidのデバッガツール
- スレッドとかヒープとかは見たことなかったので、確認してみたい techbooster.jpn.org
端末を一意に取得するID
広告配信系のサービスを導入する時に話題に。 リタゲのようなことをして他アプリに広告を配信するには端末を一意に取得していないと出せないよね、と。 どういう値を取得しているんだろう?というお話。
http://iridge.jp/blog/201404/4836/iridge.jp
GSM端末とCDMA端末の違い
IMEI とは
なんとなく、ネットワーク制限などもできるとするとこれを取得するのはかなり強いな、というイメージ。 悪用とかもできちゃう?のかな。個人情報とされるのか、みたいのが問題になる可能性があるみたい。 kaoru0822.seesaa.net
advertisingId とは
名前からもわかるように広告用の匿名性を保った上で端末を一意に判別するIDみたい。 tech.admax.ninja
【Android日誌】2016_01_25週:どこまでnullチェックすればいいのか他
shouldOverrideUrlLoading()はpostだと呼ばれないよ
webViewのページ読み込み時にURLを割り込みできる関数だが、
/** * Give the host application a chance to take over the control when a new * url is about to be loaded in the current WebView. If WebViewClient is not * provided, by default WebView will ask Activity Manager to choose the * proper handler for the url. If WebViewClient is provided, return true * means the host application handles the url, while return false means the * current WebView handles the url. * This method is not called for requests using the POST "method". * * @param view The WebView that is initiating the callback. * @param url The url to be loaded. * @return True if the host application wants to leave the current WebView * and handle the url itself, otherwise return false. */
と書いてある通り、postだとこの関数は呼ばれない。
WebView form - POST をインターセプト-Oboe吹きプログラマの黙示録
じゃあどうするのかと、jsで埋め込んでなんとかする方法がちらほら…。 ここまで対応すべきかどうかどうかは不明。
どこまでnullチェックすればいいのか?
自分の中で、いまいちこのへんの感覚がわからなかったので、調査。
呼んでくるメソッドがnullを返さないことがわかっていれば、もちろんnullチェックをしなくていいけど、
onDestory()
が呼ばれた後に通信のコールバックが返ってくる時とかは、nullになることがあるし…。
アプリを触りながらそういうところをチェックするのではなく、ソースの中でロジックで考えるように心がけようと思った。
webView読み込み途中でのクラッシュ
05:27:57.165 799-14680/? W/ActivityManager﹕ Process jp.co.hoge.hogeapp has crashed too many times: killing! 01-29 05:27:57.165 799-14680/? W/ActivityManager﹕ Force finishing activity hogehoge
webViewにてページの読込中の際に読み込み途中のページのボタンをタップすると落ちることはある。 RuntimeErrorではないからエラーログなどは取れない代わりにこのようなログアリ。
いくつもスレッドが走ることで落ちるものなのかな、と思いつつ根本的な解決が不明。
- 読み込みが終わるまでwebViewをINVISIBLEにしておく
これで対応するしかないのかもしれない…。
Android Javaでフィールドにプレフィックスをつけるのはやめようの理由
今週話題になった記事について結局なんでこんなこと言ってるの?がわからなかった。
- 昔のテキストエディタは精度が悪かったため、今みたいにメンバ変数に色とかつけてくれなかった
- 昔のCの名残りなど
- 今はIDEなどが発達してきて色などをつけてくれるから、プレフィックスが必要なくなったと考える
みたい!