皆さん、UIテスト書いていますか?
ユニットテストなら何とかという人でも、UIテストとなるとUIの更新頻度や費用対効果的な側面から、きっちりやっているというのは少ないのではないでしょうか。
そんな折、下記の素晴らしい記事を拝見し、スクリーンショットを撮るだけでもかなり効果があるのではないかと感じました。
AndroidアプリのゆるいUIテストをSpoonで実現する
https://qiita.com/oxsoft/items/d5774cc9c6016c3c28ec
で、いざSpoonでスクリーンショットを撮るところまでやってみようとしたものの、見事に躓いてしまったので、一旦 UIテストのスクリーンショットを撮る までを実現するところまでを記事にしたいと思います。
※ Spoon
https://github.com/square/spoon
Gradle Spoon Pluginを使用する
GitHubのページからjarをダウンロードしてゴニョゴニョする、ということも出来るようですが、楽をするためにGradleのプラグインを使用します。
(1). https://github.com/stanfy/spoon-gradle-plugin
(2). https://github.com/jaredsburrows/gradle-spoon-plugin
2つほどあるようですが、(1)に関しては最終更新日が1年以上前のようで、Android Gradle Pluginもver. 2までとのことで(2)のほうを使うことにしました。
導入
基本的にはREADMEに書いてあるものをコピペで問題ありませんでした。
buildscript {
repositories {
google()
jcenter()
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
}
dependencies {
classpath "com.jaredsburrows:gradle-spoon-plugin:1.4.0"
}
}
repositories {
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
}
apply plugin: "com.android.application"
apply plugin: "com.jaredsburrows.spoon"
dependencies {
androidTestCompile "com.squareup.spoon:spoon-client:2.0.0-SNAPSHOT"
}
テストクラスを作成
サンプルとして MainActivity
をテストするクラスを作成します。
スクリーンショットを撮る必要などがあるため、 androidTest
のディレクトリに作成することになります。
下記コードは、MainActivityを起動してスクリーンショットを撮る、というコードになります。
import android.content.Intent
import android.support.test.rule.ActivityTestRule
import android.support.test.runner.AndroidJUnit4
import com.squareup.spoon.SpoonRule
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class MainActivityTest {
@Rule
@JvmField
val activityRule = ActivityTestRule(MainActivity::class.java, false, false)
@Rule
@JvmField
val spoon = SpoonRule()
@Test
fun screenshotMainActivity() {
val mainActivity = activityRule.launchActivity(Intent())
spoon.screenshot(mainActivity, "MainActivity")
}
}
ポイント
Spoon ver.2 からなのかわかりませんが、GitHubのサンプルコードでは Spoon.screenshot
というメソッドでスクリーンショットを撮れるようですが、それが出来ず、代わりに @Rule
アノテーションを用いて SpoonRule
というクラスを使うことでスクリーンショットを撮ることが出来るようでした。
パーミッションを追加
これでOKと思い ./gradlew spoon
を実行すると下記のようなエラーが発生しました。
> Task :app:spoonDebugAndroidTest
2018-04-12 20:52:39 [SR.runTests] Executing instrumentation suite on 1 device(s).
2018-04-12 20:52:44 [SDR.handleFiles] Found class name dirs: []
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:spoonDebugAndroidTest'.
> Tests failed! See /Users/user_name/Spoon/app/build/spoon-output/debug/index.html
Spoonでは、テストの結果がHTMLとなって生成されるのでそれを見てみます。
ディレクトリを作れないエラーのようです。
ポイント
Spoonではスクリーンショットを保存したりする関係上、外部ストレージへのパーミッションが必要となります。 (WRITE_EXTERNAL_STORAGE
)
そのままパーミッションを追加してもいいですが、アプリとして WRITE_EXTERNAL_STORAGE
が不要な場合は、debug用のAndroidManifest.xmlを作り、そちらだけに定義するのもいいかもしれません。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="test.spoon">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>
これで準備は完了で、 ./gradlew spoon
でスクリーンショットが保存されるようになります🚀 (※ Runtime Permission用の設定をしてないのにWRITE_EXTERNAL_STORAGEが使えているのはよくわかりません。)
app/build/spoon-output
というフォルダにスクリーンショットの画像などが生成されています。
まとめ
Spoonを用い、UIテストのスクリーンショットを撮るところまで説明しました。躓いた点はあるものの、意外とすんなりと導入することが出来たかと思います。
きっちりしたUIテストを書くのはしんどいかもしれませんが、ゆるいUIテストとしてスクリーンショットを撮っていくのはなんとかやっていけそうな感があったので、機会があれば実践していきたいところです。
ちなみにスクリーンショットを撮って、差分をチェックとかをするのがいいと思いますが、冒頭に紹介した投稿でも言及されているように、スクリーンショットにタイムスタンプが入っていたり、運用していくためにはもう少しカスタマイズしていく必要がありそうです。