ubuntu16.04でAndroid StudioのEmulatorが起動しない

環境
ubuntu 16.04
Android studio 3.0.1

エミュレータを起動しようとすると、起動せずに終了してしまいます。

Event Log

17:49   Emulator: libGL error: unable to load driver: nouveau_dri.so

17:49   Emulator: libGL error: driver pointer missing

17:49   Emulator: libGL error: failed to load driver: nouveau

17:49   Emulator: libGL error: unable to load driver: swrast_dri.so

17:49   Emulator: libGL error: failed to load driver: swrast

17:49   Emulator: X Error of failed request:  BadValue (integer parameter out of range for operation)

17:49   Emulator: Major opcode of failed request:  155 (GLX)

17:49   Emulator: Minor opcode of failed request:  24 (X_GLXCreateNewContext)

17:49   Emulator: Value in failed request:  0x0

17:49   Emulator: Serial number of failed request:  58

17:49   Emulator: Current serial number in output stream:  59

17:49   Emulator: Process finished with exit code 1

調べた記事を参考に、ANDROID_EMULATOR_USE_SYSTEM_LIBS=1を設定してみました。

export ANDROID_EMULATOR_USE_SYSTEM_LIBS=1

Googleロゴまで表示されるようになりましたが、直後に終了してしまいます。

Event Log

17:51   Emulator: Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)

「ubuntu Emulator: Process finished with exit code 139」で検索すると、次の記事が見つかりました。

ubuntuでAndroid StudioのEmulatorが起動しない問題
https://qiita.com/yuqengo/items/ffd7f916c276bd4f84ce

エミュレータ設定のGraphicsをAutomaticからSoftwareに変更したら、起動しました。

「export ANDROID_EMULATOR_USE_SYSTEM_LIBS=1」を設定しなくても、起動しました。

gitブランチの名前の付け方2

以前、gitブランチの名前の付け方について紹介したことがあります。

gitのブランチの名前の付け方

実際に定着している名前は、次の4つです。
プロジェクトによっては、master、developだけで済ましてしまうこともあります。

(1) master
製品ブランチ

(2) develop
リリース前の確認用ブランチ

(3) personals/aoki/develop
開発者ごとの作業ブランチです。developからブランチします。

(4) personals/aoki/1
一時的な作業ブランチです。最後の数字はチケット番号です。personals/aoki/developですでに作業中のとき、別チケットの作業をしたいときの一時的なブランチです。developからブランチします。コミットして、developへマージしたら、すぐに削除します。

今は使わなくなった方法も紹介しましょう。

(ボツ1) ブランチ名に機能の名称をつける

チケットにする前の実験的な機能を試したいときに、ブランチ名に機能の名称をつけたことがあります。

例えば、
develop_camera
develop_news

コレという名前を考えるのが面倒でした。チケットを起こしてチケット番号をつけたほうが楽です。そもそも実験的なので放置することも多く、何をやっていたかを覚えていないこともあります。チケットにアイデアをメモしておくと、何をやっていたか思い出しやすくなります。

(ボツ2) 複数の作業ブランチ

gitは簡単にブランチ作成できることもあって、
personals/aoki/1
personals/aoki/2
personals/aoki/3
といったように、複数の作業ブランチを作成していたことがあります。

confictの解決も手間ですが、conflictがなかったとしても、マージ操作自体が面倒でした。

例えば、personals/aoki/1の作業が一段落したら、
personals/aoki/1からdevelopへマージ
developからpersonals/aoki/2へマージ
developからpersonals/aoki/3へマージ
する必要があります。

さらに、他の開発者がdevelopへpushしたら、
developからpersonals/aoki/1へマージ
developからpersonals/aoki/2へマージ
developからpersonals/aoki/3へマージ
する必要があります。

このようにブランチ切り替えとマージ操作が多くて面倒だったので、ブランチを作りすぎるのもどうかと感じました。

「継続的デリバリー」という本では、複数人で開発していても、メインブランチ1本を推奨しています。ブランチ間のマージが面倒になるため、またメイン以外のブランチは自動テストしないことが多いためです。また、少なくても1日に1回、たいていは1日に数回コミットすることも推奨しています。

デバッガでトレースしやすい書き方

IDEのデバッガには、1行づつの「ステップ」、関数の中へ入る「ステップイン」、関数から戻る「ステップオーバー」、ローカル変数やメンバー変数の値を表示する機能があります。式の一部分を指定して評価する機能もありますが、その操作をする必要があります。

「ステップイン」することなく、「ステップ」だけでどこを通っているかを確認できたり、関数の戻り値を確認できると、デバッグしやすいです。

以下の例は、架空の言語です。

