ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

Docker 入門 #1 — Windows に Boot2Docker をインストールして既存イメージを扱ってみる

Docker 使えるようにならないとなー、ということで、まずは Docker を使える環境を準備して、ユーザーガイドをちょっと読んでみた。 既存イメージを使ってコンテナの生成をするなどの操作をするところまで。 完全なる入門者向け (あるいは自分用) だけどメモしておく。

Docker のバージョンは 1.1.2 を使用した。

Docker についての参考文献

そもそもの Docker についての説明はこのエントリでは行わない。 次の記事が参考になる。

Windows での Docker 環境の構築

Windows ユーザーでない場合はそれぞれの環境用のインストールガイドを参照のこと。

Docker Engine は Linux カーネルの機能を使用しているので、Windows の上に直接 Docker 環境を構築することはできない。 VirtualBox なりなんなりで仮想マシンとして Linux マシンを Windows 上に起動する必要がある。

Boot2Docker というアプリケーションが Docker より提供されているので、(Docker Engine 用の仮想マシンを立てるつもりなら) これを使うのが便利である。 Boot2Docker を使うことで、VirtualBox 上に Docker 環境用の仮想マシンをインストールし、Docker デーモンを走らせることができる。

Boot2Docker のインストールで VirtualBox もインストールできるようなので、まだ VirtualBox をインストールしていない人でもいきなり Boot2Docker をインストールして良い。 次のエントリも参考になる。

使い方

「Boot2Docker Start」 というのがスタート画面のアプリケーション一覧に追加されているはずなので、これをクリックする。 すると、VirtualBox に Docker 用の仮想マシンが登録されて、Linux のインストールなどが実行される。 そして仮想マシンが起動して、そこに SSH 接続される。

この仮想マシン上で docker コマンドを使い、Docker コンテナを作ったりする。

また、インストール時にパスを通すかどうかのオプションを選択できるが、パスを通しておけば boot2docker コマンドが使えるようになる。「Boot2Docker Start」 を使わなくても、PowerShell を開いて boot2docker コマンドを使うことで、仮想マシンの操作ができる。

他のコマンドは boot2docker --help で調べられる。

Docker を使ってみる

ユーザーガイドに従って Docker を使ってみる。 これ以降は、基本的に boot2docker ssh して、仮想マシン上でコマンドを実行するものとする。

ユーザーガイドとは別にオンラインチュートリアルもあって、こっちの方が最初は良いかもしれない。

アプリケーションの Docker 化 (?)

docker run コマンド
$ sudo docker run ubuntu:14.04 /bin/echo 'Hello world'
Hello world

上のようなコマンドを実行すると、何やらダウンロードしてきて、最終的に 「Hello world」 が出力される。 何をしているかというと、「ubuntu:14.04」 というイメージからコンテナを新たに生成し、そのコンテナ上で 「/bin/echo 'Hello world'」 というコマンドを実行している。

指定されたイメージは、まず Docker ホスト上で探される。 そこで見つからなければ、Docker Hub 上で探される。 今回の場合、「ubuntu:14.04」 というイメージは Docker Hub からダウンロードされる。

新たに生成されたコンテナは、指定のコマンドを実行し終えると停止 (?) するようである。 (コンテナ自体は残っている。 後で出てくるが、docker ps コマンドに -a オプションを渡すと、停止しているコンテナも表示される。)

-t オプション *1-i オプション *2 を渡すことで、対話型コンテナを立ち上げることもできる。

-d オプションでコンテナのデーモン化ができる。 docker run -d ... コマンドを実行すると、長い文字列が表示される。 これはコンテナ ID である。 コンテナの名前は (明示的に指定しなければ) 自動的につけられる。

docker ps コマンド

docker ps コマンドで、実行中のコンテナの情報が表示される。 コンテナ ID やコンテナ名などが確認できる。

上で書いたように、-a オプションを付ければ停止中のコンテナも表示される。

docker logs コマンド

docker logs {container} コマンドを使えば、コンテナ内部の標準出力を表示できる。 {container} としては、コンテナ ID とコンテナ名のどちらかを指定できるっぽい。

