やらなイカ?

たぶん、iOS/Androidアプリの開発・テスト関係。

testotips.io(Appium回)に行ってきました #testotipsio

クックパッド株式会社さんで開催された、testotips.io 第1回*1に行ってきました。

connpass.com

testotips.ioは、iOS/Androidの開発系Tips共有会として続けられているpotatotipsのテスト版を指向していて、s.io==塩味*2という意味がある(かもしれない)とのこと。

今回のお題はAppium。スライドは追々connpassに張られていくと思うので、以下メモのみ。

Introduce Appium(松尾さん)

  • Appiumはnodeベースのツールで、iOS/Androidのネイティブアプリおよびブラウザの操作を自動化、GUIテストができる
  • GUIのテストについて。E2E test、Feature testなどと呼ばれているもの。テストケースの量は、Unit test > Integration test > GUI Test
  • 内容はappium.jsを追っていけばだいたいわかる
  • Capabilities*3でAppiumサーバの振る舞いを指定する
    • platform: ios, android, selendroid, chrome, safari, firefoxos
    • iOS: calendarFormat, sendKeyStrategyとかも指定できる
    • Android: unicodeKeyboard(マルチバイト文字を使う場合)
  • Tips
    • Appium 1.3.6では、iOSのplistがバイナリだと文字化けしていた。1.3.7betaで修正
    • Viewの取得、XPathだけでなく、UI Automation(iOS)/uiautomator(Android)の書式でも取得可能
    • Appiumサーバは複数実行できる(listen portを分ける)。ただしiOSはひとつしか実行できない
  • 実行には時間がかかるので、夜間にまわして翌朝チェックしている
  • DroidDriver

テスト結果レポートをSahaginで作ってみる(伊藤さん)

  • Sahagin==さはぎん。伊藤さんが作った
  • 今のところJavaのみ対応。もともとSelenium WebDriverのテスト結果のレポーターで、Appiumでも使用できる
  • テストコードから、日本語+画面キャプチャのレポートをhtmlで出力
    • スクショはステップごとに自動で撮ってくれる
    • findとかasertも日本語に置き換えて出力している
  • PageObjectパターンを使う場合、setterに@TestDocでコメントを書くとそれが表示に使用される
  • Jenkins Sahagin pluginで、Jenkinsのジョブ画面に表示できる
  • Selendroidだとスクショのタイミングがちょっとずれる
  • Tips
    • Jenkinsで実行するとき、テストの前後にAppiumサーバの起動と停止をすると安定する
    • Android emulatorのブラウザでスクショが取れない(Chrom Driverの問題?)
    • Xcode 6.2ではiOSシミュレータのSafariが使えない
    • Appiumのキャプチャが遅い
    • Appiumサーバはrootで起動できないので注意

AppiumのPHPクライアントを使う上で行っている工夫(高橋さん)

  • Yahoo!社内でPHPクライアントを使った自動化の試み
  • JavaScriptはコールバックが多くて嫌だった。社内のサーバサイドで多く使われていたPHPを選択。でも他のクライアントライブラリに比べて機能が足りない
  • テストフレームワークにはPHPUnit
  • Appium PHP Clientを継承したHelperクラスを作り、それを継承した個々のTestCase作成。Helperには足りない機能を書いている
  • コンストラクタでsessionStrategy=isolatedにされていたので、テストケースごとにアプリインストールが走っていた
  • sleepを極力しない工夫。findをラッピングして、例外を返さず、waitしてリトライすることをHelperに実装。テストコードをシンプルに保つ
  • swipeが座標指定なのをラッピング
  • UI操作のスモークテストにAppiumを使用。細かい操作のテストにはEspressoを使用している

Appiumを使ってiPhone Safari、Andorid Chromiumを使ってアプリをテストするTips(浅黄さん)

  • ブラウザのテストにAppiumを使用している
  • Androidは、SelendroidだとWebViewで実行されるので、最近はChromeDriverで直接Chromeを使用するようにしている
  • Selenium Grid Serverを使って実行。ただし、Appiumはキックできるけど、ChromeDriverはキックできないのでGrid Severを経由していない。
  • テストケースは、Excelの表形式で書いたものからJavaのコードを生成する。共通処理(ログイン等)、シナリオ、PageObject、それぞれExcelファイルで書ける

Running appium tests on Jenkins(Vishal Banthiaさん)

  • AppiumによるiOS/AndroidテストをJenkinsから実行するデモ
  • テストはRSpecで、失敗したらスクショを撮っている
  • buildとtestはジョブをわけて、pipelineでつなぐ
  • テストは機能ごとにジョブを分けている(これは増えていくとつらいと思うので私は否定派)
  • デモのリポジトリにはHeplerも入っている
    • servermanager.rb: Appiumサーバの管理。startで、前のプロセスをkillしたりとか。
    • screenshot_embedded_html_formatter.rb: スクリーンショット

所感

懇親会も込みで、他の会社で実際どのように運用しているとか、という話が聞けるのはとても有益でした。Tips紹介だけだとこれは得られないので、テスト自動化まわりはこんな感じに(ツール縛りくらいで)情報交換できる場はいいですね。

