LoginSignup
13
3

More than 3 years have passed since last update.

星1個のアプリなんて作りたくない

Last updated at Posted at 2019-12-13

Labomartの軌跡。構想から運用まで@unotovive
ゆめみ Advent Calendar 2019 の前回の記事

はじめに

Android アプリ開発者のみなさん、Google I/O 2018 の下記のセッションは見ましたか?

ちなみに、私は、、、、、、見てないです :rolling_eyes:

セッションでは、Play Store で星1レビューのついた原因分析を公開して

原因の42% は「アプリのクラッシュを含む安定性の問題」だったみたい。


出典: Youtube (Improve app performance and stability with Firebase (Google I/O'18))

星1レビューもらいたくない

テストを書きましょう笑

よくテストを書く時間がないと聞きますが、、

たぶん仕様調整やテストの時間がないだけです笑

きちんと仕様調整やテストの時間をもらいましょう :no_good:

そして、プログラムや仕様のバグを洗い出すのです :sunglasses:

千里の道も一歩から

テストを書くことは思っているより簡単。

まずは1つテストを書いてみましょう!!

テストって?

テストの種類には下記のようなものがあって

  • 単体テスト
  • 結合テスト
  • UI テスト

今回は単体テストに焦点を当てて話をしていきます!

Android の単体テスト

Android の単体テストには下記のようなものがあります

  • Local Unit Test
  • Instrumented Unit Test

何が違うん??って感じですが、簡単にいうと実機やエミュレーターが必要かどうかです。

今回は、実機やエミュレーターが必要ない Local Unit Test をやっていきます!

強い意志でテストを書こう

テストを書くのに強い意志は必要ありませんw

なんか物足りなかったので付けました笑

さて、テストを書いていこうと思いますが

せっかくなので最新の技術を使っちゃいます :nerd:

今回は JUnit5Truth を使います!

※ Truth は assertThat 使うために入れてます。ただそんだけですw

準備

ここからやっとコード書いていきます〜

下記の変更をして、Sync Now しちゃえばおk

ExampleUnitTest.kt は要らないので削除してね

app/build.gradle
android {
    ...
+   kotlinOptions {
+       jvmTarget = '1.8'
+   }
}

dependencies {
    ...
-   testImplementation 'junit:junit:4.12'

+   testImplementation 'org.junit.jupiter:junit-jupiter-api:5.5.2'
+   testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.5.2'
+   testImplementation "org.junit.jupiter:junit-jupiter-params:5.5.2"
+   testImplementation 'com.google.truth:truth:1.0'
}

テストするもの

今回は下記のような String の拡張関数作って

よくあるパスワードチェック処理をテストしていきます!

extensions/StringExtension.kt
package {自分のパッケージ名}.extensions

/**
 * パスワードの条件
 *
 * 半角英小文字・大文字・数字をそれぞれ1種類以上含む
 * 8文字以上10文字以下
 */
fun String.isPassword(): Boolean {

    val regex = Regex("""
        ^(?=.*?[a-z])(?=.*?[A-Z])(?=.*?\d)[a-zA-Z\d]{8,10}${'$'}
    """.trimIndent())

    return matches(regex)
}

テスト実行!!!!

test パッケージの下に下記のファイルを作成します!

extensions/StringExtensionKtTest.kt
package {自分のパッケージ名}.extensions

import org.junit.jupiter.api.Test

import com.google.common.truth.Truth.assertThat

internal class StringExtensionKtTest {

    @Test
    fun isPassword() {

        val password = "1234abcdAB"

        assertThat(password.isPassword()).isTrue()
    }
}

そして、isPassword() メソッドの左にある実行マーク押して

テストを動かしてみてください!

テストが成功すると気持ちいいですよね!

テストが成功する度に緑のチェックマークがクセになっていきます

複数パターン一気にテストしたいよ

さっきのテストでは1つしかテストできてない。。

一気に10個とかやっちゃいたい、、どうすれば、、、

はい、そんなときのために ParameterizedTest があります :sunglasses:

使ってみましょ〜

extensions/StringExtensionKtTest.kt
package {自分のパッケージ名}.extensions

import com.google.common.truth.Truth.assertThat
import org.junit.jupiter.api.extension.ExtensionContext
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.Arguments.arguments
import org.junit.jupiter.params.provider.ArgumentsProvider
import org.junit.jupiter.params.provider.ArgumentsSource
import java.util.stream.Stream

internal class StringExtensionKtTest {

    @ParameterizedTest
    @ArgumentsSource(TestCase::class)
    fun isPassword(password: String, expected: Boolean) {

        assertThat(password.isPassword()).isEqualTo(expected)
    }

    private class TestCase : ArgumentsProvider {
        override fun provideArguments(context: ExtensionContext?): Stream<out Arguments> = Stream.of(
            arguments("1234abcdAB", true),
            arguments("abcdAB1234", true),
            arguments("1234abcdab", false)
        )
    }
}

はい、JUnit5 最高

これで複数ケース簡単にテストできますね♪

じゃんじゃんテストケース追加していってください :relaxed:

実は、、

テストが失敗するケースがあります笑

みなさん見つけられましたかね?

見つけられていない方はテストケース追加しまくってくださいね :heart:

おわりに

ちゃんとテストを書いて、少しでもバグを減らして

星5のレビューたくさんもらえるようになりましょ〜 :star2:

明日は @ihcamonoihS さんの記事 :hand_splayed:

参考文献

13
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
3