docker stop コマンド

docker stop {container} コマンドを使えば、動いているコンテナを止めることができる。

コンテナの扱い方

バージョン確認

docker version コマンドで、Docker クライアントと Docker サーバーのバージョン情報が表示される。 Go のバージョンや Git コミットのリビジョンも表示される。

Docker クライアントのコマンド一覧

オプションなしの docker コマンドで、docker コマンドが受け付けるアクション一覧が表示される。 各アクションについては、docker {action} --help コマンドでヘルプを表示できる。

コマンド一覧については Web 上のヘルプを参照してもよい。

Web アプリケーションを Docker 内で動かす
$ sudo docker run -d -P training/webapp python app.py

上記コマンドで、トレーニング用の web アプリケーションを Docker 内で動かすことができる。 「training/webapp」 というイメージは Docker Hub からダウンロードされる。

-P オプションは、コンテナ内部で必要なネットワークポート (exposed port) をホストのそれにマップするように Docker に伝えるためのものである。 上のコマンドを実行した後、docker ps -l コマンド *3 を実行すると、PORTS の項に以下のような表示が出るはずである。

PORTS
0.0.0.0:49155->5000/tcp

ローカル Docker ホストの 49155 ポートが、コンテナの 5000 ポートにマップされていることがわかる。 コンテナ側のどのポートを露出させるかを指定する方法は、後で (イメージ作成方法のところ) で説明される。 ホスト側のポートは 49000 から 49900 の間 (high port と表現されている) から自動的に選ばれる。

-P オプションの代わりに、docker run コマンドに -p {container_port} オプションを渡すことで、コンテナの指定のポートをホスト側の high port にマップすることもできる。 -P オプションは、コンテナの exposed port をホストの high port にマップするものであるが、-p オプションはコンテナ側の指定のポートが exposed port かどうかは関係ないようである。

また、-p {host_port}:{container_port} という形式で、コンテナの指定のポートを、ホストの指定のポートにマップすることもできる。

ちなみに、Windows 上で Boot2Docker を使っている場合は、WindowsPowerShell 上で boot2docker ip コマンドを実行することで、Docker ホストの IP アドレスを取得できる。

docker port コマンド

docker port {container} {private_port} コマンドで、指定のコンテナの指定のポートがどのポートにマッピングされているかを知ることができる。

Web アプリケーションのログ表示

docker logs コマンドの -f オプションは、tail コマンドの -f オプションのようなものである。

コンテナのプロセス

docker top {container} コマンドで、指定のコンテナのプロセス一覧を見ることができる。

コンテナの詳細

docker inspect {container} コマンドで、指定のコンテナの詳細情報を JSON 形式で得ることができる。

さらに、-f オプションを使うことで、特定の情報のみを取りだすこともできる。

$ sudo docker inspect -f '{{ .NetworkSettings.IPAddress }}' nostalgic_morse
172.17.0.5
コンテナの再起動

停止されたコンテナは、docker start {container} コマンドで再度起動できる。 実行中のコンテナの再起動は docker restart {container} コマンド。

そういえばコンテナが停止される際に、コンテナ内のプロセスがどうなるのか、とか、再起動時にはどうなるのか、とかわかってない。

コンテナの削除

停止されたコンテナは docker rm {container} コマンドで削除できる。

そういえば同僚が 「要らなくなったコンテナのごみ掃除が大変だ!」 とか言ってたけど、これのことなのかなー。

今回はここまで

既存のイメージを使うところまではこんな感じ。 さらにイメージをビルドしたりする話が続くけど、それはまた別のエントリに。

*1:新しいコンテナ内に pseudo-tty または terminal を割り当てる。

*2:コンテナの標準入力に引っ掛けることで対話型のコネクションを張る。

*3:「-l」 オプションは、最後に開始されたコンテナの情報を表示するためのオプション。

読んだ: アジャイル開発とスクラム 顧客・技術・経営をつなぐ協調的ソフトウェア開発マネジメント