*1:とは言っていませでしたが続くといいですね!

*2:プロレスファンとしては「しょっぱい」に余り良いイメージを持てませんが、それはそれ。これはこれ。

*3:Capability==ケーパビリティ。Capacityはキャパシティなのに!

モバイル向けテスト手法勉強会に行ってきました #33testing

先週、クラウド名刺管理のSansan株式会社さんで開催された『最新事例から学ぶ!モバイル向けテスト手法勉強会』に参加させていただき、また「テストの種類とBDD」と題してお話してきました。

テストの種類とBDD

どうしても前提となる話が増えてしまってテスト実装の話まで入れられませんでした。このプレゼンがつまらなくても、テストのことは嫌いにならないでください。

後半は、BDDか、テクニック的な話(テストダブル、テストファースト、TDDとか)にするか迷ったのですが、今回の感触だとテクニックの話のほうがよかったかも知れません。しかし元々20分ギリギリ話すつもり&電エースの話をしすぎた結果、BDDの部分は全部飛ばすはめになった今となってはどちらでもよかったですね。

テストのテクニックに関しては、拙著『iOSアプリテスト自動化入門』の2.3、2.4に書いてありますので、そちらを参照頂けましたら幸いです。

なお、BDDのところで紹介しているテスト自動化ツールの連載は、昨日第6回が公開されました。

ほかの方々の講演

聴講メモが混ざってしまっていたので、以下まとめて全体の話として書きます。

テストを書いてるひとはまだ少ない
  • UIのテストを過剰に自動化しようとする(そして挫折する)よりはいいと思います
  • 岸川さんの話にあったように、モデル(MVCのM)を中心に、ユニットテストは自動化していったほうがいいでしょう
    • ただし、「6〜7割実装してからテストを書きはじめる」のはテストを書いたことが無い人が真似しようとしても難しいです。テストしやすい実装になっていないと、テストを後から書くのは困難なので。
  • ユニットテストのメリット、運用(岸川さん)
    • 変更を入れる際の安心感
    • テストはgreenな状態を維持する
    • カバレジはあまり気にしすぎない。テストを書くモチベーションになるなら使う
      • ユビレジさんの場合、サーバサイドで80%、クライアントは全体で15%、ViewControllerを抜いて25%くらい
ビルド、AdHoc配布までの自動化は進んでいる
  • テストはまだなくても、CIサービスを使ってビルド、AdHocでテスター向け配布までは自動化している
  • ブランチモデルにgit-flowを使い、developにマージされるごとにビルド・AdHoc配布
    • スプリントのQA期間など、5〜10/day以上になり、ビルド待ちが発生することも多い
  • CIサービスとしては、Circle CIが多く、次いでTravis CI
    • Circle CIはタスクの並列化が難しいので、例えばテスト実行と平行してAdHoc配布を行なうといったことはTravis CIのほうが向いている
    • Greenhouse CIは、スクリプトを書かずにできる範囲が広く、ほぼスクリプトレスで構築できる。ただし高度なことを行なうには壁がある
    • Jenkinsでもいいけれど、プラグインに頼りすぎずRakefileMakefileに書くように(岸川さん)
    • Rakefileが巨大になったので、XCJobsを作った(岸川さん)
  • AdHoc配布は、Fabric.ioが多い
    • 最近までTestFlightを使い、Fabric.ioの"Beta by Crashlytics"に乗り換えた
      • TestFlightはiOS8以上なのがネック
    • Crashlytics(クラッシュログ解析)を利用していたのでそのまま
    • iOS/Androidで同じサービスのほうが、テストする人はありがたい
    • 弊社はTestFlightがAndroidを切ったタイミングでDeployGateに移ったのですが、もう少し様子見。
  • 自動化にはfastlaneが便利
    • ビルド、テスト実行(xctool)、署名、AdHoc配布などのコマンドは、fastlaneを使うと便利
    • KrauseFx/fastlane · GitHub
  • チャットでコントロール
    • Hubotに"release"を指示すると、リリースブランチを切り、PR、Travisでビルド、配布が流れる
    • チャットにログが残るので、可視化、かつ、作業単位での分担・引き継ぎが容易
Xcodeプロジェクト
  • プロジェクトをcheckoutしたらすぐビルドできるように。プロジェクト固有ルールでの初期設定はなくす。CocoaPodsのようなデファクトを積極的に使う
  • Target、Configurationがたくさんあるとどれを使うべきかわからない。Schemeもたくさんあるとわからない。
  • 依存ライブラリのコードをプロジェクトに混ぜない。CocoaPodsを使えばlockファイルで差分もわかる
    • なお、"混ぜない"は、プロジェクト内で修正を入れたりしないことが重要で、Podsから取得したコードをバージョン管理に含める運用の是非ではないです。
Android
  • Google Playの段階的リリースを使用している
  • 引き継いだ時点でテストコードなし
  • Robotiumを使用
    • リリースビルドをテストできないので、Appiumを検討中
    • まずスモークテスト
    • solo.getView()などをラップして、スクリーンショットを撮るようにする
    • 極力sleep()は使わず、waitForXxxx()を使う
    • ローカライズを意識して文字列はハードコーディングでなく文字列リソースを使う