1行に関数を2つ以上書くと、2つめ以降の関数にステップインしにくい

デバッグしにくい例
func_b内にステップインするためには、1回目の「ステップイン」でfunc_aにステップインします。「ステップオーバー」でこの行に戻ります。2回目の「ステップイン」でfunc_bにステップインします。

func_a(); func_b();

デバッグしやすい例
func_bの行で止まり「ステップイン」すると、func_b内にステップインします。

func_a();
func_b();

if文の条件部分と本体を1行にすると、ifの本体を通ったのかわからない

デバッグしにくい例
ステップ実行すると、if文のtrue/falseに関係なく、次の行に進みます。funcを呼んだかどうかがわかりづらいです。

if (1 < a) { func(); }

デバッグしやすい例
ステップ実行すると、if文がtrueなら、func()の行で止まります。

if (1 < a) {
    func(x);
}

if文の条件式が複雑だと、デバッグしにくい

デバッグしにくい例

if (x <= func_a() && y <= func_b()) {
}

デバッグしやすい例

function is_xxxx(x, y) {
    a = func_a();
    b = func_b();
    f1 = x <= a;
    f2 = y <= b;
    f = f1 && f2;
    return f;
}

if (is_xxxx(x, y)) {
}

関数Aの引数で関数Bを呼ぶと、関数Bの戻り値を確認しにくい

デバッグしにくい例
func_bの戻り値を確認するには、func_aにステップインする必要があります。
また「1行に関数を2つ以上書くと、2つめ以降の関数にステップインしにくい」と同じ問題があります。

func_a(func_b());

デバッグしやすい例
func_a(b);の行で止まると、変数のbの値が表示されます。

b = func_b();
func_a(b);

return式で関数Aを呼ぶと、関数Aの戻り値を確認しにくい

デバッグしにくい例
funcの戻り値を確認できません。

return func();

デバッグしやすい例
return result;で止まると、変数resultの値が表示されます。

result = func();
return result;

右辺の式内で関数を呼ぶと、戻り値を確認しにくい

デバッグしにくい例
func_aやfunc_bにステップインしないと、戻り値を確認できません。

x = func_a() + func_b();

デバッグしやすい例
x = a + b;の行で止まると、変数aや変数bの値が表示されます。

a = func_a();
b = func_b();
x = a + b;

判断と処理を分けて読みやすくする

判断と処理を分けると、読みやすく、テストしやすく、デバッグしやすくなります。

例は javascriptで書いています。

1.初期バージョン

最初に書くバージョンはだいたいこんな感じです。
「もろもろの処理」は、複数行だったり、if文やfor文を含むことがあります。

function func2 (a, b) {
    if (a > 10) {
        if (a > 20) {
            if (a > 30){
                もろもろの処理_1
            } else {
                もろもろの処理_2
            }
        } else {
            もろもろの処理_3
        }
    } else {
        もろもろの処理_4
    }
}

2.もろもろの処理をそれぞれ別メソッドにします。

function func2 (a, b) {
    if (a > 10) {
        if (a > 20) {
            if (a > 30){
                func2_1();
            } else {
                func2_2();
            }
        } else {
            func2_3();
        }
    } else {
        func2_4();
    }
}

function func2_1() {
    もろもろの処理_1
}

function func2_2() {
    もろもろの処理_2
}

function func2_3() {
    もろもろの処理_3
}

function func2_4() {
    もろもろの処理_4
}

3.「判断」と「処理」を別メソッドにします。

function func2 (a, b) {
    var num = case_number(a, b);
    process(num);
}

function case_number(a, b) {
    var num = 0;
    if (a > 10) {
        if (a > 20) {
            if (a > 30){
                num = 1;
            } else {
                num = 2;
            }
        } else {
            num = 3;
        }
    } else {
        num = 4;
    }
    return num;
}

function process(num) {
    switch (num) {
        case 1:
            func2_1();
            break;
        case 2:
            func2_2();
            break;
        case 3:
            func2_3();
            break;
        case 4:
        default:
            func2_4();
            break;
    }
}

4.判断内のif文のネストをelse〜ifで小さくします。

function case_number(a, b) {
    var num = 0;

    if (a <= 10) {
        num = 4;
    } else if (a <= 20) {
        num = 3;
    } else if (a <= 30) {
        num = 2;
    } else {
        num = 1;
    }

    return num;
}

5.デシジョンテーブル風のコメントをつけておきます。

/*
| # | a     | action  |
| - | ----- | ------- |
| 4 | <= 10 | func2_1 |
| 3 | <= 20 | func2_2 |
| 2 | <= 30 | func2_3 |
| 1 | > 30  | func2_4 |
*/
function func2 (a, b) {
   ...
}