開発手法としてスクラムを取り入れているチームに所属しているが、アジャイルスクラムといった手法についてあまり知識を持っていないソフトウェアエンジニア、という立場で本書を読んだ。 本書のカバー袖には 『企業の経営層に向けてソフトウェア開発手法の 「アジャイル」 とその手法の一つである 「スクラム」 を体系的に解説する』 とあるのだが、経営層に限らず、アジャイル的な開発手法を採用して開発プロセスを改善していこうとする人であれば、誰にとっても有益だと思う。

アジャイル開発については、ウォーターフォールとの比較として 「小さなサイクルを回して変化に柔軟に対応しながら開発を進める」 という程度の理解しかなかったので、本書を読んで 「人が知識を運ぶ」 とか 「人と人のコミュニケーションで知識を伝える」、「顧客と協調して開発を進める」 といった、どちらかというと社会的な活動やその意義についての部分が非常に参考になった。

アジャイル開発とスクラム 顧客・技術・経営をつなぐ協調的ソフトウェア開発マネジメント

アジャイル開発とスクラム 顧客・技術・経営をつなぐ協調的ソフトウェア開発マネジメント

本書は 3 部構成になっている。 第 1 部 「アジャイル開発とは何か、スクラムとは何か」 では、ソフトウェア開発手法であるアジャイル開発について、どういうものなのか、なぜそれが必要とされたのか、といったことが説明される。 そして、アジャイル開発の枠組として、スクラムについても詳しく説明される。

アジャイル開発については、「ウォーターフォールのように要件定義や設計、実装という各作業で開発プロセスを分断するのではなく、小さなサイクルを回して完成を目指す」 (すなわち、包括的なドキュメントより動くソフトウェアを重視し、計画に従うだけでなく変化に柔軟に対応していくことを重視する) というものだと思っていたのだけれど、それだけでなく、「個人と対話」 や 「顧客との協調」 といったことにも価値を置く価値観が根底にある、ということを知れたのが良かった。 この価値観は、「アジャイル宣言」 に述べられている。

また、朝会 (デイリースクラム) やプランニングポーカー、アジャイル開発の各種プラクティスについても説明される。 プラクティスとしてはアジャイルの右翼 (開発環境) に属するものと左翼 (チーム環境) に属するものがあり、それらをうまく組み合わせてアジャイル開発の目的である 「ビジネス価値」、「顧客満足」、「市場創造」 といったことを達成する。 ここら辺のプラクティスについては、軽く紹介されるだけという感じなので、実際に現場で実践するのであれば詳細は別の書籍などで学ぶと良いと思う。 次のようなスライドもある。

2 部では、実際にアジャイル開発を導入した国内の 3 社 (リクルート楽天富士通) の事例が紹介される。

3 部では、現在のアジャイル開発では明示的に言及されないような、企業経営とリーダーシップの側面から、アジャイル開発の考察がなされる。

個人的に気になった内容

アジャイルの各種プラクティス