所感

  • 過剰にUIのテストをしよう!みたいな雰囲気でなくて良かった
  • ビルド・配布から自動化に手を付けるというのは、良い傾向
  • とは言え、あとからテストを書くのは困難なことが多いです。CIを導入しているなら、サイクロマティック複雑度を計測して酷いものからリファクタリングしていくアプローチもあり。『iOSアプリテスト自動化入門』の8.2あたりが参考になるはず

Realm(realm-cocoa)を使うアプリをテストする #realm_jp

iOS/Android向けDBMS+ORMのRealmを利用しているアプリのテストコードの書きかた、またテストコードからIn Memory Storeで使用する方法を試してみました。

realm-cocoa のバージョンは 0.90.6 を使用しています。

テストターゲットの準備

Realmをプロジェクトに取り込む方法はいくつかありますが、今回はCocoaPodsを利用しました。このとき、下記のようにテストターゲット側にもRealm/Headersの利用を宣言する必要があります。

target 'RealmInMemoryStoreExampleTests', exclusive: true do
  pod 'Realm/Headers'
end

テスト用のRealmインスタンスを使用する

Realmのサンプルコードにあるように[RLMRealm defaultRealm]でデフォルトRealmインスタンス*1を使用すると、テストコードからの実行でもテスト対象アプリの利用するDBを使ってしまうため、これに干渉してしまいます。

また、[RMLObject allObjects]といったRealmオブジェクトを指定しないメソッドは総じて、デフォルトRealmインスタンスを使用します。

これを避け、テストコードからはデフォルトとは異なるDBを利用する方法は二通りあります。

方法1: setDefaultRealmPathでデフォルトを置き換える

プロダクトコード(テスト対象アプリ)側で[RLMRealm defaultRealm][RMLObject allObjects]などを直接利用している場合、テストコード側であらかじめ+[RLMRealm setDefaultRealmPath:]を呼ぶことで、以降のデフォルトRealmを置き換えることができます。

通常は[setUp]を下記のようにすれば良いでしょう。

- (void)setUp {
    [super setUp];

    //default realmをテスト専用のものに置き換える(テスト対象アプリのrealmファイルに干渉させないため)
    NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    NSString *realmPath = [docPath stringByAppendingPathComponent:@"test.realm"];
    [RLMRealm setDefaultRealmPath:realmPath];

    //内容をクリア
    RLMRealm *realm = [RLMRealm defaultRealm];
    [realm beginWriteTransaction];
    [realm deleteAllObjects];
    [realm commitWriteTransaction];
}

これで、以降個々のテストメソッドでは全てのオブジェクトがクリアされたクリーンなtest.realmに対して読み書きを行なうことができます。

なお、DBのクリアは意味的には「後処理」ですが、テストがエラーで落ちる等の要因で実行されないと次(次回)のテストが失敗してしまうこともあります。安定したテスト実行のために[tearDown]でなく「前処理」である[setUp]でクリアを行なっています。

方法2: テスト対象メソッドでRealmインスタンスを受け取る

メソッドの引数、もしくはRealmを扱うクラスのインスタンスフィールドにRealmインスタンスを保持し、これをテストコードから書き換え可能にしておきます。

Realmインスタンスは、デフォルトでなく[RLMRealm realmWithPath:]でファイルパスを指定して初期化できます。 プロダクトコードでは[RLMRealm defaultRealm]を利用し、テストコードからは[RLMRealm realmWithPath:]でファイル名を指定することで専用のRealmインスタンスを使用できます。

プロダクトコード

+ (Employee *)addEmployeeWithName:(NSString *)name salary:(float)salary realm:(RLMRealm *)realm{
    Employee *newEmployee = [[Employee alloc] init];
    newEmployee.name = name;
    newEmployee.salary = salary;
    newEmployee.addDate = [NSDate date];

    //引数で受け取ったRLMRealmインスタンスを使用する
    [realm beginWriteTransaction];
    [realm addObject:newEmployee];
    [realm commitWriteTransaction];

    return newEmployee;
}

テストコード

- (void)testAddEmployee {
    NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    NSString *realmPath = [docPath stringByAppendingPathComponent:@"test.realm"];
    RLMRealm *realm = [RLMRealm realmWithPath:realmPath];

    //テスト用のRLMRealmインスタンスを渡す
    [EmployeeManager addEmployeeWithName:@"John Cena" salary:2000000 realm:realm];
}

テストデータをファイルで用意して使用する

大量のデータや複雑なクエリをテストするためのデータのinsertは、テストコードで行なうよりも、あらかじめRealmのファイル形式で準備するほうが管理しやすいケースもあるでしょう。*2

これは、上記いずれかの方法でRealmファイルパスを指定してRealmインスタンスを得る場合、あらかじめ用意したRealmファイルをアプリのDocuments下に置き、そのパスを[setDefaultRealmPath:][realmWithPath:]に渡すことで実現できます。

テスト実行環境のファイルの扱いについては、拙著『iOSアプリ テスト自動化入門』の「2.4.1 テストフィクスチャをファイルでバンドルする」「2.4.3 アプリケーションデータを再現してテスト実行する」が参考になるはずです。

