テストは、開発者の生活に欠かせないものです。テストされたコードは保守が容易であり、テストはドキュメントとしてもよく使用されます。
Kotlin を使用している場合は、以前に多くのテストを作成したことがあると思いますが、Kotlin Playground で試したことはありますか?
この記事では、Kotlin Playground を使用してコードをテストする方法を示します。Call of Duty Warzone 2 エラーコード Diver を修正する方法? また、非同期コードを簡素化するために使用できる高度なコルーチンの概念についても紹介します。
一足先:
Kotlin プレイグラウンドとは何ですか?
遊び場への入場
高度な Kotlin コルーチンについて学ぶ
高度なコルーチンのテスト 通常のサスペンド機能のテスト スイッチ/インジェクションのテスト スケジューラのテスト スタートアップのテストPUBG が起動時にクラッシュし続けるのはなぜですか? pubg 起動した途端クラッシュする 修正方法/ 非同期テスト作業 / スーパーバイザ作業 テスト工程
テストを改善するための戦略 CoroutineScope の名前付けは、コルーチンのベスト プラクティスに従います
Kotlin プレイグラウンドとは何ですか?
何かをテストする簡単な方法が必要な場合があります。Dropbox エラー 404 を修正するにはどうすればよいですか? ただし、Android Studio やその他のコード エディターを開くには時間がかかります。自分のアイデアをすばやくテストする方法があるとしたら? それが Kotlin Playground のすべてです。
Playground は、Kotlin コードを実行できるエディターであり、MicrosoftTeams エラー コード 4c7 を修正する方法と、最も重要なこととして、ブラウザーで実行できます。JetBrains によって開発および保守されています。Steam ストアをクリックしても反応しない場合はどうすればよいですか? Steam ストア ボタンが機能しない問題を修正する方法アクセスするには、play.kotlinlang.orgに移動します。
Kotlin Playground には、すべての標準の Kotlin ライブラリ (コレクション、リフレクション、コルーチンなど) が付属していますが、新しいライブラリの追加はサポートされていません。つまり、標準の Kotlin ライブラリに依存するもののプロトタイピングまたはテストにのみ使用できます。
Kotlin Playground の優れた機能は、作成したコードを他のユーザーと簡単に共有できることです。Robloxエラーコード529を修正するには? robloxエラーコード279 何が起こっているのかページのURLをコピーして他の人に送信するか、「コードを共有」ボタンを使用して埋め込み可能なバージョンのコードを取得してください。
Kotlin Playground にも隠し機能があります。Ctrl (Windows) または Command (Mac) キーを押しながらクリックすると、さらにカーソルが作成されます。Zoomアカウント無効エラーを修正するには? Zoom アカウントがロックされている解決策同時に複数行のコードを編集する必要がある場合、これは非常に便利です。
2022 年 5 月の時点で、Playground はモバイル デバイスもサポートしているため、Kotlin コードを実行するためにコンピューターも必要ありません。また、Kotlin のバージョンを選択できるアクション ツールバーも追加されました。xbox 申し訳ありませんが、ゲーム パスを表示できません。なぜですか? ゲームパスの修正方法が表示されず、コンパイラを選択してプログラムパラメータを設定できません。
遊び場への入場
Playground でコードを実行するためにWindows 10 マウスのダブルクリックを修正する方法は? Win10 マウスがダブルクリックになり、コールバックの方法が変わります。メイン メソッドを作成する必要があります。そうしないと、「プロジェクトにメイン メソッドが見つかりません」というエラーが発生します。
在本教程中,我将使用 Kotlin v1.7.21 和 JVM 编译器。如何修复RPC服务器在Windows10上不可用?rpc服务器不可用 win10解决方法请务必将以下导入添加到文件顶部:
import kotlin.test.*
import kotlinx.coroutines.*
这样做之后你应该有一个看起来像这样的游乐场:
如果您按下紫色的运行按钮,代码应该可以编译,您应该看不到任何错误。
了解高级 Kotlin 协程
在我们深入测试之前,让我们回顾一下Kotlin 协程的一些概念。
CoroutineContext是协程的重要组成部分,window11怎么返回window10?win11回退到win10教程它定义了协程的行为方式,并具有四个共同元素:
Job:控制协程的生命周期;此元素默认为 a,但您也可以指定Job SupervisorJob
CoroutineDispatcher:定义协程应该在哪个线程组中执行;大多数时候你会使用Main或IO调度员
CoroutineExceptionHandler: 定义未捕获的异常应该发生什么
CoroutineName: 为协程定义一个名称(本文后面会详细介绍)
如果您使用过withContextscope 函数,如何修复Valorant错误代码62?您可能想知道它的性能。如果您有很长的操作链,并且其中许多操作用于withContext确保工作在正确的线程中执行,这不会增加很大的性能开销吗?
如果我们看一下它的实现,我们会发现有两条快速路径。第一个将当前上下文与新上下文进行比较。如果它们相同,则无需更改线程。如何修复Windows错误0x80070015Windows?10种方法轻松解决第二条路径比较调度程序。如果它们相同,则也无需更改线程。
因此,如果调度程序相同,修复 Windows 更新失败并出现错误 0x80242016方法我们就不必担心线程,开销很小。
流是价值流。如果您需要合并它们,可以使用一个简洁的操作符,该combine操作符允许您根据需要合并任意数量的流。这是它最简单的签名:
fun <T1, T2, R> Flow<T1>.combine(flow: Flow<T2>, transform: suspend (T1, T2) -> R): Flow<R>
假设您有flowA并且flowB想要合并它们。电脑蓝光过滤软件有那些?护眼模式中的蓝光过滤怎么选为此,请使用以下代码:
flowA.combine(flowB) { a, b ->
// combine them and emit a new value
}
或者,您可以使用上述代码的顶级版本:
combine(flowA, flowB) { a, b ->
// combine them and emit a new value
}
测试高级协程
现在,让我们继续进行测试。我们将了解如何测试正常suspend功能、如何切换/注入测试调度程序以及如何测试launch/ async、Job/SupervisorJob和流。
测试正常suspend功能
让我们从定义一个suspend函数开始,这样我们就有了一些东西来编写我们的测试。假设我们有一个函数返回是否启用了某个功能:
suspend fun isEnabled(): Boolean {
delay(1_000)
return true
}
现在,让我们在 main 函数中编写我们的测试。assertTrue由提供并断言我们传入的变量是;否则,它会抛出异常:kotlin.testtrue
fun main() {
runBlocking {
val result = isEnabled()
assertTrue(result)
}
}
如果我们运行这段代码,我们将不会得到任何输出,因为测试通过了,但如果我们更改isEnabled为返回false,我们将得到以下错误:
Exception in thread "main" java.lang.AssertionError: Expected value to be true.
如果您想向 中添加自定义消息assertTrue,请使用以下命令:
assertTrue(result, "result should be true but wasn't")
这将导致以下输出:
Exception in thread "DefaultDispatcher-worker-1 @coroutine#1" java.lang.AssertionError: result should be true but wasn't
切换/注入测试调度程序
在您的代码中硬编码调度程序不是好的做法。只要有可能,您应该接受调度程序作为您的类中的参数。
看看下面的代码:
class Database {
private val scope = CoroutineScope(Dispatchers.IO)
fun saveToDisk() {
scope.launch {
...
}
}
}
很难测试这个。为了使事情更简单,我们可以将其更改如下:
class Database(private val scope: CoroutineScope) {
fun saveToDisk() {
scope.launch {
...
}
}
}
这样,可以在测试期间注入作用域。
测试launch/async
launch并且async可能是 中最常用的功能之一Compose,尤其是对于 Android 开发人员而言。那么,我们如何测试它们呢?
让我们从定义一个保存一些状态的简单函数开始。您不能调用suspend函数,因为您的 Activity 或 Fragment 中没有作用域。但是,使用协程可以帮助您避免阻塞主线程,这可能会在您将内容保存到后端时发生:
private val scope = CoroutineScope(Dispatchers.IO)
fun saveState() {
scope.launch {
// save state to backend, disk, ...
}
}
鉴于我们没有数据库或服务器,让我们创建一个变量来假装我们做了一些事情:
private val state: Any? = null
fun saveState() {
scope.launch {
state = "application state"
}
}
现在我们有了可测试的东西,让我们来编写我们的测试:
fun main() {
runBlocking {
saveState()
assertNotNull(state)
}
}
这应该有效,对吧?好吧,如果我们运行这段代码,我们会得到一个错误提示stateis null。这段代码的问题是它在调用saveState但没有等待它执行,所以我们在操作完成之前检查结果。
要解决这个问题,我们可以在检查之前简单地添加一个小延迟state,如下所示:
fun main() {
runBlocking {
saveState()
delay(100)
assertNotNull(state)
}
}
这样,saveState在我们检查变量之前就有时间执行。但是,使用它delay来测试您的代码并不是最佳做法。为什么是 100 毫秒而不是 200 毫秒?如果代码执行时间超过 100 毫秒怎么办?这就是为什么我们应该避免这种做法。在本文的稍后部分,我将向您展示一种更好的测试方法。
测试async是一个类似的过程;让我们修改saveState它使用async:
fun saveState() {
scope.launch {
async { state = "application state" }.await()
}
}
fun main() {
runBlocking {
saveState()
delay(100)
assertNotNull(state)
}
}
现在,运行这段代码;您会看到它按预期工作。
测试Job/SupervisorJob
接下来,让我们探讨一下如何测试Jobs. 如果您使用它,GlobalScope则很难测试您的代码,因为您无法替换或模拟它。此外,由于您无法取消GlobalScope使用它,因此您基本上失去了对工作的控制。相反,我们将为我们的测试定义一个自定义范围,如果需要我们可以控制它:
private val scope = CoroutineScope(Dispatchers.Default)
我们可以定义一个变量来跟踪Job并修改saveState以将结果分配launch给该变量:
private var job: Job? = null
private var state: Any? = null
fun saveState() {
job = scope.launch {
println("application state")
}
}
现在,在主函数中我们可以测试saveState函数:
fun main() {
runBlocking {
saveState()
job?.join()
assertNotNull(state)
}
}
运行这个,你不应该得到任何错误。
你可能会问,“为什么我们需要使用join?” 嗯,调用launch不会阻塞代码执行,所以我们需要使用join来防止main函数退出。
现在我们知道如何测试 a Job,让我们学习如何测试 a SupervisorJob。
ASupervisorJob类似于 a Job,除了它的子节点可以彼此独立地失败。让我们首先更改我们的范围以拥有一个 SupervisorJob:
val scope = CoroutineScope(SupervisorJob())
现在在我们的 main 函数中,让我们添加另一个只launch抛出错误的函数:
fun main() {
runBlocking {
scope.launch { throw error("launch1") }.join()
saveState().join()
assertNotNull(state)
}
}
运行它,你会在输出中看到一个错误。那么,不应该SupervisorJob阻止它吗?如果我们更详细地分析它,我们会发现它实际上确实阻止了错误的冒泡,但它并没有阻止它被记录下来。如果你println在断言下面添加一个语句,你会看到它实际上被打印出来了;因此,即使第一个launch抛出错误,第二个也能运行。
测试流程
为了测试流程,我们将从添加一个新的导入开始:
import kotlinx.coroutines.flow.*
observeData接下来,让我们创建一个仅返回流的函数:
fun observeData(): Flow<String> {
return flowOf("a", "b", "c")
}
现在,在我们的 main 方法中,我们可以使用 assertEquals 函数来比较期望值和实际值:
suspend fun main() = runBlocking<Unit> {
val expected = listOf("a", "b", "c")
assertEquals(expected, observeData().toList())
}
改进测试的策略
现在我们对如何测试高级协程有了更好的了解,让我们看看一些使协程测试和调试更容易的策略。
命名你的CoroutineScope
如果你有很多协程范围,调试它们可能会很困难,因为它们都使用类似于@coroutine#1、@coroutine#2 等的命名约定。
为了使调试更容易,我们可以添加到,如下所示:CoroutineName(...)CoroutineScope
private val scope = CoroutineScope(Dispatchers.Default + CoroutineName("database"))
如果在该范围内出现问题,我们将收到如下错误:
Exception in thread "DefaultDispatcher-worker-1 @database#2" java.lang.IllegalStateException: …
遵循协程最佳实践
为了使测试更容易,请遵循以下协程最佳实践:
将调度程序注入您的类:避免在您的类中对调度程序进行硬编码。注入它通过允许您替换它们来简化测试
避免GlobalScope:它使测试变得非常困难,这本身就是避免它的一个很好的理由。它还使控制作业的生命周期变得更加困难
结论
在本文中,我们探讨了如何使用 Kotlin Playground 来测试协程。我们还研究了一些协程概念,例如CoroutineContext和Flow。最后,我们讨论了一些使测试更容易的策略。
现在轮到你了; 学习东西的最好方法是练习。下次见!