プランニングポーカーは 1 回やったことがあるけど、ちゃんとしたやり方を知らなかったので 「なるほどー」 という感じで読んだ。 他のプラクティスについては大体知ってたけれど、いくつか新しい発見があった。

  • プランニングポーカー
    • 最初にベースラインを決める。 メンバー全員が知っているあまり大きくないタスクを選ぶ。 → こないだプランニングポーカーやったとき、最初のタスクは適当に数字を出してて 「こんなんでいいのかなー」 と思ったりしてた。
    • 見解は一番大きい数字と小さい数字の人が言う。 → 数字が合わなかったら全員が言うものだと思ってたけど、確かにそれだと時間かかりすぎるし、最大と最小の人が言えば良さそう。
    • 3 回で切り上げ。 → まあそんなものか。
  • 朝会でプロジェクトの外部の人の発言するタイミングを制限する。 → 外部の人が、自分がリスクを取るわけでもないのに気軽に口出しする、というのを防ぐ意味。
    • プロジェクト内の人をブタ、外部の人をニワトリと呼ぶことがある話。 ハムエッグを作るのにブタは自分を生命をかけるが、ニワトリは自身の生命に関わらない貢献の仕方をする。
    • ブタとニワトリの話、会社の人もしてた。
  • タスクかんばんのタスクは 2、3 時間程度で終わる粒度が良い。
    • 今のプロジェクトでもタスク粒度には悩んでる。
    • タスクが動くことで進捗状況の共有。 さらに達成感にもつながる。 1 日で動くようなタスク粒度にすべきとのこと。
  • バーンダウンチャート
    • 進捗状況の確認のための質問は 「完了までにあと何ポイント (理想時間) 必要か」 にする。 「何パーセント完了したか」 や 「残り何パーセントか」 ではない。
    • 作業が進むにつれて、見積もりよりも実際に必要な作業が多いことがわかったりするので、残り作業時間を把握すべき。
  • スプリントで完了できたポイント数をベロシティとして、スプリントあたりに進めることができるタスク量の目安とする。
    • 工数をポイントで見積もった場合に、実時間とどう変換するのがいいんだろうなーと思っていたけれど、実時間と変換するよりはスプリントあたりに進めることができるポイント数を把握してれば良い、という感じか。
  • スプリントの成果物はリリース判断可能なもの。
  • ユーザーストーリーには詳細な仕様は書かない。
    • あえてコミュニケーションを発生させる意図がある。
    • これに限らず、アジャイル開発では文書などで伝えられる 「形式知」 だけでなく、「暗黙知」 というところにも焦点を当てている。 人と人とのかかわりで伝えられる知識。
  • ペアプログラミング
    • 15 分おきにぐらいでペアを交代する。 開発のメリハリやリズム。 → 15 分がいいのかどうかわからないけど、まあそれぐらいかなーという気はする。
    • リスクが大きい作業や、クリエイティブな作業はペアで行った方が効率的。 → 設計とかも、設計をきっちり書いてレビューしてもらって大きな直しが発生する、というような状況になるぐらいなら最初からペアでやった方が良さそう。

事例

各社、それぞれ課題があったり良い取り組むをしていたりして興味深い。 他社がやってるからといって表面的に真似ても意味はないけど、どういう考えで各取り組みをしたのかが書かれているので、そこら辺がだいぶ参考になる。

リクルート
  • バーンダウンチャートに上限線を引く。
    • 予めバッファを持たせて、上限線を引いておく。 実績線が上限線を超えそうになったら要件の調整を行う。
    • 上限線を引いておくことで、要件の調整に対して事業部側の理解を得やすい。
  • 出世魚型のドキュメント。
    • ドキュメントは開発フェーズをまたいで使いまわし、更新していく。
    • ドキュメント作成の工数削減と、ドキュメントが分散して齟齬が発生することを防ぐ。
    • 言葉で聞いたら、さもありなん、という気はするけど、実際のところドキュメントどうするかって結構難しい問題ではある。
  • 最初はワンチームマインドの醸成に苦戦した。
    • 見積もりのずれに対する認識。 事業部側は見積もりは初期から変わらないという認識。
    • 意識の変革と共有。 地道な啓蒙や説得。
  • 会議からの持ち帰りの禁止。
    • 「持ち帰って検討」 が開発スピードを遅らせる。
    • 持ち帰って 100 % の精度で回答するのではなく、80 % の精度でいいのでその場で回答する。
    • 残り 20 % に起因する手戻りが発生しても、お互いに怒らないように。
    • 精度を求めすぎて時間がかかる、というのは避けるように自分も意識してはいるけど、それでも時間をかけて検討することは結構多いので、もうちょっとスピード重視に振ってもいいかもなーとか思ったり。
