收益:
- 能够根据测试金字塔使用人工智能生成单元、集成和 UI 测试,并涵盖限制和错误情况以及满意的场景
- 能够通过检查生成的每个测试是否实际验证行为来清除空/无用的测试和臃肿的覆盖范围
- 通过告诉 AI 代码应该做什么来确保测试捕获错误并防止其修复错误
写代码只是工作的一半;证明代码正确工作是另一半。移动应用程序会遇到数百种不同的设备、屏幕尺寸、操作系统版本和用户行为。手动测试所有这些是不可能的;这就是为什么自动化测试(代码测试代码——无需人工点击即可运行的测试)是移动质量的支柱。人工智能在编写测试方面非常高效,因为编写测试正是它喜欢的模式工作:验证特定输入的特定行为。在本单元中,我们将学习如何利用人工智能加速单元测试、接口测试和自动化,同时通过人眼确保测试质量。
测试金字塔:测试什么以及测试多少
健康的测试策略类似于金字塔。基础包括大量的单元测试(独立测试单个函数或类的快速测试);它们又快又便宜。中间是较少的集成测试(测试多个部分如何协同工作)。顶部有最少的 UI/端到端测试(通过像用户一样单击屏幕来完成测试);它们很现实,但缓慢而脆弱。人工智能在每一层都有帮助,但最大的价值在于基础:快速生成业务逻辑的单元测试。
测试类型
适用范围
速度
人工智能效率
单元测试
单一功能/类
非常快
非常高
整合
夹层
中等
高
用户界面/端到端
全屏流
慢
中等(易碎)
Tip: When telling the AI to "generate tests for this function", explicitly ask for edge cases: empty input, null, negative number, very large value, network error. AI轻松生成幸福路径;真正的错误隐藏在边界中,如果你不希望它们出现在那里,它们就会跳出来。
使用 AI 编写测试的步骤
- 定义要测试的行为。 “这个函数应该将这个输出提供给这个输入。”
- 指定框架。 Android 上的 JUnit + MockK、iOS 上的 XCTest、UI 上的 Espresso (Android) 或 XCUITest (iOS)。
- 询问极限状态。快乐的场景+错误+断点。
- 管理模拟对象。模拟网络和数据库等外部依赖项以进行测试(模拟 - 受控模拟而不是实际服务)。
- 运行测试并验证。测试是否通过,是否证实了任何真正有意义的事情?
第五步很关键。人工智能有时会产生“总是通过”的无用测试;例如,不验证任何内容或检查自己的虚假数据的测试。通过测试和有价值的测试是不同的事情。
注意:人工智能可以产生并不意味着测试是正确的。有时,人工智能会将代码当前(可能是错误的)行为视为“正确”,并相应地编写测试。此类测试修复错误而不是捕获错误。您确定测试的预期内容;告诉AI它应该做什么,而不是代码做什么。
测试覆盖率测量和谬误
测试覆盖率(测试运行的代码百分比)是一个有用但具有误导性的指标。 90%覆盖率表示90%的代码已经被执行;但尚未验证这些线路是否正常工作。运行一行但不检查结果的测试扩大了范围,但不提供安全性。目标不是高数字,而是有意义的验证。您可以利用人工智能快速扩展规模,但要确保每个测试都实际测试一种行为。
三个迷你箱子
案例一——边境局势被抓获。 AI was asked for tests for a money transfer function in a banking application, and specifically "negative amount" and "more than balance" scenarios were added.测试发现转账没有被负数阻塞;这将是生产中的一个主要安全漏洞。通过添加单行控件来关闭。教训:边界测试是最有价值的测试。
案例 2 — 假测试。通过 AI 生成的 40 个单元测试将覆盖率提高到 85%,令一个团队松了口气。在检查过程中发现,大多数测试实际上并没有验证任何输出,他们只是调用该函数并编写assertTrue(true)。覆盖率很高,但保护为零。通过真实验证对测试进行了彻底修改和重写。教训:覆盖率数字可能会撒谎。
案例 3 — UI 测试加速。电子商务团队在 20 分钟内用 AI 编写了添加到购物车流程的 XCUITest 脚本;如果是手写的话,需要半天的时间。 AI猜测屏幕元素标识符;团队将它们与真实代码进行匹配并修复。草稿速度是真实的,但标识符验证是人类的工作。
弱提示/强提示
弱提示:“为此函数编写一个测试。”
强有力的提示:“使用 JUnit5 + MockK 为这个 Kotlin 函数生成单元测试。功能:转账(金额、来源、目标)。要测试的行为(代码应该做什么):- 有效转账必须成功 - 负数或零金额必须被拒绝 - 大于余额的金额必须被拒绝 - 网络错误必须抛出适当的异常 每个测试应该仅验证一件事,其名称应该是描述性的,模拟外部服务。不要编写空断言。”
可复制模板
单元测试模板:“为 [语言] 的此函数生成 [JUnit/XCTest] 单元测试。预期行为:[做什么]。包括:快乐场景、空输入、断点、错误情况。让每个测试验证单个行为;使用有意义的断言;模拟。[代码]”
UI 测试模板:“使用 [Espresso/XCUITest] 编写以下流程的 UI 测试:[用户流程一步一步]。选择具有辅助功能 id 的屏幕元素,使用 id 而不是文本。添加等待策略。提醒我将元素 id 与实际代码相匹配。”
测试审核模板:“检查这些测试:1)它们是否确实验证了输出/行为还是为空?2)它们是否涵盖了极限情况?3)它们是否修复了代码错误或期望正确的行为?标记并加强弱测试。[测试]”
覆盖率优化模板:“识别此类中未经测试的部分并建议有意义的测试。优先考虑具有实际风险的路径,而不仅仅是覆盖率的数量。[代码]”
常见错误
- 只是测试快乐的场景。错误存储在极限状态中;公开询问他们。
- 接受空的/无用的测试。 assertTrue(true) 类型的测试扩大了范围并且不提供任何保护。
- 让人工智能验证代码在做什么。测试应该预期代码应该做什么;否则它会修复该错误。
- 将范围编号误用于目的。 90% coverage does not mean 90% accuracy.
- Linking to text in UI testing. The test is broken when the text changes; Use stable identifier (id).
- 模拟设置不正确。调用实际服务的“单元测试”将会缓慢且脆弱。
总之
测试是移动质量的支柱,人工智能在这方面非常高效,尤其是在单元测试方面。遵循测试金字塔:许多单元,中等集成,少量 UI 测试。明确向 AI 询问满意的场景以及极限情况和错误路径。确保生成的每个测试实际上验证了一种行为;空洞的测试和夸大的覆盖范围具有误导性。最重要的是,告诉 AI 代码应该做什么,而不是它做了什么,这样测试就会发现错误,而不是修复它。
应用任务
使用业务逻辑功能(例如折扣计算或表单验证)的“单元测试模板”向 AI 请求测试,并明确指定限制情况(空、负、太大)。运行生成的测试,然后使用“测试审核模板”审核相同的测试。找到至少一个弱测试,加强它,并测试测试是否捕获函数的实际错误(通过添加一个小错误)。
清单
- [ ] 我为测试金字塔选择了适当的层(优先单元)
- [ ] 除了快乐的场景之外,我还想要限制和错误情况
- [ ] 我验证每个测试都包含有意义的断言
- [ ] 我告诉人工智能代码应该做什么,而不是它做了什么
- [ ] 我关注的是实际风险路径,而不是承保范围的数量
- [ ] 我在 UI 测试中使用了稳定标识符,我没有绑定到文本