对于任何一个开发人员来说,测试必然是不可缺少的一部分。以前开发都是直接run代码到模拟器或者实体机上面进行实体测试,虽然说这样的测试,可以更加直观的看出问题。但是进行单元测试的话,需要较大的代码量来写测试用例,而且实体测试耗时更长,费时费力。所以想要学习如何更高效的进行代码测试。
稍微了解了一下(看了半天的样子吧,这篇文章只是为了暂时记录一下遇到的坑,而不是个全方位系统的介绍,所以如果有错或者需要补充的地方请在评论区指出),测试大致分为三类:
向app的build.gradle中加入
android {
testOptions {
unitTests {
includeAndroidResources = true
}
}
}
dependencies {
testImplementation 'junit:junit:4.12'
testImplementation 'org.robolectric:robolectric:4.2.1'
testImplementation 'androidx.test:core:1.2.0'
}
这里写了两个Activity,在MainActivity里面使用一个TextView,点击TextView跳转到SecondActivity
1.MainActivity
package com.example.androidtestlearning
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tv_turn_new_activity.setOnClickListener {
startActivity(Intent(this,SecondActivity::class.java))
}
}
}
2.SecondActivity(就是一个空的什么都没写的activity)
package com.example.androidtestlearning
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class SecondActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
}
}
用来测试是否点击了MainActivity里的tv_turn_new_activity能跳转到SecondActivity
package com.example.androidtestlearning
import android.content.Intent
import androidx.test.core.app.ActivityScenario
import org.junit.Assert.*
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import kotlinx.android.synthetic.main.activity_main.*
import org.robolectric.Shadows
@RunWith(RobolectricTestRunner::class)
class MainActivityTest {
@Test
@Throws(Exception::class)
fun clickText() {
val scenario = ActivityScenario.launch(
MainActivity::class.java
)
scenario.onActivity { activity ->
//点击tv
activity.tv_turn_new_activity.performClick()
//预期的Intent
val expectedIntent = Intent(activity, SecondActivity::class.java)
//用来获取MainActivity对应的ShadowActivity的instance
val shadowActivity = Shadows.shadowOf(activity)
//实际获得的Intent
val actualIntent = shadowActivity.nextStartedActivity
//判断两个Intent是否一样
assertEquals(expectedIntent, actualIntent)
}
}
}
旧的资料使用Robolectric.setupActivity(MainActivity.class); 来获取activity,然后发现setupActivity方法已经被弃用了,文档上写的
Use {@link androidx.test.core.app.ActivityScenario} instead, which works with instrumentation tests too.
于是就直接跳转到ActivityScenario类里去看,是这样推荐使用的
* {@code
* Before:
* MyActivity activity = Robolectric.setupActivity(MyActivity.class);
* assertThat(activity.getSomething()).isEqualTo("something");
*
* After:
* try(ActivityScenario scenario = ActivityScenario.launch(MyActivity.class)) {
* scenario.onActivity(activity -> {
* assertThat(activity.getSomething()).isEqualTo("something");
* });
* }
那么我就直接把这一段代码ctrl+c ctrl+v了上去,然后发现找不到ActivityScenario。我就google了一下,android developer是这样配置的gradle
dependencies {
// Core library
androidTestImplementation 'androidx.test:core:1.0.0'
// AndroidJUnitRunner and JUnit Rules
androidTestImplementation 'androidx.test:runner:1.1.0'
androidTestImplementation 'androidx.test:rules:1.1.0'
// Assertions
androidTestImplementation 'androidx.test.ext:junit:1.0.0'
androidTestImplementation 'androidx.test.ext:truth:1.0.0'
androidTestImplementation 'com.google.truth:truth:0.42'
// Espresso dependencies
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-accessibility:3.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-web:3.1.0'
androidTestImplementation 'androidx.test.espresso.idling:idling-concurrent:3.1.0'
// The following Espresso dependency can be either "implementation"
// or "androidTestImplementation", depending on whether you want the
// dependency to appear on your APK's compile classpath or the test APK
// classpath.
androidTestImplementation 'androidx.test.espresso:espresso-idling-resource:3.1.0'
}
然后发现这样添加之后还是找不到ActivityScenario,我的测试类是写在test文件夹而不是androidtest里面的。而androidTestImplementation是为androidTest里面的文件所依赖的,所以改为testImplementation,即可找到此类。
我之前根据资料没有添加这几行代码
android {
testOptions {
unitTests {
includeAndroidResources = true
}
}
}
导致一直报错
No such manifest file: .\AndroidManifest.xml
虽然我的程序运行没有错误了,但是它的expectedIntent和actualIntent判断出来不一样emmmm我也不知道为什么(有大佬知道的话,能告诉我是为什么吗)
java.lang.AssertionError: expected: android.content.Intent but was: android.content.Intent
Expected :android.content.Intent
Actual :android.content.Intent