【Android Studio】Junitでタップとスワイプ(+private変数判定)【日本語】

Android Studio(JAVA)のJUnitで、タップ(クリック)とスワイプ(スライド)のテストをしてみた。

オマケでprivate変数の値を元に判定もしてみた。

尚、本記事は過去のJUnitテストの続きから行ってます。

 

過去のJUnitテストについてはこちら

他のプログラミングに関する記事はこちら

スポンサーリンク


 

【前提】

過去のJUnitテストを行った後からスタートします。

過去のJUnitテストについてはこちら

 

【早速実装してみる】

1.レイアウトのxmlを以下の通り更新します。

やってることは元からあるHelloWorldを消して、タップ操作が出来るラジオボタンと、スワイプ操作が出来るシークバーを作成しているだけです。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <RadioGroup
        android:id="@+id/radioGroup"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" >

        <RadioButton
            android:id="@+id/radioButton1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:checked="true"
            android:text="RadioButton1"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <RadioButton
            android:id="@+id/radioButton2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="RadioButton2"
            app:layout_constraintLeft_toLeftOf="@+id/radioButton1"
            app:layout_constraintTop_toBottomOf="@+id/radioButton1" />

        <RadioButton
            android:id="@+id/radioButton3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="RadioButton3"
            app:layout_constraintLeft_toLeftOf="@+id/radioButton2"
            app:layout_constraintTop_toBottomOf="@+id/radioButton2" />
    </RadioGroup>

    <SeekBar
        android:id="@+id/seekBar"
        android:layout_width="200dp"
        android:layout_height="30dp"
        android:max="20"
        android:progress="10"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/radioGroup"/>

</androidx.constraintlayout.widget.ConstraintLayout>

 

結果、こんな形になります。

 

2.MainActivityクラスを以下の通り更新します。

やってることは、レイアウトのRadioGroupとSeekBarをID指定で取得しているだけです。

package com.sample.junittest;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.RadioGroup;
import android.widget.SeekBar;

public class MainActivity extends AppCompatActivity {

    /**
     * RadioGroup
     */
    private RadioGroup radioGroup;

    /**
     * SeekBar
     */
    private SeekBar seekBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        radioGroup = findViewById(R.id.radioGroup);
        seekBar = findViewById(R.id.seekBar);
    }
}

 

3.Gradle.build(Module(app)の方)のandroid内のdefaultConfigに以下追加します。

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

更に、同Gradle.build内のdependenciesに以下追加します。

    androidTestImplementation 'androidx.test.ext:junit:1.1.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
    androidTestImplementation 'androidx.test:rules:1.1.0'

Gradle.build全体でみると、以下みたいになります。

apply plugin: 'com.android.application'
apply plugin: 'jacoco'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.2"
    defaultConfig {
        applicationId "com.sample.junittest"
        minSdkVersion 28
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" //追加
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.0' //追加
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' //追加
    androidTestImplementation 'androidx.test:rules:1.1.0' //追加
}

 

4.Gradle.buildを更新したら、忘れずにGradleの設定を適用します。

Gradleの設定を適用するには、画面右上にあるゾウさんのアイコンをクリックします。

 

5.androidTestの方のtestに対し右クリック>New>JavaClassで新しいクラスを作成します。

操作を伴うJUnitのテストクラスはandroidTestの方に作成しないとエラーになります。

※操作を伴わないJUnitのテストクラスは前回と同じくtestの方(以下画像でいうとCalculatorTestクラスがある方)に作成でいいかと

 

6.任意の名前を付けてOKします。今回は「MainActivityTest」という名前にします。

 

これで空のクラスが出来上がります。

7.作成したMainActivityTestクラスに以下記述をします。

package com.sample.junittest;

import android.util.Log;
import android.widget.RadioGroup;
import android.widget.SeekBar;

import org.junit.Rule;
import org.junit.Test;

import androidx.test.rule.ActivityTestRule;

import java.lang.reflect.Field;

import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.swipeLeft;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static junit.framework.TestCase.assertEquals;

public class MainActivityTest {
    @Rule
    public ActivityTestRule<MainActivity> mainActivityActivityTestRule = new ActivityTestRule<>(MainActivity.class,false, false);

    @Test
    public void testClickAndSwipe() throws Exception{
        // アクティビティ作成
        MainActivity mainActivity = mainActivityActivityTestRule.launchActivity(null);

        // ラジオボタンのリソースを取得してクリック
        onView(withId(R.id.radioButton3)).perform(click());

        // シークバーのリソースを取得して左にスワイプ
        onView(withId(R.id.seekBar)).perform(swipeLeft());

        // private変数取得
        Field fieldRadioGroup = mainActivity.getClass().getDeclaredField("radioGroup");
        Field fieldSeekBar = mainActivity.getClass().getDeclaredField("seekBar");

        // private変数へのアクセス制限を解除
        fieldRadioGroup.setAccessible(true);
        fieldSeekBar.setAccessible(true);

        // 値取得
        RadioGroup radioGroup = (RadioGroup) fieldRadioGroup.get(mainActivity);
        SeekBar seekBar = (SeekBar) fieldSeekBar.get(mainActivity);

        // 判定
        assertEquals(radioGroup.getCheckedRadioButtonId(),R.id.radioButton3);
        assertEquals(seekBar.getProgress(), 0);

    }
}

 

ざっというと

・@Ruleで、@Testの内容が行われる前にMainActivityクラスを生成してます

・onViewのperformで、クリックしたりスワイプしたりしてます

・private変数の値を確認する場合はFieldを使ってアクセス制限を解除して、値を取得してます。

getDeclaredField内の文字列は、MainActivityクラスで使っている変数名と同じにする必要があります。

・最後に値を取得して、判定してます

 

8.画面上部のメニューからRun>Runを選択します

 

9.ドロイド君のアイコンのテスト用メソッド(今回はtestClickAndSwipe())を選択します

そうすることでエミュレーターが立ち上がり、勝手にテストコードで記載した操作が行われ、結果を判定します

 

 

他のプログラミングに関する記事はこちら

スポンサーリンク