测试JavaScript UIs的5个基本技巧

121 阅读5分钟

当涉及到为(JavaScript)用户界面编写测试时,你要么喜欢,要么不喜欢。但是,如果你所在的公司要求有一定的测试覆盖率门槛,或者你希望有逻辑覆盖,你最终还是要做。不管你是什么情况,我相信下面的五个提示会帮助你写出更好的测试。

刚开始的时候,我在写测试方面挣扎了很久。这个概念很简单--你写的代码可以验证你写的其他代码。但是,那时候有些不对劲,我一开始并不太喜欢。几年后的今天,我对写测试已经没有问题了。我有了自己的想法。这些是我发现在日常的UI测试中最有用的技巧。

1.测试行为,而不是实现

对于一些人来说,遵循测试UI行为而不是实现的原则可能是很自然的。但相信我,有时在测试代码的深处,你可能会失去这个想法,并试图黑掉你的测试方式。

如果你熟悉测试驱动开发(TDD),也有行为驱动开发(BDD).这个想法是使用一个DSL(特定领域的语言)来创建一个脚本,几乎项目中的每个人都能理解。在很长一段时间里,主要的工具是Cucumber(库,不是蔬菜)。它可以让你形成一个这样的测试脚本。

功能。将物品放入购物车 场景。打破者加入游戏 考虑到用户已经访问了令人敬畏的购物页面 当用户向购物车添加物品时 那么用户应该在购物车中看到该物品

这个想法很简单,实现时使用的是小黄瓜语法中的 "Given"、"When "和 "Then "格式。像这样的脚本是为了让利益相关者阅读并理解其功能和场景,但我很少看到他们在实践中阅读这些脚本。

总之,如果你不喜欢这样的工具,你可以跳过使用它(咄),但要记住,你应该测试行为。

2.一次测试一件事

几年前我给自己的一个很好的建议是,在一个测试中专注于测试一件事。我曾经在一个测试中测试过很多不同的东西。Cypress框架的一个好处是,他们建议只测试一次登录功能,在所有其他测试中以编程方式登录。

因此,假设你正在测试向购物车添加一个项目。理想情况下,如果你在测试中专注于这一块UI功能,那将是最好的。所有其他的事情,比如:

  • 登录
  • 为要添加到卡上的物品播种
  • 发布用户购买物品的商店

都应该是设置的一部分。你不应该在测试中直接做所有这些事情,而应该只关注用户将物品添加到购物车中的动作。

3.合理安排测试结构

另一件能让你在测试中获得成功的事情是遵循AAA模式。AAA代表以下内容:

  • 第一个A--安排:放置和执行一切需要为即将测试的功能设置的测试。种子数据,登录用户,存根调用,等等。
  • 第二个A--行动:执行动作,如添加一个项目到购物车。
  • 第三个A--断言:确保收到的值满足期望。确保测试验证了预期的行为。

继续,并在你的下一个测试中尝试。

4.使用助手来生成测试数据

通常,你会面临同样的问题--在测试中创建特定的数据对象。无论是产品、用户、随机项目,你都必须在测试设置中以某种方式创建对象。有一种软件设计模式可以帮助你解决这个问题,那就是工厂模式

一个可以帮助我们生成对象的库是Fishery库。如果你使用TypeScript,这两者可以完美地结合起来。比方说,我们想在测试中生成一个用户。一种方法是这样做的:

// factories/user.ts

import { Factory } from "fishery"
import { User } from "../my-types"
import postFactory from "./post"

export const userFactory = Factory.define<User>(({ sequence }) => ({
  id: sequence,
  name: "Rosa",
  address: { city: "Austin", state: "TX", country: "USA" },
  posts: postFactory.buildList(2),
}))

然后,我们可以像这样不慌不忙地创建用户:

const user = userFactory.build({ name: "Sandra" })

你现在应该有更精确的测试,因为你可以生成对象而不需要指定所有的属性,只需要指定与你正在编写的当前测试相关的属性。另外,用户工厂的定义在一个地方,你可以很容易地从那里编辑它,当一些属性改变时,不需要去看你所有的测试。

5.避免睡觉(在测试中)

我们都经历过这样的情况,设置一些超时来处理一个异步测试案例或强制下一个tick。有了新的工具,你就不需要这样做了。如果你要测试一些异步代码,你可以用Jest来测试:

test("the data is peanut butter", async () => {
  const data = await fetchData()
  expect(data).toBe("peanut butter")
})

有了简单的async / await语法,就不再需要setTimeout了。或者,更好的是,如果你使用Cypress,他们有一个集成的等待机制,会给每个命令执行一定的时间。另外,在testing-library中,你可以像其文档中描述的那样做waitFor

总之,无论你做什么,在你调用setTimeout 或任何其他与时间有关的方法之前,请三思而后行,因为这将使你的测试不那么可读,而且可能是摇摆不定。

总结

谢谢你阅读这五个提示。我希望你在阅读后获得一些启发。同时,我希望这些能帮助你为你的JavaScript应用程序写出更好的UI测试。