6. if文の条件式が長いときは、それぞれ別メソッドにします。

function case_number(a, b) {
    var num = 0;

    if (is_later_equal(a, 10)) {
        num = 4;
    } else if (is_later_equal(a, 20)) {
        num = 3;
    } else if (is_later_equal(a, 30)) {
        num = 2;
    } else {
        num = 1;
    }

    return num;
}

function is_later_equal(a, x) {
    var f = (a <= x);
    return f;
}

最後に、func2メソッドの処理をとりだして、別クラスにします。

cordovaで開発したiPhoneアプリをappiumでテスト(2/2)

cordovaで開発したiPhoneアプリをAppiumでテストしたので、まとめました。

cordovaで開発したiPhoneアプリをappiumでテスト(1/2)
1.目標
2.simulator用appをビルド
3.appium他のインストール
4.Appiumデスクトップのインストール
5.Appiumデクトップを起動、Inspectorウィンドウで操作の記録

cordovaで開発したiPhoneアプリをappiumでテスト(2/2)
6.nodeでテストケース作成(アプリ起動のみ)
7.テストケースの実行
8.テストケース作成(座標をタップ、スクリーンショット保存)

6.nodeでテストケース作成

githubにappium公式サンプルソースがあります。
https://github.com/appium/sample-code

sample-code/examples/node/helpers/*.js
sample-code/examples/node/ios-simple.js
sample-code/examples/node/package.json
をダウンロードして、ios-simple.jsを改造します。

/Users/taro/projects/hello/platforms/ios/appium-testcaseの下に
helpers/*.js
ios-simple.js
package.json
を保存しました。

必要なnodeモジュールをインストールします。

$ cd /Users/taro/projects/hello/platforms/ios/appium-testcase
$ npm install

beforeメソッドのdesired変数は、「4.Appiumデクトップを起動、Inspectorウィンドウで操作の記録」のdesired capbilitiesの各項目を参考に設定してください。

テストケースの内容は、アプリを起動して、1秒間表示して、終了するだけです。

ios-simple.jsを編集します。

"use strict";

require("./helpers/setup");

var wd = require("wd"),
    _ = require('underscore'),
    Q = require('q'),
    serverConfigs = require('./helpers/appium-servers');

describe("ios simple", function () {
  this.timeout(300000);
  var driver;
  var allPassed = true;

  before(function () {
    var serverConfig = process.env.npm_package_config_sauce ?
      serverConfigs.sauce : serverConfigs.local;
    driver = wd.promiseChainRemote(serverConfig);
    require("./helpers/logging").configure(driver);

    var desired = {
      "appium-version": "1.4",
      platformName: "iOS",
      deviceName: "iPhone 7",
      platformVersion: "11.0",
      automationName: "XCUITest",
      app: "/Users/taro/projects/hello/app/Applications/HelloWorld.app",
    }; 

    return driver.init(desired);
  });

  after(function () {
    return driver
      .quit()
      .finally(function () {
        if (process.env.npm_package_config_sauce) {
          return driver.sauceJobStatus(allPassed);
        }
      });
  });

  afterEach(function () {
    allPassed = allPassed && this.currentTest.state === 'passed';
  });

  it ("test_1", function () {
    return driver
      .sleep(1000)
  });

});

7.テストケースの実行

appiumサーバの起動

Appiumデスクトップで[Start Server]しておくか、または、ターミナルで

appiumサーバの起動
$ appium &

appiumサーバの停止
$ pkill -f appium

テストケースの実行

$ cd /Users/taro/projects/hello/platforms/ios/appium-testcase
$ npm run ios-simple

iPhone simulatorの終了

$ pkill -f CoreSimulator

8.テストケース作成(座標をタップ、スクリーンショット保存)

Inspectorウィンドウで、xy座標をメモしてはクリックを繰り返して、テストケースを作りました。
次のように、座標指定のタップ、スクリーンショット保存処理、AlertダイアログのOKを追加しました。

"use strict";

require("./helpers/setup");

var wd = require("wd"),
    _ = require('underscore'),
    Q = require('q'),
    serverConfigs = require('./helpers/appium-servers'),
    fs = require('fs');

describe("ios simple", function () {
  this.timeout(300000);
  var driver;
  var allPassed = true;

  before(function () {
    var serverConfig = process.env.npm_package_config_sauce ?
      serverConfigs.sauce : serverConfigs.local;
    driver = wd.promiseChainRemote(serverConfig);
    //require("./helpers/logging").configure(driver);

    var desired = {
      "appium-version": "1.4",
      platformName: "iOS",
      deviceName: "iPhone 7",
      platformVersion: "11.0",
      automationName: "XCUITest",
      app: "/Users/taro/projects/hello/app/Applications/HelloWorld.app",
    }; 

    driver.saveScreenshot = function (path) {
      return driver.takeScreenshot().then(function(data) {
        fs.writeFile(path, data, "base64", function(err) {
          if (err) {
           throw err;
          }
        });
      });
    };

    return driver.init(desired);
  });

  after(function () {
    return driver
      .quit()
      .finally(function () {
        if (process.env.npm_package_config_sauce) {
          return driver.sauceJobStatus(allPassed);
        }
      });
  });

  afterEach(function () {
    allPassed = allPassed && this.currentTest.state === 'passed';
  });

  var tap_at = function (x, y) {
    var action = new wd.TouchAction();
    return action
      .press({"x": x, "y": y})
      .wait(100)
      .release();
  }

  it ("test_1", function () {
    return driver
      .sleep(1000)
      .saveScreenshot("/Users/taro/projects/hello/platforms/ios/appium-testcase/screenshots/01.png")

      .performTouchAction(tap_at(161, 464))
      .sleep(1000)
      .saveScreenshot("/Users/taro/projects/hello/platforms/ios/appium-testcase/screenshots/02.png")

      .acceptAlert()
      .sleep(1000)
      .saveScreenshot("/Users/taro/projects/hello/platforms/ios/appium-testcase/screenshots/03.png")
  });

});

最終的に、desired変数のdeviceName、platformVersion、appやスクリーンショット保存パスは、環境変数で渡すようにしました。
また、シミュレータでの実行が思ったより遅かったので、sleepで調整しています。

三項演算子はデバッグしにくい

三項演算子はデバッグしにくいので、デバッグしやすさという観点では使わないほうがいいと思います。

三項演算子の例

x = (a < b) ? a : b;

if文の例

if (a < b) {
    x = a;
} else {
    x = b;
}

理由1:
デバッガでステップ実行したとき、if文のほうが処理の流れを追いやすいから。

三項演算子の文をデバッガでステップ実行すると、単に次の行に移動します。行を追っているだけでは、aとbのどちらを採用したのかがわかりません。a, b, xの値を読んだり、式を評価する必要があります。

if文をステップ実行すると、if の次に、x = a; または x = b; の行に移動します。どの選択肢に移動したのか、ひと目でわかります。

理由2:
選択肢が3つ以上になったとき、if文で書き直すから。

今は選択肢が2つですが、近い将来3つに増えるかもしれません。三項演算子で書いてあれば、if〜else if文で書き直すでしょう。それなら、今、if文で書いたほうがいいと思います。

理由3:
三項演算子を入れ子にした難解なコードを見たことがあるから。

見た瞬間、ここ触りたくねーと思いました。

この記事を書いた後、自分のソースを検索したら、予想より多く見つかりました。まあそんなもんですね。

この記事のタグは「コーディングスタイル」より「デバッガブル」だなと思い、「デバッガブル」で検索したら、いい記事が見つかりました。
デバッグしやすい、解析しやすいコードを書こう

gitのブランチの名前の付け方

かつてSubversionを使っていたときは、ほとんどブランチを使ったことがない。慣例にしたがってtrunk、branches、tagsを用意するものの、trunkだけを使っていた。ブランチとタグの違いを理解していなかった。ブランチ操作を難しいものと思い込んでいたし、「変更履歴」と「以前の状態と比較できる」だけで満足していた。

gitを使うようになってからブランチ/マージを試してみたら、あっけないほど簡単だった。日常的にmasterブランチと開発ブランチを使うようになった。

するとブランチの名前の付け方を考えるようになった。最初はmasterとwork。次の段階では、チケット番号をつけてwork_1234 や ticket_1234で作業するようになった。この程度のざっくりとした運用で問題はないのだが、標準的なブランチ名の付け方や運用方法があるなら、知りたいと思っていた。

素晴らしい記事を発見した。ブランチは5個あるが、各ブランチの目的と運用方法が明確で迷うことはないと思う。

O-Showさんの日本語訳
http://keijinsonyaban.blogspot.jp/2010/10/successful-git-branching-model.html

Vincent Driessenさんの原文”A successful Git branching model
http://nvie.com/posts/a-successful-git-branching-model/

中央リポジトリ(例 github)

・master 現在の製品バージョン。
・develop 次回リリースの開発用。

開発者リポジトリ

・feature- 新規機能の開発用。developから分岐し、developへマージする。
・release-
 次回リリースの準備用。developから分岐し、developとmasterへマージする。
・hotfix-* 現在の製品バージョンのバグフィックス用。masterから分岐し、developとmasterへマージする。

※このブランチモデルをベースにしたgit-flow というプラグインもある。

gitブランチの名前の付け方2