Macbook
Macbook を買うということになって、新製品の発表があって、11インチと13インチで散々迷って、
結局コーディングを本気でするなら13インチのほうがいいだろうというアドバイスに従い、
(Macbook Proにしろという意見もあるだろうけど、重くてイヤなので・・・)
新バージョンの Macbook Air 13インチを注文した!
Air だけど、今の会社で支給されてる Pro よりもメモリもディスクも倍^^
こいつでガッツリとコードを書く人になる!
届くのは来週末らしい。
VAIO P に Linux をインストール
以前やってみてUSBからブートできずに諦めた記憶があるが、
ネットでできてるって記事が多いので、もう一度やってみたところ、できた。
前はなんでできなかったんだろう。
1. Windows領域を縮小する
コントロールパネル → 管理ツール → コンピュータの管理 → 記憶域 → ディスクの管理
右クリック → ボリュームの縮小
参考: Windows7とUbuntu10.04.1 LTSのデュアルブート
2. Ubuntu Lubuntuを用意する
USBからブートできるように、Universal-USB-Installerを使ってISOファイルをUSBに入れた。
Lubuntuは32bit版にしないとダメ。
参考: Vaio P50にUbuntu 12.04 LTSをインストール&サスペンド有効化
3. VAIO P 起動時に F2 を押してBIOS画面を出す
External Device boot を Enable にして、External Device boot を一番上にする。
4. USBを VAIO P に差して起動する
Install Ubuntu を選択すると、なんかエラーが表示されるが、少し待つとインストーラが起動する。
あとはWindowsと共存するように選択して、普通のインストール。
意外にあっさりできたな。
Windowsだと起動後しばらく動きが遅くて使えないのだが、Ubuntuだとマシかな?
んー、そうでもないか・・・
webapp-containe, compiz というプロセスがCPUを食いつぶしている。
ということで、軽量という Lubuntu に入れなおし。
負荷が上がることもなくて快適ではあるが、音がちゃんと鳴ってくれないのがまだ直らない。
小さくて可愛いマシンではあるので、使ってあげたい。
ElasticSearch
MongoDB の全文検索機能が日本語に対応していないということで、ElasticSearchを使ってみた。
例えば東京都って文字があるときに、東京ではヒットしてほしいが京都ではヒットしてほしくないみたいな検索。
ElasticSearch は Java で動いていて、データをインデックス化して保持している。
MongoDB とつなげるためのプラグインを入れて、MongoDB から ElasticSearch にデータを流し込み同期しておく。
バージョンの依存関係が強いので、MongoDB のバージョンに合わせて各モジュールのバージョンを選ぶ。
・MongoDB 2.4.9
・ElasticSearch 1.1.1
・Kuromoji Analysis Plugin 2.1.0
・MongoDB River Plugin 2.0.0
・Attachments Plugin 2.0.0
インストールはpluginというスクリプトが同梱されてるので、楽。
wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.1.1.tar.gz tar xzvf elasticsearch-1.1.1.tar.gz sudo mv Downloads/elasticsearch-1.1.1 /home/mera/ sudo ln -s /home/mera/elasticsearch-1.1.1 /home/mera/elasticsearch cd /home/mera/elasticsearch bin/plugin -install elasticsearch/elasticsearch-analysis-kuromoji/2.1.0 bin/plugin -install elasticsearch/elasticsearch-mapper-attachments/2.0.0 bin/plugin --install com.github.richardwilly98.elasticsearch/elasticsearch-river-mongodb/2.0.0
文章を単語に分けてくれる機能が Kuromoji プラグイン。
これをデフォルトで使ってくれるように、設定ファイル(config/elasticsearch.yml) に以下を追加しておく。
index.analysis.analyzer.default.type: custom index.analysis.analyzer.default.tokenizer: kuromoji_tokenizer
起動するときは、これでアクセスできるようになる。
/home/mera/elasticsearch/bin/elasticsearch -d
アクセスはHTTP経由で行うのが、ちょっと独特でおもしろいけど、RESTか。
ポートはデフォルトで 9200番。
$ curl -XPUT 'http://localhost:9200/test/' {"acknowledged":true}
でデータが格納される場所ができる。
この場合は “test” というデータベース的なものができる。
消すときは、
$ curl -XDELETE 'http://localhost:9200/test' {"acknowledged":true}
で、データは MongoDB から吸い上げたい。
そのためのプラグインが elasticsearch-river-mongodb
同期用の設定もPUTで書き込む。
こんな感じで、MongoDB にある “test” データベースを丸ごと、ElasticSearch の “test” に同期する。
$ curl -XPUT "localhost:9200/_river/test/_meta" -d ' { "type": "mongodb", "mongodb": { "db": "test", "servers": [ { "host": "127.0.0.1", "port": 27101 } ], "options": { "secondary_read_preference": true, "import_all_collections": true } }, "index": { "name": "test" } }'
シャットダウンするときは、プロセスをKillするんじゃなくて、POSTで指令。
$ curl -XPOST 'http://localhost:9200/_shutdown'
データを検索するときは、
$ curl -XGET "http://localhost:9200/test/_search"
とか、
curl -XGET 'http://localhost:9200/test/questions/_search?pretty=true' -d ' { "query" : { "simple_query_string" : { "fields": ["question_title"], "query": "難問 山", "default_operator": "and" } } }'
とか、いろいろ検索文は作れる。
どう組み立てていいかよくわからないときは、
bin/plugin -install mobz/elasticsearch-head
でプラグインを入れておくと、http://localhost:9200/_plugin/head/ でデータベースの中身が見れたり、
検索用のJSONクエリを「選択してボタン」って感じで作ることができたりして、わかりやすい。
SIMロック解除
先日会社帰りにdocomoショップに寄ったが、2時間待ちで断念。
今日別のdocomoショップに行ったが同じく1.5~2時間待ち。
番号札だけもらって、買い物に出て、1時間半前に戻った。
まだ自分の前の番号が掲示されていたが、すぐに呼んでもらえた。
端末の確認と本人確認をして、軽く説明を受けて、
解除用のSIMを挿して何やら操作して、あっさり解除完了。
3240円を支払って、おしまい。
家に帰ってから、OCNのSIMを挿してみて、使えた。
そういやOCNのは元々docomo回線だから、解除前も確認しておくべきだったか。
Nexus 7は4Gで使えるけど、Garaxy S2は3G。
だったら、Xperia E1と同じか。
動作が軽くなることを期待して、Garaxy S2 は初期状態にリセットしてみた。
いずれにせよ、データ通信は Nexus 7 をメインで使うので、
Garaxy S2 と Xperia E2 は電話番号だけちゃんと入ってればいい。
まぁこれでSIMフリー端末が3台になった。
Skype 通話
先月電話する用事があり、電話代がかなり高かったので、調べてみた。
タイプシンプル バリュー 30秒20円
Skype to 固定電話 1分2.6円
ネットがなければ使えないにしても、ネットがある環境ではこっちのほうが断然お得。
ちなみに先月のケースではネットがなかったので、ちょっと仕方ない点もあるのだけど。
早速使ってみたけど、普通に電話できた。
いいねー。
mochijson2
Erlang で JSON からデータを取り出したくて、mochijson2 に辿り着いた。
https://github.com/bjnortier/mochijson2
やりたかったことは、Google Geocoding APIを使って、住所から座標を取り出すこと。
説明に書いてあるとおり、
http://maps.googleapis.com/maps/api/geocode/json?address=東京都新宿区
のように検索すると、結果が JSON 形式で返ってくる。
{ "results" : [ { "address_components" : [ { "long_name" : "新宿区", "short_name" : "新宿区", "types" : [ "locality", "political" ] }, { "long_name" : "東京都", "short_name" : "東京都", "types" : [ "administrative_area_level_1", "political" ] }, { "long_name" : "日本", "short_name" : "JP", "types" : [ "country", "political" ] } ], "formatted_address" : "日本, 東京都新宿区", "geometry" : { "bounds" : { "northeast" : { "lat" : 35.7298939, "lng" : 139.7451615 }, "southwest" : { "lat" : 35.6731516, "lng" : 139.6732487 } }, "location" : { "lat" : 35.6938401, "lng" : 139.7035494 }, "location_type" : "APPROXIMATE", "viewport" : { "northeast" : { "lat" : 35.7298939, "lng" : 139.7451615 }, "southwest" : { "lat" : 35.6731516, "lng" : 139.6732487 } } }, "types" : [ "locality", "political" ] } ], "status" : "OK" }
この結果が 下記コードの Body に入っている。
構造としては、
1. results の中の配列の一番目の塊の中
2. geometry というキーのバリューの中
3. location というキーのバリューの中
4. lat, lng というキーの値がそれぞれ緯度経度
これを順に辿っていくことになる。
Decoded = mochijson2:decode(Body), {struct, Results} = Decoded, Results2 = proplists:get_value(< <"results">>, Results), [H, T] = Results2, {struct, Items} = H, Geo = proplists:get_value(< <"geometry">>, Items), {struct, Locs} = Geo, Loc = proplists:get_value(< <"location">>, Locs), {struct, Latng} = Loc, Lat = proplists:get_value(< <"lat">>, Latng), Lng = proplists:get_value(< <"lng">>, Latng),
ポイントとしては、
・mochijson2:decode から値を取り出すと {struct, 本体} という形なので、本体のほうを分解していく
・キーの名前を指定するときは、バイナリ形式で < <"キー">> という形で書く
・配列の先頭を取り出すときに [H, T] という形に代入すると H が先頭(Head)
といったところだったかな。
参考になったサイトは、
Destructuring JSON in Erlang Made Easy
である。
最初にコマンドラインでちゃんと分解してみてから、アプリのコードに組み込むべし。
このあと住所の投げ方によって返ってくる形が違うことがわかり、If文とかを追加してちょっと複雑になった。
そんなこんな、誰が使うんだろうね・・・
Erlang が流行ってるのかどうか、全然知らない。
Erlang
技術的に使わなければならない明確な理由は見えていないけど、仕事で使い始めた。
Erlang というプログラミング言語。
並列処理に強いらしい。
・行の区切りは , (カンマ)
・節の区切りは ; (セミコロン)
・命令の終わりは . (ドット)
という直感的ではない言語なので、まだ好きになれない。
例えば、こんな感じになるのだが、end. の前が ; で終わらないのがなんかイヤ。
logout('GET', []) -> Response = api:logout(boss_session:get_session_data(BossSessionID, sessionID)), case Response of ok -> boss_session:delete_session(BossSessionID), {redirect, "login"}; {error, Reason} -> {ok, {error, Reason}} end.
他にも、
・変数は大文字で始まる
・変数は再代入できない
・関数の最後にアクセスした値がそのままreturnされる
・コメントアウトは % (パーセント)
・文字列の連結は ++ (プラス2つ)
・改行文字が ~n などニョロ
という書き方上の違和感はたくさんある。
いちばん大きい特徴は、値をバイナリに変換してから変数に渡さないといけないことかもしれない。
例えば、日本語を扱うとき、
unicode:characters_to_binary(FirstName)
のように一度バイナリに変換しないとエラーになる。
バイナリの値は
< < >>
で囲まれて表現されるらしい。
まだ少ししか書いてないけど、やっぱりまだ慣れてない。
PowerMockito
昨日の Mockito の続きとして、今度は PowerMockito.
https://code.google.com/p/powermock/
PowerMock という名前が正しいのかな?
PowerMock + Mockito = PowerMockito ということでいっか。
このページがだいぶ役に立った。
How to use PowerMock and Mockito to test static and private methods
昨日の Mockito と同じ例を使う。
内部でしか呼んでいない getHttpClient() を private メソッドに変えたことが、昨日と違うところ。
例えば、TestTarget というクラスがあるとする。
getData() が内部で HttpClient を使って通信して、その結果を返すとする。
ここで HttpClient をモックにしたいので、getHttpClient() というメソッドを作り、その動作を置き換える。
@RunWith(PowerMockRunner.class) @PrepareForTest(TestTarget.class) public Class TestTarget { public TestTarget(String arg1, String arg2) { } public String getData() { HttpClient httpClient = getHttpClient(); HttpResponse response = httpClient.execute(... String result = ... return result; } private HttpClient getHttpClient() { return HttpClients.createDefault(); } }
0. Class に Annotation として @RunWith, @PrepareForTest をつける。
1. PowerMockito.spy にテスト対象のクラスを渡して、メソッドを差し替える準備をする。
TestTarget instance = PowerMockito.spy(new TestTarget("TEST_VALUE1","TEST_VALUE2"));
2. doReturn と when で何をしたら何を返すかを書く。
getHttpClient() を呼んだら、モックである httpClientMock を返すようにする。
ここも Mockito とは違うところで、when と thenReturn だとうまくいかない。
HttpClient httpClientMock = Mockito.mock(HttpClient.class); PowerMockito.doReturn(httpClientMock).when(instance, "getHttpClient");
3. 置き換え後のインスタンスでテストをする。
Assert.assertNotNull(instance.getData());
4. HttpClient の代わりに HttpClientMock が呼ばれる。
こんな感じで使う。
モックに差し替えるためだけに Getter を用意した。
それだけの変更で済んだので個人的にはよし。
当然このようなメソッドは private であるべきなので、PowerMockito を使った。
だけど、どうやらこのやり方はCoolじゃないらしいとTwitterでコメントくれた人がいた。
その人がどこかにまとめると言っていたので、もしそれを読む機会があったら書き足すつもり。
Mockito
ユニットテストを書くときに、HttpClient など通信をするモジュールを使ってると、
実際に通信が始まっちゃうと困ることが多々ある。
その通信部分をモックに置き換えて、テスト用の出力を返してもらうだけにする。
JUnit を使っているのだが、どうやってモックに置き換えるかが問題。
実際に使ったのは PowerMockito だけど、まずはその元となっている Mockito から紹介。
https://code.google.com/p/mockito/
モックを生成するのは、単純に Mockito.mock を呼べばいい。
指定したクラスのインスタンスを作ってくれるので、テスト対象のクラスに投げるのに使える。
例えば、HttpResponse のインスタンスが欲しいなーと思っても、
new して作ると、引数が必要だったり、その引数を用意するために別のインスタンスが必要だったりする。
それが1行書くだけでいいので、実際のインスタンス生成のメンドクサさはなくなる。
HttpResponse httpResponseMock = Mockito.mock(HttpResponse.class);
ただ、モックもちゃんと動作をしてもらわないとテストに使えないので、必要なメソッドだけ動作を定義する。
例えば、そのモックの getStatusLine() を呼んだら statusLineMock を返すようにする。
その statusLineMock もモックで作っておき、getStatusCode() が呼ばれたら SC_OK を返す、など。
StatusLine statusLineMock = Mockito.mock(StatusLine.class); Mockito.when(statusLineMock.getStatusCode()).thenReturn(HttpStatus.SC_OK); Mockito.when(httpResponseMock.getStatusLine()).thenReturn(statusLineMock);
この Mockito.mock だとインスタンスを丸ごとがモックになる。
本物のインスタンスの動きをして欲しい部分があるときには逆にメンドクサイ。
そういうときに使うのが、Mockito.spy というもの。
テスト対象のクラスはモックにするわけにはいかず、実際の動作をしてくれないとテストの意味が無い。
そこで、どうしてもモックにしたいメソッドだけを指定する。
・Mockito.mock は全体をモックにしてからメソッドを置き換えて動作を定義していく
・Mockito.spy は本物をベースにしてメソッドを一部モックにする
例えば、TestTarget というクラスがあるとする。
getData() が内部で HttpClient を使って通信して、その結果を返すとする。
ここで HttpClient をモックにしたいので、getHttpClient() というメソッドを作り、その動作を置き換える。
public Class TestTarget { public TestTarget(String arg1, String arg2) { } public String getData() { HttpClient httpClient = getHttpClient(); HttpResponse response = httpClient.execute(... String result = ... return result; } public HttpClient getHttpClient() { return HttpClients.createDefault(); } }
1. Mockito.spy にテスト対象のクラスを渡して、メソッドを差し替える準備をする。
TestTarget instance = Mockito.spy(new TestTarget("TEST_VALUE1","TEST_VALUE2"));
2. when と thenReturn で何をしたら何を返すかを書く。
getHttpClient() を呼んだら、モックである httpClientMock を返すようにする。
Mockito だと差し替え対象のメソッド getHttpClient() は public じゃないといけないという制約がある。
HttpClient httpClientMock = Mockito.mock(HttpClient.class); Mockito.when(instance.getHttpClient()).thenReturn(httpClientMock);
3. 置き換え後のインスタンスでテストをする。
Assert.assertNotNull(instance.getData());
4. HttpClient の代わりに HttpClientMock が呼ばれる。
こんな感じで使う。
ポイントは 2. の箇所で、public メソッドじゃないとダメなところ。
この部分を private メソッドでもOKにしたのが、PowerMockito なのである。
つづく
Viber動作確認
手元に2台あるので試してみた。
こちら側=Android, 相手側=iPhone での実験。
こちらが送信したら、ステータスが「送信済み」になる
相手の端末が受信したら、ステータスが「配信済み」になる
相手がメッセージを開いたら、「読んだ」というコメントがメッセージの下に付記される
相手側の端末で電話番号を消されていたら、メッセージを送ることはできるが、名前じゃなく電話番号で届く
相手側の端末でアカウントを非アクティブにしたら、配信時にエラーになり、SMSで送信するか聞かれる
でもアカウントの状態は「オンライン」のままだった
相手側の端末でViberを非アクティブにせずにアンインストールしたときの試し忘れた