2015/12/21

Android: Checkstyle

ファイルの一部分をチェック対象外にする

Checkstyle - Filtersのsuppressを参照.

まず, checkstyleのconfigファイルに下記FileContentsHolderSuppressionCommentFiltermoduleを設定.

<module name="Checker">
  <module name="TreeWalker">
    ...
    <module name="FileContentsHolder"/>
  </module>
  <module name="SuppressionCommentFilter"/>
</module>

これで// CHECKSTYLE:OFFのコメントから// CHECKSTYLE:ONのコメントまでの間を, Checkstyleのチェック対象外として指定できる.

// CHECKSTYLE:OFF
for (int i = 0, len = array.length; i < len; i++) {
  ...
}
// CHECKSTYLE:ON

警告抑止設定の外部ファイル化

Suppression情報は外出しできる.

checkstyleのconfigファイルに下記SuppressionFiltermoduleを設定.
valueにsuppressions定義ファイルのパスを指定する.

<module name="SuppressionFilter">
  <property name="file" value="./app/config/checkstyle/suppressions.xml"/>
</module>

suppressions.xmlのexample.

<?xml version="1.0"?>

<!DOCTYPE suppressions PUBLIC
    "-//Puppy Crawl//DTD Suppressions 1.1//EN"
    "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">

<suppressions>
  <suppress checks="MethodName" files="Hoge.java" />
</suppressions>

Checkstyleの解析結果をHTML形式で出力する

Generate Checkstyle HTML report with Gradleを参照.

Checkstyle pluginのreportsはhtml形式をサポートしていないのでxslを使ってstylesheetをあてる.

task checkstyle(type: Checkstyle) {
    configFile = file("$projectDir/config/checkstyle/checkstyle.xml")
    source 'src/main/java'
    include '**/*.java'
    exclude '**/gen/**'
    classpath = files()
    reports {
        xml {
            destination "$buildDir/reports/checkstyle/report.xml"
        }
    }
}

task checkstyleReport << {
    if (file("$buildDir/reports/checkstyle/report.xml").exists()) {
        ant.xslt(in: "$buildDir/reports/checkstyle/report.xml",
                style:"$projectDir/config/checkstyle/checkstyle.xsl",
                out:"$buildDir/reports/checkstyle/checkstyle.html"
        )
    }
}

gradle.taskGraph.afterTask {Task task, TaskState state ->
    if(state.failure) {
        if (task.name in ['checkstyle']) {
            checkstyleReport.execute()
        }
    }
}

以上.

2015/12/15

Android: AppiumでUI Testing

本稿は下記を参考にしています.

Appiumは各ベンダ(Google, Apple)がリリースしているUI Testing Frameworkをラップした統一APIを提供してUIテストを可能にするもの.
これにより, iOSのテストケースをAndroidでも流用できるといったアドバンテージがある
(UI構成が違えばテストケースの流用は難しい)

AppiumがラップするUI Testing Frameworkは下記.

  • iOS: Apple’s UIAutomation
  • Android 4.2+: Google’s UiAutomator
  • Android 2.3+: Google’s Instrumentation.

確認環境は下記.

  • Android 5.0
  • Appium 1.4.13

注意点

Appiumはプロダクトのバイナリ(.apk)があればテスト可能だが, テスト対象アプリで準備が必要な点がある.
Android4.4以降でWebViewをテストする場合はWebViewのデバッグオプションが, Android4.1以前で動作する場合はINTERNETパーミッションが必要になる.

WebView

Android4.4からWebViewはChromiumベースに変更された.
テスト対象アプリをKitKat以上 かつ WebViewをテスト対象に含む場合は下記を実施する必要がある.

// WebViewをテストする場合は下記をWebView使用前に実施しておくこと.
WebView.setWebContentsDebuggingEnabled(true);

参考:

- Remote Debugging on Android with Chrome
- Appium - AUTOMATING HYBRID ANDROID APPS

Apptium or Selendroid

Androidのバージョンによって動作するモードが異なる.

  • Android 4.2+: Google’s UiAutomator
  • Android 2.3+: Google’s Instrumentation. (Instrumentation support is provided by bundling a separate project, Selendroid)

これはAppiumが使用するライブラリのサポート範囲に依存している.
Selendroid modeで確認する場合, テスト対象のアプリにINTERNETパーミッションを宣言する必要がある.