楽天
  • 割り込み作業が多いという問題。
    • スクラムマスター経由で依頼してもらうようにして、優先度などをスクラムマスターが調整。
    • こういうのはスクラムマスターの仕事として重要なものの一つなのだなー、と今のプロジェクトでも感じてる。
  • 新撰組の旗を立ててチームの共通認識にする。 目に見える形になっていることの重要性。
    • 「俺たち新撰組みたいだよな」 というような話をチームでしていて、そこから旗を立てたらしい。
    • こういう、チームの結束を高めるための取り組みの事例はいろいろ聞くけど、じゃあ自分のところは何かできるか、っていうと難しいよね。 旗立てればいいってものでもないし。
  • 横やり作業もタスク化する。
    • 必ずしもそれがいいかどうかはわからないけど、自分が何しているのか共有するためにプロジェクト外のことをタスクかんばんに乗せるのは一つの手ではあるなー。
富士通
  • チーム内は完全ペア作業。 教育効果。
    • 人数が多く人の出入りも激しいので、教育効果の高いことをする必要がある、という感じみたい。
    • ある程度少人数で固定のメンバーでやるなら、いい感じのところでペア作業すれば良さそう。
  • チーム間の Try 共有。
    • 振り返りで出てきた Try をチーム間で共有することで、チームとしての成長を共有する。
    • こういう取り組みはいいなーと思った。
  • 文書で伝えたつもりが伝わってないということもある。 文書ではなく人が情報を運ぶという意識。
    • 後でも出てくるけど、こういう 「暗黙知」 も重視する姿勢がアジャイルっぽい感じだなーと思った。

アジャイル開発とスクラム

アジャイル開発で重要そうなトピック。

  • 多層学習と多能力学習。
    • 個人、チーム、部、会社、という様々な層で学習が起こる。
    • チーム内にエンジニアやデザイナ、営業、といった様々な専門スキルを持つ人間がいるので、自分の専門外のことも学習する。
  • 暗黙知形式知、両方の形式が重要。
    • SECI モデル。 暗黙知形式知にする (文書化) ことで複数形式知をまとめたりできるし、さらにそうしてできた形式知暗黙知として人が取り込む、みたいな感じのモデル。
    • 自転車に乗る乗り方、みたいな体でわかることが暗黙知
    • 暗黙知は人と人が直接やり取りすることで伝えられる。 アジャイル開発ではこういう人と人のやり取りが重要視されていると感じる。
  • 実践知リーダー。
  • PDCA (計画、実行、検査、適応) サイクルの前に共同化。
    • 計画は形式知からくるもの。 イノベーションにはもっと主観的な動機が伴っているはず。 それを共同化 (チームメンバーとの共有) する。
    • 何を作るか、ではなく、なぜ作るか、という思い。
    • 合宿の意義もここにある。

アジャイル開発とスクラム 顧客・技術・経営をつなぐ協調的ソフトウェア開発マネジメント

アジャイル開発とスクラム 顧客・技術・経営をつなぐ協調的ソフトウェア開発マネジメント

Annotations Support Library が Android Studio 0.5.5 でサポートされた

Annotations Support Library の概要

ちゃんとしたドキュメントが見当たらないのですが、 *1 Android Support library のリビジョン 19.1.0 から、新たに Annotations Support Library が追加されました。 このライブラリは、その名のとおり Android アプリ開発時に用いることができるアノテーションの集まりです。 例えば、@NonNull@Nullable といったアノテーションが含まれています。

さらに、Android Studio ではバージョン 0.5.5 からこれらのアノテーションをサポートしており、アノテーションを使うことでいろいろと警告を出してくれるようになっています。

Support for the new annotations which shipped with the most recent version of the support library, such as @NonNull and @Nullable, as well as annotations to declare resource types and valid constants. Add a dependency on com.android.support:support-annotations:+ to use these in your projects. In the upcoming 0.10.x version of the Android Gradle plugin, the plugin will extract these annotations into your libraries' AAR files such that clients of your library can get the same resource type checks as is shown above for the SDK APIs.

Android Studio 0.5.5 Released - Android Tools Project Site

Android Support library については前に記事を書きましたので、合わせて参照ください。

Support Annotation についての公式的なドキュメントは次のページをご覧ください。

Annotations Support Library の使い方

ビルドシステムに Gradle を使っている場合についての説明です。