In Memory Storeで使用する

Realmは、ファイルでなくメモリ上だけで動作させることもできます。インメモリでの動作は、ファイルI/Oが無いぶん高速、かつ、実行ごとにクリーンな状態のRealmインスタンスを得られるため、テストコードから使うには最適です。

インメモリで動作するRealmインスタンスは、[RLMRealm inMemoryRealmWithIdentifier:]で生成できます。 こちらはデフォルトを置き換えるクラスメソッドは存在しないため、プロダクトコード側が上記「テスト対象メソッドでRealmインスタンスを受け取る」にあるようなRealmインスタンスを差し替え可能な構造である必要があります。

テストコード

- (void)testAddEmployee {
    //インメモリで動作するRealmインスタンスを生成
    RLMRealm *realm = [RLMRealm inMemoryRealmWithIdentifier:@"test"];

    //テスト用のRLMRealmインスタンスを渡す
    [EmployeeManager addEmployeeWithName:@"John Cena" salary:2000000 realm:realm];
}

余り性能は出ないという話でしたが、小さなオブジェクトを1,000件insertする*3テストでは、

  • ファイル : 0.820[sec]
  • インメモリ : 0.189[sec]

となり、1/4程度には抑えられるようです。

サンプルコード

GitHubに置いてあります。

参考資料

Realmのドキュメント

書籍

iOSアプリ テスト自動化入門

iOSアプリ テスト自動化入門

*1:実体はアプリのDocumentsディレクトリ下にdefault.realmというファイル

*2:例えば、RealmファイルはiOS/Androidで同一なので、両プラットフォーム対応の場合には共通化もできます

*3:1レコードごとに毎回commitしています

Realm Tech Talk with JP Simard 1 に行ってきました #realm_jp

iOS/Androidで使用できるDBMS(+ORM)であるRealmのイベント、Realm Tech Talk with JP Simard #1(於 freee株式会社さん)に行ってきました。

Tech Talk with JP Simard from Realm

Realmのメンバー、JP SimardさんによるRealmの紹介。

Realmの特徴

  • オープンソース(ASL 2.0)である。なお、現時点でDBのCore部分はまだクローズドだが、オープンにする方向で進めている。
  • iOS/Androidで同じように使用できる。リリースタイミングのずれはあるが*1、双方、同じ機能を提供する。

既存DBMS(およびORM)との比較

  • iOSのCore DataはSQLiteのORM(Object Relational Mapper)で、古く、遅い。学習コストも高い。
  • SQLiteは早いが、ORMでなくSQLクエリで操作する必要がある。スレッドセーフでない。
  • ほか、FMDB(SQLiteのラッパー)などもあるが、総じて遅い。またAndroid向けには選択肢が少ない。
  • ベンチマーク
    • 単純なinsertは、生のSQLiteが早い(178k件/sec)が、Realmはそれに次ぐ(94k件/sec)。FMDB(47k件/sec)、Core Data(18k件/sec)
    • レコード数カウントは、Realm(30.9回/sec)、SQLite(13.6回/sec)、Core Data(1.0回/sec)。なお、数値はDBに200kレコード入っている状態のクエリ実行回数
    • 抽出クエリは、Realm(31回/sec)、SQLite(14回/sec)、Core Data(2回/sec)

モデルの定義

RLMObjectを継承したValue Objectを定義する。

@interface Employee : RLMObject
@property NSString *name;
@property float salary;
@end

RLM_ARRAY_TYPE(Employee)

@interface Company : RLMObject
@property NSString *name;
@property RLMArray<Employee> *employees
@end

これで、Employeeテーブルと、Employeeの配列(内部的にはrelation)を持ったCompanyテーブルができる。Swiftではデフォルト値の定義も可能。 (コードはその場でメモした擬似コードなので注意)

使いかた

Add(insert)はこんな感じで可能。

let employees = List<Employee>()
let company = Company()

Realm.write{     //transaction
    defaultRealm.add(company);
}

GCDから使う場合

dispatch_async(queue){
    realm.beginTransaction()
    ...
    realm.commitWriteTransaction()
}

(※コードはイメージです)

抽出クエリは、#filter()をチェインしていく形式で記述。

マルチスレッドでRealmを使っても、ちゃんと捌いてくれる。ただし、クエリで取り出したインスタンスはそのスレッドでしか使用できない。別スレッドでは再取得する必要があるので注意。

Notifications

例えばinsertされたタイミングで指定メソッドの呼び出しを登録できる。何がinsertされたかは(今は)わからない。

注意点

  • NSDataは、秒単位までしか保持されない。これはAndroidとの整合性のため。ミリ秒以上の精度はNSTimeintervalを使う。
  • KVOは未サポート

Work In Progress

  • multi process
  • fine-grain notifications(Notificationで操作されたオブジェクトも通知できる)
  • async queries
  • cascading deletes(リレーションのレコードを連鎖で削除する)
  • nullable types(現状はNullを入れられない)
  • sync
  • open source core

質疑応答

