为什么端到端测试是你最好的朋友(以及如何在Kotlin中与它交朋友)
\n\n想象一下:你写了一个很棒的Kotlin服务,一切编译通过,单元测试全部通过,代码审查也完成了。你部署到生产环境,然后……用户抱怨“购买”按钮不工作,尽管单元测试已经测试过它。熟悉吗?欢迎来到一个Kotlin应用端到端测试不是奢侈品,而是必需品的世界。
\n\n端到端测试是对整个用户路径的检查:从点击按钮到数据库写入再返回。在本文中,我们不只是谈论理论。我们将为Kotlin应用编写真实的测试,分析各种工具,并展示如何在配置基础设施时保持理智。系好安全带,会有代码和咖啡。
\n\n什么是端到端测试,它与其他类型的测试有何不同
\n\n让我们立即澄清这一点。端到端测试从用户的角度全面检查系统。与以下测试不同:
\n\n- \n
- 单元测试——隔离地测试单个方法/类。 \n
- 集成测试——测试两到三个组件之间的交互(例如,控制器+服务)。 \n
- UI测试——经常与端到端测试混淆,但UI测试可能不检查后端,只检查界面渲染。 \n
Kotlin应用的端到端测试是一个完整的周期:用户界面(如果有)、API、业务逻辑、数据库、外部服务。所有部分必须像钟表一样协同工作。
\n\nKotlin端到端测试工具
\n\n工具的选择取决于你测试的内容:Android应用、Ktor Web服务还是桌面应用。以下是Kotlin开发者的首选:
\n\n- \n
- Selenide + Kotlin——用于Web界面。它是Selenium的封装,但语法简洁,非常适合Kotlin。 \n
- Ktor Client + TestContainers——用于后端。在Docker中启动测试基础设施(数据库、缓存)并发送HTTP请求。 \n
- Espresso + Compose Test——用于Android。随Android SDK提供的原生工具。 \n
- Cucumber + Kotlin——如果需要用客户能理解的语言编写BDD场景。 \n
我们将专注于前两个场景,因为它们最通用。
\n\n为Kotlin Web应用编写端到端测试(Selenide)
\n\n假设我们有一个基于Spring Boot + Kotlin的简单在线商店。我们需要测试一个场景:用户访问网站,将商品添加到购物车,并完成结账。
\n\n首先,在build.gradle.kts中添加依赖项:
dependencies {\n testImplementation("com.codeborne:selenide:6.19.1")\n testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")\n testImplementation("io.github.bonigarcia:webdrivermanager:5.6.2")\n}\n\n现在编写测试本身。请注意:我们使用Kotlin的扩展函数使代码更具可读性:
\n\nimport com.codeborne.selenide.Condition.visible\nimport com.codeborne.selenide.Selenide.`$`\nimport com.codeborne.selenide.Selenide.open\nimport org.junit.jupiter.api.BeforeEach\nimport org.junit.jupiter.api.Test\n\nclass ShopE2ETest {\n\n @BeforeEach\n fun setUp() {\n // 在每个测试之前打开浏览器\n open("https://test-shop.example.com")\n }\n\n @Test\n fun `user can add product to cart and checkout`() {\n // 步骤1:找到商品并添加到购物车\n `$`("[data-testid='product-1']").shouldBe(visible).click()\n `$`("[data-testid='add-to-cart']").click()\n\n // 步骤2:检查购物车不为空\n `$`("[data-testid='cart-badge']").shouldHave(text("1"))\n\n // 步骤3:前往结账\n `$`("[data-testid='checkout-btn']").click()\n\n // 步骤4:填写表单\n `$`("[