Android SDK Manager で 「Android Support Repository」 (リビジョン 5 以上) をインストールしたうえで、build.gradle に次のように記述することで Annotations Support Library を使用できます。

dependencies {
    compile 'com.android.support:support-annotations:22.2.0' // バージョン番号は必要に応じて変更してください。
}

使用できるアノテーション紹介

どういうアノテーションがあるのかを紹介します。 バージョン 19.1.0 時点での情報ですので、新しいバージョンでは使用できるアノテーションが増えているかもしれません。

@NonNull@Nullable

これらは、メソッドの返り値が null になりうるかどうかや、メソッドのパラメータとして null を許容するかどうか、といったことを表すのに用いられます。

    private void displayName(@NonNull String name) {
        // ...
    }

例えば、引数として null を許容しないメソッドを定義する場合、上のように @NonNull アノテーションを用いて null を許容しないことを表現できます。

そして、そのように定義されたメソッドの呼び出し時に null を引数として渡すようなコードを書くと、Android Studio 上で次のように警告が表示されます。

f:id:nobuoka:20140510013210p:plain

私は null になりうる変数には xxxOrNull みたいな名前を付けるといった命名規則などで null 周りのバグを減らすように気を付けたりしているのですが、アノテーションIDE によるサポートがあると便利で良さそうですね。

どの種類のリソースを参照するための int 値なのかを示すアノテーション

Android アプリで使用する各種リソースは int 値で参照されます。 どの種類のリソースでも同じ int 型で表されるので、Drawable のリソース ID を受け取るメソッドに、Drawable 以外のリソースの ID を渡すといったことや、そもそもリソースの ID でない単なる数値を渡すといったことも (コード上は) 可能です。

Annotations Support Library には、どの種類のリソースの ID なのかを示すためのアノテーションも含まれています。 例えば、Drawable リソースであることを示すアノテーション@DrawableRes アノテーション です。

    private void receiveDrawableRes(@DrawableRes int resId) {
        // ...
    }

例えば、引数として Drawable リソースの ID を受け取るメソッドを定義する場合、上のように @DrawableRes アノテーションを付けて、引数が Drawable リソースの ID であることを示せます。

このメソッドに Drawable 以外のリソースの ID を渡すと、次のように Android Studio がエラー表示してくれます。

f:id:nobuoka:20140510014441p:plain

@DrawableRes アノテーションの他にも、@AnimRes@ColorRes@StringRes といった、各種リソースに対応したアノテーションが存在します。

@IntDef@StringDef

定数として定義したいくつかの int 型 (あるいは String 型) の値のうちのいずれかを引数として受け取るメソッドを書きたい、ということがままあります。 そんなときに便利なのがこれらのアノテーションです。

普通にメソッドを定義すると、任意の int 値を受け取れるようになってしまいますが、これらのアノテーションを用いて独自のアノテーションを定義することで、メソッドが指定の定数のみを受け取ることを示すことができます。

@IntDef アノテーションを用いて、独自のアノテーション (@NavigationMode アノテーション) を定義する例は次のような感じです。

    @IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
    public @interface NavigationMode {}
    public static final int NAVIGATION_MODE_STANDARD = 0;
    public static final int NAVIGATION_MODE_LIST = 1;
    public static final int NAVIGATION_MODE_TABS = 2;

そして、上で定義されたアノテーションを使い、NAVIGATION_MODE_STANDARDNAVIGATION_MODE_LISTNAVIGATION_MODE_TABS のいずれかの値を受け取るメソッドであることを次のように示せます。

    private void navigate(@NavigationMode int navMode) {
        // ...
    }

呼び出し時には定数を使って値を指定しないと、次のようにエラーが表示されます。

f:id:nobuoka:20140510021304p:plain

まとめ

Android Support library のリビジョン 19.1.0 で Annotations Support Library が追加され、Android Studio 0.5.5 でそれらのアノテーションがサポートされました。