理解できたものだけ。

  • Realmのファイルは、iOS/Androidで共通フォーマットなのでファイルコピーで共有できる
  • desktop appで、Realm Browserというのがある。CUIツールは無い
  • coreは、TightDB(旧社名?)
  • in memoryで利用するには、begin transactionのとき指定できる
  • arrayのcountをクエリで取ることはできない(カウントを格納するプロパティを設けるなどのwork around)

realm-javaを使ってみての発表

Chatwork 宮下さんの発表。ChatworkのAndroid版で実際に使用したお話。

Android のORMはそもそも選択肢が少ない。

  • greenDAO: 早いけど準備が面倒
  • ActiveAndroid: insertが遅い(Chatworkさんの事例での話で、大量にinsertが発生すると厳しい)
    • Benchmark: 619件の処理(insert?)で、ActiveAndroidでは1551ms、Realmは414ms。

realm-javaでのモデル定義例

class xxx extends RealmObject{
    @primaryKey private long id;
}
  • RealmObjectはvalue objectでなくてはならず、ロジックは持てない。toString(), equals()とかもオーバーライドできない。
  • Realmのobjectは、スレッド単位でしか利用できない。別スレッドで扱うならqueryしなおす
  • 日本語ドキュメントのバージョンは0.72、最新は0.79.1。かなり変更があるので、最新情報にあたるほうがいい。
  • ButterKnifeと干渉するところがあったが、Gradleの定義で回避できた

所感

iOS/Androidで共用できるシリアライズ機構としては、Dropboxが公開しているmx3も気になっているのですが、こちらはライブラリでなく実装サンプルであり、ORMも含めて考えるとRealmの有望さを感じました。

モデルがvalue objectに限定されることは不便に思いますが、ロジック付きのラッパーを作ればいいので致命的ではなさそう。

最近、DBMSを使う系のアプリを作っていないのですが、止まっている電エースアプリAndroid版ででも使ってみたい。

懇親会では、freeeさんの会社およびプロダクト*2の話をたくさん聞けて、それもまた色々参考になりました。

freeeさん、岸川さん、通訳を買って出てくださった北さん、そしてJPさん、ありがとうございました。

*1:iOSがやや先行するみたい

*2:クラウド会計をユーザとして使いたいと思っていたので

#ABC2014W におけるOculus Rift体験展示のノウハウ #JAGVR

東海大学 高輪キャンパスで行われた、日本Androidの会のイベント「ABC 2014 Winter」においてVR部として一部屋いただき、Oculus RiftなどによるVRコンテンツの展示、またタオバイザー(Cardboard互換HMD)向けアプリ作成のハンズオンを行ないました。

私はほぼ展示に張り付いていたので、そこで得られた知見・改善点などを書き留めておきます。

なお、セッティング等どうしても汎用的な方向に振るしかなく、当日余り良いVR体験を得られなかった方もいらっしゃったはず。お詫びするとともに、できればこれに懲りず、よりご自身に合ったセッティングで体験いただける機会にリベンジしていただけましたら幸いです。

f:id:nowsprinting:20141221100418j:plain

Oculus Rift DK2

Oculus Riftは、Oculus VR社が販売しているHMD(Head Mount Display)です。現在、DK2(Development Kit 2/開発キット)をOculus VR社のWebサイトから購入(個人輸入)することができます。

今回VR部ではこれを2台(2コンテンツ)用意し、VR(Virtual Reality)体験してもらうという展示でした。

セッティングのポイントは以下3点。

  • レンズはA(通常・遠視向け)固定。ある程度の近視の方には裸眼、それで無理そうな方にはメガネ着用で体験していただきました*1。ここは妥協。
  • レンズ距離は一番近くに設定。私としては少しだけ離すのがベストなのですが、今回は両手が空くコンテンツですし、見づらい方には手で保持して顔から離して調整してもらうことに。
  • IPD(瞳孔間距離)は、今回は5.5cmとしました。IPDについての詳細、決め方など『Oculus Riftでオレの嫁と会える本』Chapter 8-1を参考にしました。

VRコンテンツ作成の入門書的な本ですが、VR酔いへの対応策なども丁寧に書かれています。ぜひ手元に置いておくべき一冊。

PC

880M SLI搭載のゲーミングノートを使用しました。OSはWindows 7。ノートのメリットは本体の可搬性と、説明員が状況を確認するためのモニタがあること。展示に使用するのでなければタワー型のほうがコスパいいです。

おすすめ設定は下記を参照。

コンテンツ

展示したコンテンツは、@youten_redoさんチョイスの以下ふたつ。

UnityCoaster2 UrbanCoaster

iWorks(@x68user)氏によるジェットコースターの定番。Oculus SDK 0.4.4対応のV1.1を使用。

Unity-Chan "Candy Rock Star" Live Demo

ユニティ・テクノロジーズ・ジャパン制作の「ユニティちゃん」ライブのOculus Rift対応版。GitHubリポジトリoculusブランチのものからOculus SDK 0.4.4に入れ替えたもの。

展示向けコンテンツの要件

