Я абсолютный новичок, когда прихожу на юнит-тест в Android и Robolecti c. Я пытаюсь написать простой модульный тест для взаимодействия моего пользовательского интерфейса, но я не могу понять, что считать правильным модульным тестом, а что нет.
Я смотрю это видео: Test-Driven Разработка на Android с Android библиотекой поддержки тестирования (Google I / O '17) . Исходя из моего понимания, модульный тест должен быть написан до написания реального кода, тогда код, который я пишу, должен удовлетворять только модульному тесту.
Поэтому вот что я хочу сделать:
- У меня есть действие с именем
LoginActivity
- Внутри
LoginActivity
содержится 2 EditText
с идентификатором username
и password
, кнопка с идентификатором loginButton
и a TextView
с идентификатором statusText
- При нажатии на
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)
Вопрос:
assertEqual()
, assertThat()
: Значит ли это, что «это результат, которого я ожидаю, я хочу, чтобы это произошло»? Когда использовать assertEqual()
и assertThat()
? Это нормально, я использую
assertThat(statusText.getText().toString(),equalTo("Username should not be Empty"));
в случае выше?
- Что я делаю не так, чтобы я получил вышеупомянутую ошибку? Как ее решить?
Если возможно, пожалуйста, дайте мне правильный пример модульного теста для случая, который я перечислил выше. Спасибо заранее.