<uses-permission android:name="android.permission.INTERNET" />

参考:

- Appium - ANDROID SUPPORT
- Appium - Notes

Launch Appium server

Appiumをダウンロードする.
今回はAppium 1.4.13を選択. ダウンロードしたらAppiumを起動.

参考: Appium GUI

Appium GUIで下記を実行してAppiumサーバを起動する.

  1. Android Setting(Droid icon) - App Path にテスト対象のapkのパスを入力
  2. Android Settingを閉じて Launch

TestCase

Appiumはテスト対象アプリの操作に特化したツールであるため, アサーションなどの機構は別で用意する必要がある(Productionコードは必要無い).
今回は別プロジェクト(module)を作成してJUnitでテストスクリプトを書いた.

テストコードに必要なライブラリは下記.

dependencies {
    // Appiumクライアントライブラリを利用するための宣言
    testCompile 'io.appium:java-client:2.1.0'
}

テストの実行結果はbuild/reports/testsに出力される.

補足: io.appium:java-client:は3.3.0がリリースされていたが, hamcrestなど依存ライブラリが変わっている様子. 今回は動作確認目的のため2.1.0で実施.

以上.

AWS EC2 + bugspotsでバグ予測

AWS EC2にbugspotsの実行環境を構築した際のメモ.

Setup

試したEC2インスタンス(Amazon Linux)はt2.microの無料枠を使用.
EC2インスタンスを作成したらssh接続.
あらかじめインストールされているRubyバージョンを確認 (今回はruby 2.0.0p647で確認).

$ ruby -v

gitもインストールしておく (今回はgit 2.4.3で確認).

$ sudo yum install git

次にbugspotsのインストールで必要になるDevelopment toolcmakeをインストール.
(cmakeのバージョンは2.8.12)

$ sudo yum -y groupinstall "Development tools"
$ sudo yum install cmake

bugspotsをインストール.

$ sudo gem install bugspots

bugspots

git cloneでレポジトリを複製したらgitレポジトリでbugspotsコマンドを実行すればok.


# コミットログに"fix"を含むものを対象とする
$ bugspots . 

# コミットログが"bug"から始まるものを対象とする
$ bugspots -r "/^*bug/" .

より頻繁にbugfixされているソースコードほど高い値(Hotspots)になるアルゴリズム.
この記事が詳しい.

以上.

2015/12/09

Android:GradleでBuildConfigに定数追加する際のハック

Build variant毎に定数の値を変えたい場合, 下記のようにすることで実現できる.

productFlavors {
  development {
    buildConfigField "boolean", "PRODUCTION_MODE", "false"
  }
  production {
    buildConfigField "boolean", "PRODUCTION_MODE", "true"
  }
}

しかし, この例ではプロダクションモードを判定する下記のようなif文を書いた場合にAndroidStudioがwaningをあげてくる.

// これだとBuild variantによってPRODUCTION_MODEが常に
// true/false固定となり, AndroidStudioがシンプル化をすすめてくる. 
if (BuildConfig.PRODUCTION_MODE) { ... }

Build variantを変えるとtrue/falseが変わるため, コードをシンプル化(true/falseに置き換え)することはできない.
warningを放置すると誤ってシンプル化される恐れもある. 暫定的にwarningを回避する方法は下記.

// 下記コメントを記載することでwarning抑止できる
// noinspection ConstantConditions,PointlessBooleanExpression
if (BuildConfig.PRODUCTION_MODE) { ... }

もしくは, AndroidStudioをだます下記の方法でこれに対処することができる.

productFlavors {
  development {
    buildConfigField "boolean", "PRODUCTION_MODE", "Boolean.parseBoolean(\"false\")"
  }
  production {
    buildConfigField "boolean", "PRODUCTION_MODE", "Boolean.parseBoolean(\"true\")"
  }
}

Boolean.parseBoolean(String)を使うことでwarningが出なくなる.
(逆に言うとシンプル化できるところでwarningが出ていない)
後者はハックであるため今後も保証されたものではないことに注意.

確認したAndroidStudioのバージョンは1.5.1.

参考: Why does the BuildConfig class use Boolean.parseBoolean() instead of literal values?

以上.