著しく開発効率が上がったり、本質的な機能の向上があるわけではなく、あくまで開発の補助に使用できるものではありますが、地味に便利だと思います。 せっかく Android Studio でこのようなアノテーションがサポートされたのですから使っていきましょう!

Effective Android

Effective Android

  • 作者: TechBooster,小太刀御禄,出村成和,重田大助,西岡靖代,宮川大輔,柏本和俊,あんざいゆき,八木俊広,木村尭海,小林慎治,有山圭二,中西良明,わかめまさひろ,新井祐一,桝井草介,久郷達也,寺園聖文,shige0501,山下智樹,前田章博,秋葉ちひろ,末広尚義,中澤慧,日高正博,塚田翔也,井形圭介,中川幸哉,山崎誠,山下武志,なまそで,橋爪香織,さとうかずのり,l_b__,ゼロハチネット,長汐祐哉
  • 出版社/メーカー: インプレスジャパン
  • 発売日: 2014/01/17
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログ (8件) を見る

変更履歴

  • 2015-06-13 : 「support-annotations ライブラリ」 と記述していたのを 「Annotations Support Library」 に変更。

*1:最近公式的なドキュメントも書かれました。

Jenkins 上で Android アプリのテストを実行する方法 (Gradle 使用)

最近 Jenkins 上で Android アプリのテストを実行できるようにしたので軽くメモしておきます。

Jenkins実践入門 ?ビルド・テスト・デプロイを自動化する技術 (WEB+DB PRESS plus)

Jenkins実践入門 ?ビルド・テスト・デプロイを自動化する技術 (WEB+DB PRESS plus)

更新履歴

  • 2014-03-25: Android Gradle plugin 0.9.0 でテストのタスク名が変更されたことに合わせて内容を変更しました。

前提

Gradle ラッパーは別にリポジトリに入れてなくてもいいですが、入れておくとシェルスクリプトでテストを実行できるので便利です。

手元でのテスト実行

Jenkins 上でテストする前に、まず手元でテストを実行できるようにしておく必要があります。 *1

./gradlew connectedAndroidTest

# 注意: Android Gradle plugin 0.9.0 よりも古いバージョンを使っている場合は次のコマンドです
./gradlew connectedInstrumentTest

上記コマンドによりテストが実行されるようにしておいてください。 接続されている Android 端末 (エミュレータも可) を使ってテストが実行されます。

Android SDK のサンプルの中にテストのプロジェクトがあるので、それも参考になります。

Jenkins 上でのテスト実行

Jenkins 上で Android アプリのテストを実行するには、次が必要となります。

  • Jenkins 上でのテスト実行時に Android エミュレータが起動するようにする
  • テスト実行 (ビルド) に必要な Android SDK を Jenkins 上にインストール

Android エミュレータの起動には、Jenkins のプラグイン Android Emulator Plugin を使用します。 また、このプラグインAndroid SDK のインストールも行いますので、ビルドの際にはその SDK を使用するようにしておくと良いでしょう。

Android Emulator Plugin のインストール

Jenkins で Android Emulator Plugin をインストールするのは簡単で、「Jenkin の管理」 ページから 「プラグインの管理」 ページに行き、「利用可能」 タブで 「Android Emulator Plugin」 を選択してインストールするだけです *2

テスト実行のために必要な設定

