Как выполнить простой модульный тест пользовательского интерфейса в Android, используя Robolecti c? - PullRequest
0 голосов
/ 16 апреля 2020

Я абсолютный новичок, когда прихожу на юнит-тест в Android и Robolecti c. Я пытаюсь написать простой модульный тест для взаимодействия моего пользовательского интерфейса, но я не могу понять, что считать правильным модульным тестом, а что нет.

Я смотрю это видео: Test-Driven Разработка на Android с Android библиотекой поддержки тестирования (Google I / O '17) . Исходя из моего понимания, модульный тест должен быть написан до написания реального кода, тогда код, который я пишу, должен удовлетворять только модульному тесту.

Поэтому вот что я хочу сделать:

  1. У меня есть действие с именем LoginActivity
  2. Внутри LoginActivity содержится 2 EditText с идентификатором username и password, кнопка с идентификатором loginButton и a TextView с идентификатором statusText
  3. При нажатии на loginButton, если username или password пусто, тогда установите statusText в качестве примера строки «Пароль не должен быть пустым».

Настройка файла build.gradle:

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"

    defaultConfig {
        applicationId "myaplication"
        minSdkVersion 21
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    testOptions {
        unitTests {
            includeAndroidResources = true
        }
    }

    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.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    testImplementation 'androidx.test.espresso:espresso-core:3.2.0'

    testImplementation 'junit:junit:4.12'
    testImplementation 'org.robolectric:robolectric:4.3'

    testImplementation 'androidx.test:core:1.2.0'
    testImplementation 'androidx.test:runner:1.2.0'
}

Вот модульный тест, который я пишу для случая, перечисленного выше:

import android.widget.EditText;
import android.widget.TextView;

import org.junit.Before;
import org.junit.Test;
import org.robolectric.Robolectric;

import androidx.test.filters.SmallTest;
import static org.junit.Assert.*;

@SmallTest
public class LoginActivityUnitTest {

    private LoginActivity loginActivity;
    private EditText username,password;
    private TextView statusText;

    @Before
    public void setUp(){
        loginActivity = Robolectric.buildActivity(LoginActivity.class )
                .create()
                .resume()
                .get();
        username = loginActivity.findViewById(R.id.username);
        password = loginActivity.findViewById(R.id.password);
        statusText = loginActivity.findViewById(R.id.statusText);
    }

    @Test
    public void whenUsernameEmptyShouldPresentEmptyError(){
        //set up condition for test
        username.setText("");
        password.setText("123456");

        //Execute the code under test
        loginActivity.findViewById(R.id.loginButton).performClick();

        //Make assertions on the result
        assertEquals(statusText.getText().toString(),"Username should not be Empty");
    }


    @Test
    public void whenPasswordEmptyShouldPresentEmptyError(){

        username.setText("abc12345");
        password.setText("");

        //Execute the code under test
        loginActivity.findViewById(R.id.loginButton).performClick();

        assertEquals(statusText.getText().toString(),"Password should not be Empty");
    }

}

Вот что я получаю при запуске теста:

java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked. See http://g.co/androidstudio/not-mocked for details.

    at android.os.Looper.getMainLooper(Looper.java)
    at org.robolectric.android.controller.ComponentController.<init>(ComponentController.java:30)
    at org.robolectric.android.controller.ComponentController.<init>(ComponentController.java:22)
    at org.robolectric.android.controller.ActivityController.<init>(ActivityController.java:65)
    at org.robolectric.android.controller.ActivityController.of(ActivityController.java:56)
    at org.robolectric.Robolectric.buildActivity(Robolectric.java:89)
    at org.robolectric.Robolectric.buildActivity(Robolectric.java:75)
    at upuphere.com.githubcdci.LoginActivityUnitTest.setUp(LoginActivityUnitTest.java:22)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

Вопрос:

  1. assertEqual(), assertThat(): Значит ли это, что «это результат, которого я ожидаю, я хочу, чтобы это произошло»?
  2. Когда использовать assertEqual() и assertThat()? Это нормально, я использую

    assertThat(statusText.getText().toString(),equalTo("Username should not be Empty")); в случае выше?

  3. Что я делаю не так, чтобы я получил вышеупомянутую ошибку? Как ее решить?

Если возможно, пожалуйста, дайте мне правильный пример модульного теста для случая, который я перечислил выше. Спасибо заранее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...