既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
Hamcrest
语义化
// 导入 Hamcrest
// testImplementation ‘org.hamcrest:hamcrest-all:1.3’
class StatisticsUtilsKtTest : TestCase() {
@Test
fun testGetActiveAndCompletedStats() {
val tasks = listOf(
Task(“title”, “desc”, isCompleted = false)
)
val result = getActiveAndCompletedStats(tasks)
assertThat(result.completedTasksPercent, is
(0f))
assertThat(result.activeTasksPercent, is
(100f))
}
}
Room 测试
@RunWith(AndroidJUnit4::class)
class WordDaoTest {
private lateinit var database: AppDataBase
private lateinit var wordDao: WordDao
private val word1 = Word(“hello”)
private val word2 = Word(“world”)
@get:Rule
var instantTaskExecutorRule = InstantTaskExecutorRule()
@Before
fun createDb() = runBlocking {
val context = InstrumentationRegistry.getInstrumentation().targetContext
database = Room.inMemoryDatabaseBuilder(context, AppDataBase::class.java).build()
wordDao = database.wordDao()
wordDao.insertAll(listOf(word1, word2))
}
@After
fun closeDb() {
database.close()
}
@Test
fun testGetAlphabetizedWords() = runBlocking {
val wordList = wordDao.getAlphabetizedWords().first()
Assert.assertThat(wordList.size, CoreMatchers.equalTo(2))
Assert.assertThat(wordList[0], CoreMatchers.equalTo(word1))
Assert.assertThat(wordList[1], CoreMatchers.equalTo(word2))
}
@Test
fun testDeleteAll() = runBlocking {
wordDao.deleteAll()
val wordList = wordDao.getAlphabetizedWords().first()
Assert.assertThat(wordList.size, CoreMatchers.equalTo(0))
}
}
ViewModel 测试
ViewModel
没有参数时,可以直接实例化,ViewModel
有参数时可以参考Hilt
@RunWith(AndroidJUnit4::class)
class HomeViewModelTest {
private lateinit var viewModel: HomeViewModel
private val coroutineRule = MainCoroutineRule()
private val instantTaskExecutorRule = InstantTaskExecutorRule()
@get:Rule
val rule = RuleChain
.outerRule(instantTaskExecutorRule)
.around(coroutineRule)
@Before
fun setUp() {
viewModel = HomeViewModel()
}
@Test
fun testDefaultValues() = coroutineRule.runBlockingTest {
viewModel.updateTaps()
val value = viewModel.userName.getOrAwaitValue()
assertThat(value, is
(“aa bb”))
}
}
- 这里主要是观测
LiveData
的变化,所以可用协程的通道来实现数据的观察
// 官方代码
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
fun LiveData.getOrAwaitValue(
time: Long = 2,
timeUnit: TimeUnit = TimeUnit.SECONDS,
afterObserve: () -> Unit = {}
): T {
var data: T? = null
val latch = CountDownLatch(1) // 一次计数
val observer = object : Observer {
override fun onChanged(o: T?) {
data = o
latch.countDown()
this@getOrAwaitValue.removeObserver(this)
}
}
this.observeForever(observer)
try {
afterObserve.invoke()
// Don’t wait indefinitely if the LiveData is not set.
if (!latch.await(time, timeUnit)) {
throw TimeoutException(“LiveData value was never set.”)
}
} finally {
this.removeObserver(observer)
}
@Suppress(“UNCHECKED_CAST”)
return data as T
}
Hilt 测试
- 有一点需要注意的是,
Hilt
需要提供Application
,所以这里可以自定义一个AndroidJUnitRunner
,作为测试的启动项
class MainTestRunner : AndroidJUnitRunner() {
override fun newApplication(cl: ClassLoader?, name: String?, context: Context?): Application {
return super.newApplication(cl, HiltTestApplication::class.java.name, context)
}
}
- 在
module
的build.gradle
文件当中修改testInstrumentationRunner
defaultConfig {
…
testInstrumentationRunner “com.huang.myapplication.MainTestRunner”
…
}
- 用
@HiltAndroidTest
注解测试类
@HiltAndroidTest
class MainViewModelTest {
private lateinit var viewModel: MainViewModel
private val hiltRule = HiltAndroidRule(this)
private val instantTaskExecutorRule = InstantTaskExecutorRule()
private val coroutineRule = MainCoroutineRule()
@get:Rule
val rule = RuleChain
.outerRule(hiltRule)
.around(instantTaskExecutorRule)
.around(coroutineRule)
@Inject
lateinit var repo: WordRepository
@Inject
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
止,不再深入研究,那么很难做到真正的技术提升。**
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!