テスト実行用のジョブを作ったら、ジョブの設定で以下のことを行います。

  • Jenkins のジョブ実行時に Android エミュレータを起動するようにする (「Run an Android emulator during build」 の設定項目)
    • 「高度な設定」 を開いて 「Show emulator window」 のチェックを外すこと
  • ビルド手順として 「シェルの実行」 を追加し、中身を 「./gradlew connectedAndroidTest」 とする *3
  • ビルド後の処理として 「JUnit テスト結果の集計」 を追加し、パスとして 「**/build/androidTest-results/connected/*.xml」 と入力する *4

多分これだけでテストが実行されると思います。 環境変数 ANDROID_HOME には Android Emulator Plugin が使用する Android SDK のパスが設定されているらしいので、自分で ANDROID_HOME などの設定をする必要はないはずです。

Android SDK build-tool のインストールが必要な場合

ただし、ビルドに使用する Android SDK build-tool のバージョンがインストールされていない場合は次のようなエラーが発生してしまうので、Android Emulator Plugin によってインストールされた Android SDK のディレクトリに行って、Android SDK build-tool をインストールする必要があるかもしれません。 (/var/lib/jenkins/tools/android-sdk/tools/android update sdk -u -a -t platform-tool,tool みたいなコマンド *5 ですかね。) *6

FAILURE: Build failed with an exception.


* What went wrong:
Execution failed for task ':modules:volley:compileReleaseAidl'.
> failed to find Build Tools revision 19.0.3

【追記】 上のようなエラーの場合は、/var/lib/jenkins/tools/android-sdk/tools/android update sdk -u -a -t build-tools-19.0.3 というコマンドでビルドツールをインストールすれば良さそうです。 (参考: Android-Jenkins: failed to find Build Tools revision 17.0.0 On Jenkins Build Server - Stack Overflow)

Windows でのはまりどころ

Windows 上に Jenkins をインストールして使っている場合、Jenkins はローカルシステムアカウントで動いていると思います。 しかし、この状態では Android SDKJava SDK を見つけるのに失敗するなどの問題があります。

ビルドします。 ワークスペース: C:\Program Files (x86)\Jenkins\jobs\build-android-app\workspace
$ C:/Users/nobuoka/AppData/Local/Android/android-studio/sdk/tools/android.bat list target
'C:\Windows\system32\java.exe' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
無効なパスの指定です
指定されたパスが見つかりません。
指定されたパスが見つかりません。
指定されたパスが見つかりません。

そのため、Windows 上の Jenkins で Android アプリのテストを実行する場合は、実際のユーザーアカウントで Jenkins を動かす必要があります。 Windows 8 では、タスクマネージャの 「サービス」 タブの項目一覧の適当な場所を右クリックして 「サービス管理ツールを開く」 を選んでサービス管理ツールを開き、Jenkins のサービスのプロパティを開いて 「ログオン」 タブで通常ユーザーのアカウントを入力します。 これで Jenkins サービスを再起動したらうまくいくはずです。

*1:Android アプリのテストについてはそのうち別エントリで書こうと思いますが、ここでは詳しくは説明しません。

*2:多分 Jenkins の再起動が必要です。

*3:Android Gradle plugin 0.9.0 よりも古いバージョンを使用する場合は 「./gradlew connectedInstrumentTest」 です

*4:Android Gradle plugin 0.9.0 よりも古いバージョンを使用する場合は 「**/build/instrumentTest-results/connected/*.xml」 です

*5:Linux におけるデフォルトのディレクトリ配置の場合?

*6:ここら辺あんまりわかってないので違うかもしれません。

rbenv で管理されている ruby でコマンド付きの gem をインストールしたら rbenv rehash しよう

これまでは Ruby のバージョン管理には RVM を使っていたのですが、rbenv が良いという話を結構前から聞いていたので rbenv を使い始めてみました。

インストール方法などは基本的に上記 GitHub リポジトリの README に書いてあります。

で、普通に ruby コマンドを使ったり gem コマンドを使ったりできていたのですが、コマンド付きの gem (bundle コマンドが使えるようになる bundler とか) をインストールしたところ、使えるはずのコマンドが使えなくて困ってしまいました。

$ gem install bundler
Fetching: bundler-1.3.5.gem (100%)
Successfully installed bundler-1.3.5
Parsing documentation for bundler-1.3.5
Installing ri documentation for bundler-1.3.5
1 gem installed

$ bundle
bash: bundle: コマンドが見つかりません

それについても rbenv のリポジトリの README に書いてありました。

rbenv rehash

Installs shims for all Ruby executables known to rbenv (i.e., ~/.rbenv/versions/*/bin/*). Run this command after you install a new version of Ruby, or install a gem that provides commands.

$ rbenv rehash

コマンド付きの gem をインストールしたときなどは rbenv rehash が必要みたいですね。