必須要件としては3点。

  • 適度な長さ(この点、ユニティちゃんライブはショートに変えたほうがよかったかも)
  • VR酔いしにくい品質(75fps出ること)
  • 一回再生するごとに停止し、何らかのアクションで次の再生がはじまる(体験者が入れ替わるため)

さらに、3DVR体験としてのわかりやすさから、あったほうがいい特徴3点。

  • カメラに向かってキャラクターが接近する(3Dっぽさの体感)
  • まわりを見渡せる(ヘッドトラッキング
  • 近づいたり、覗きこんだり、VR世界内のキャラクターがこちらを見る(ポジショントラッキング

今回は借り物のアプリですが、展示を回す中で「あったほうが良い」と感じたことがいくつかありました。今後、自作する際には入れていきたいのが以下。

  • Rキーでポジションのリセット。これはOculus SDKのCameraには入っているのですが、Cardboard向けアプリでも何らかのジェスチャーでリセットできるような仕掛けは考慮したほうがよさそう
  • 再生を中断して、アイドル状態に戻る機能*2。これが欲しい理由は以下2つ。
    • 体験者が途中でHMDを外して離脱してしまうことが何度かあった
    • 体験者がいないとき、PCのモニタで再生しておきたい。それを、体験者が来たときに中断したい。

その他、準備したもの

ヘッドホン

没入感を増すため、周囲の雑音を考慮するとあったほうがいいです。より没入感が欲しいコンテンツ(今回のユニティちゃんライブや、Mikulusなど)はノイズキャンセリングが望ましいかも。

ただしノイズキャンセリングの場合、説明員の声が聞こえなくなるデメリットがあります。必要なアナウンスをコンテンツ側に作りこむ、オペレーションを徹底するなどの考慮は必要でしょう。

ウェットティッシュ

HMDのスポンジ部分を拭くために用意しました。余り活用できてなかったので、スポンジ保護シートなどと組み合わせることを考えたほうがいいかも。

フライヤー

これは用意してなかったのですが、どういったコンテンツか、体験時間は何分か、といった情報は紙で掲示しておくとよかったかも。

また、待ち行列ができるのであれば、HMDの調整の仕方なども事前に読んで待っていただけるとよりスムーズになるでしょう。

オペレーション

呼び込み

Ocufesなどとは異なり、「Androidのイベントに来て、講演の合間にうろうろしたらVR部屋があった」というものなので、積極的に並んでまで体験しよう、という方は少なかったです。 従って、遠目に、興味ありそうに見てる人がいたら呼び込んで被らせる形。

皆さん講演の合間に展示を回っている状況なので、待ち時間、終了時間が見える形でないと並んで待ってまで体験するには至らない、と途中で気付きました。今後似たようなケースであれば改善していきたい。

お子様が来られたとき、明らかに13歳未満でしたので泣いて馬謖を斬る思いでお断りしました。この辺りの根拠についてはこちらにまとめられています。ちゃんと断る覚悟を持つために読んでおいたほうがいいです。

セットアップ

体験者に座っていただいてから、スタートまでに気をつけたこと。

  • まず、正しく座ってもらう。荷物のために斜めに座ったりしてしまう方もいたので、極力まっすぐ座ってもらう。バックパックなどはそれほど問題ないと思ったので背負ったままで。
  • メガネの方、外してもある程度は見えるのかを聞く。
    • ある程度見えるのであれば、裸眼でHMDを被ってもらう
    • かなり悪いならば、一旦外してもらってHMDといっしよにかぶってもらう
  • HMDを被せる。ほとんどそのまま被ってもらってしまいましたが、メガネの方とか女性とか、もっと後ろのマジックテープ着脱を活用すればよかった
  • 目とレンズの位置がずれているとボヤけて見えるので、表示されている文字がくっきり見えているか確認。スループットが落ちてでもここはちゃんと調整してもらうほうがいいはず。
    • 「上下左右に動かしてはっきり見える位置」「もしくは顔から少し離してみる」という説明がうまく伝わらないこともあって、表現は検討・改善していきたい。
  • HMDを装着した状態でリラックスした姿勢を取ってもらい、そこでキーボードのRを押してポジションリセット。

スタート

  • コースターは、"Look Here"の文字を凝視するとスタートします。ちゃんと見るべき位置を言ってあげて、細かく観測補正(ちょい右、ちょい下、とか)してあげれば、問題なくスタートできていました(逆にサポートなしだと厳しいと思う)。
  • コースターが動き出してから、「ヘッドホン被せます」と宣言しつつヘッドホンを被せる。相手は視界を奪われているので、かならず宣言してから。
  • まだスピードが遅いうちに、まわりを見渡せることを伝えました。UnityCoaster2 v1.1では左に女の子が座っているので、それを見てもらうのがインパクトありました。
    • 伝えるタイミングはスタート前でもいいかも知れません
    • ノイズキャンセリングヘッドホンを使う場合は、スタート前に。

ゴール

  • ゴールの建物に入ったあたりでヘッドホンを外してあげます
    • このときも、先に「ヘッドホン外します」と宣言してから
    • 早めに外すのは、自分でHMDを先に外そうとする傾向があるため
  • ほとんどの方はHMDは自分で外してもらっていましたが、後ろのマジックテープを外してあげてもよかったかも
  • 何か言わないと気まずい、なんと言っていいかわからない、という人もいそうなので、とりあえず「酔いとかないですか?」とか先に聞いてみるなどしました

その後

  • ほぼ並んでいない状態ですが、「空いたらやってみたい」くらいの人はいるので、できるだけ早めに椅子から立ってもらったほうがいいです。
  • 座ったまま質問などはじめる方もいるので、できれば次の方をスタートさせるまで先にオペレーションする間、待っていただくよう上手く言えるとベスト。難しいですが。
  • 無理にHUDを外そうとした際にレンズ距離が動いてしまったことがあったので、定位置にあるかチェックする

所感

こういった形でOculus Riftの体験展示を行なうのははじめてだったので、オペレーションは一日かけて体験者の方を観察しながら改善していった感じです。

重ねて書きますが、当日余り良いVR体験を得られなかった方もいらっしゃると思います。申し訳ありませんでした。Oculusは、VR技術は悪くないので、ぜひぜひこれに懲りずにリベンジしていただけることを切に願います。

今回、展示は自作でなく借りもののコンテンツだったのですが、それでも体験された方のリアクションを見ているのはとてもとても楽しかったです。ご来場いただいた皆さま、ありがとうございました。

*1:視力1.0未満だとAではぼやけるそうです。裸眼でも1.0ある人は少ないはずなので、Bのほうがよかったのかも

*2:アプリケーションを再起動すればいいのですが

システムテスト自動化カンファレンス2014で「ビルドプロセスとCI」をお話してきました #stac2014

ヤフー株式会社さんで開催された、テスト自動化研究会の旗艦イベント「システムテスト自動化カンファレンス2014」にスタッフとして参加、また、一枠いただいて講演させていただきました。

f:id:nowsprinting:20141215034050p:plain

写真は会場から見下ろせた、見ろ、リアj ミッドタウンのイルミネーション。

システムテスト自動化 標準ガイド

昨年に続き二回目の開催となったシステムテスト自動化カンファレンス2014。今回は、主催のテスト自動化研究会メンバーで翻訳・執筆を行なった書籍『システムテスト自動化 標準ガイド』で得られる知見を中心に紹介する内容でした。

システムテスト自動化 標準ガイド (CodeZine BOOKS)

システムテスト自動化 標準ガイド (CodeZine BOOKS)

  • 作者: Mark Fewster,Dorothy Graham,テスト自動化研究会,伊藤望,玉川紘子,長谷川孝二,きょん,鈴木一裕,太田健一郎,森龍二,近江久美子,永田敦,吉村好廣,板垣真太郎,浦山さつき,井芹洋輝,松木晋祐,長田学,早川隆治
  • 出版社/メーカー: 翔泳社
  • 発売日: 2014/12/16
  • メディア: 大型本
  • この商品を含むブログを見る

翔泳社様による書籍の先行販売も行われ、ご用意いただいた分および、急遽取りに行っていただいた会社在庫分まで完売してしまったとのこと。購入できなかった方は申し訳ないです。

またどこからか「ギア本」という愛称も付けていただいたようで、翻訳・執筆陣の端くれとして有難い限りです。

システムテスト自動化カンファレンス2014

カンファレンスの内容、また他の登壇者の資料については、connpassやテスト自動化研究会のWebサイトなどに順次上がっていくはずですので、そちらを参照してください。

ビルドプロセスとCI

システムテスト自動化 標準ガイド』の第14章「CI(継続的インテグレーション)」を書かせていただいた流れで、CIやビルドパイプラインまわりについてお話させていただきました。

会場は、何らかのCIツールを使っている方が7割くらい。Travis CIなどのサービスを使っている方は5〜6名ほど。

余りテクニカルな話ではなく、ツール起点で考えていませんか?基本に立ち返るために先人の知見に立ち返ってみては?という話。 「言われてみれば当たり前」のことに気付かないことは往々にしてあるはずで、それをちょっと視点を変えて見てみるきっかけにでもなれば幸いです。

実はかなり直前までオチがつかず困っていたのですが*1、「繰り返しはギャグの基本」という言葉を思い出してまとめてみました。基本大事。

なお、スライド内でも紹介していますが、CIやビルドパイプラインまわりのテクニカルな話は『継続的デリバリー』を読むのが一番だと思います。 『継続的インテグレーション入門』はさらに深く、原点に当たりたい人は読むといいと思います。

継続的デリバリー 信頼できるソフトウェアリリースのためのビルド・テスト・デプロイメントの自動化

継続的デリバリー 信頼できるソフトウェアリリースのためのビルド・テスト・デプロイメントの自動化

継続的インテグレーション入門

継続的インテグレーション入門

以下、質疑応答でいただいた内容とかTweet拾ったものとか。

Jenkinsについて

私のオススメは「かえる本」

Jenkins

Jenkins

あとは用途(目的)に応じて、という感じでしょうか。

Walterについて

Jenkinsのプラグインに対するアドバンテージを質問されました。私としては、

という点です。Jenkinsでもジョブ設定の差分を管理できるJobConfigHistory Pluginがありますが、可用性が断然違ってきます。

また、方向性としては、私の後に講演されたYahoo! JAPAN赤根さんのように、ジョブ自体を毎回生成するアプローチもありますね。

Walterについては、作者さんのブログ記事もご参考。

シンプルなビルドパイプラインツールwalterをリリースしました | Advanced Technology Lab

Travis CIについて

口頭で挙げたもの。

iOSアプリのビルド

はい、忘れてました。CloudBeesでもMac OS XのSlaveを選択できるので、iOSアプリのビルドできるはずです。少し前にPriceとか変更になったのですが、以前は有料プランでのみ選択可能だったはず。

【12/18追記】CircleCIもiOSビルドに対応したと発表されました。 see: Announcing the Launch of iOS and Android Support on CircleCI | The Circle Blog

iOSMac OS Xアプリのビルドは、Mac OS Xで実行する必要があります。JenkinsをLinux上に立てている場合はSlaveとしてMacを接続し、そこでビルドが走るようにする必要があります。

上記のTravis CIなどは、Mac OS Xの動作するWorkerを備えています。このような形でMac OS Xを使うのはAppleと別途契約しているという話だったはず。

iOSアプリのビルド自動化については、こちらがおすすめです(自薦)。

iOSアプリ テスト自動化入門

iOSアプリ テスト自動化入門

*1:中だるみについては早々に諦めた

日本Androidの会 VR部 #JAGVR 第1回勉強会に行ってきました

にわかに設立された日本Androidの会 VR部の第一回勉強会に行ってきました。

f:id:nowsprinting:20141116115552p:plain

ざっくりと二部構成で、発表と、班分けしてのVRデバイス体験&もくもく会

発表

ポイントだけ。細かくはそれぞれのスライド参照。

VR部について+AR・VRデバイスと開発環境の紹介(@youten_redo)

AR/VRコンテンツの作り方 - Google スライド

VR部の設立目的として、

  • みんなで(顔を合わせて)あそぶ
  • みんなで(はげましあってモチベを維持して)つくる

が挙げられていました。VRコンテンツとかUnityとか後発組の我々に取ってはありがたい限りです。

スライドの「VRコンテンツ要素の分類」には、Cardboard系のMHDや、ハコスコ(単眼ハコスコ)で体験できるVRコンテンツの違いが分類されていて、営業などでお客様に「まずここから」説明するときに使えそうな感じ。

質疑応答で用語の使い分けについて聞いたこと。

また、12/21(sun)に東海大学 高輪キャンパスで開催されるABC 2014 Winterに「VR部屋」が作られるので、デバイス・コンテンツの持ち寄り、また発表など企画しましょう、とのこと。

ABC 2014 Winter | Android Bazaar and Conference 2014 Winter

Google Cardboard を100円ショップの 材料で作ってみた(@ohwada)

20140820 Google Cardboard in Wearable Meeting

Cardboard本体をレーザーカッターで切り、レンズなどを100円ショップで調達する話。今はタオバイザー、ハコスコ版Cardboard、ハコスコDXとか完成品を購入できるものが出てきましたが、自作派も楽しそう。

自作といえば@kakocomさんが本体から自作なものを持って来られていて、見せていただきました。

VRにおける入力デバイス(@nowsprinting)

自分の発表。ざっと調べた、VR世界への入力方法(デバイスに限らず)の紹介。画像の選定にとても時間を食いました。

しかし、歯ブラシコントローラの素晴らしさを伝えきれていないような気がして、大変心残りです。どこかのVRイベントで見かけたらぜひ体験するべきです。

VRの薄い本について(@l1cml @syyama_net)

今朝見たらアカウントが変わっていた @syyama_net さん。VRの薄い本をRe:VIEWで書くので、執筆したい人募集!のこと。

透過型HMD Google Glass の紹介(@teshi04)

てしさんの人生初LT。最近影の薄い感じのあるGoogle Glassについて、できること、アプリストア、野良アプリなどの紹介。Glass愛を感じました。

普通にGlassをかけて街を歩ける世の中が来て欲しいというのは同感。常々「カメラ無くていいから」と思ってます。

VRデバイス体験&もくもく&雑談

3ブロックに分かれて、持ち寄ったデバイスの体験とか雑談とか。本当はジェスチャー入力系のAssetをアレコレしようと目論んでいましたが、持ち込んだマシンでは色々足りなくて断念。

気になっていたRICOH THETA m15とかステレオカメラ(3Dカメラ)とかの知見を得られたのでよかった。

また、懇親会では小さい方のテーブルでメインフレームの話とかVRの没入感についての話とかもして楽しかった。

まとめ

Androidか何かの下地があって、VRに入る取っ掛かりとしてはいい感じの勉強会だったと思います。 最近では「サマーレッスン」開発の話として「VRの一般化」ということが語られていて、そうなると開発者としても営業としても、人に説明/説得する、その手段として体験してもらう、ということは意識していかないと。

そして、次回開催より先にABC 2014 Winterが来ると思うので、何かしら協力したい。

ABC 2014 Winter | Android Bazaar and Conference 2014 Winter