通过测试进行开发:提高技能

测试是每个开发人员应具备的一项重要技能。 但是,有些人不愿意这样做。

我们每个人都遇到了一个开发人员,该开发人员声称测试是无用的,需要太多的精力,而实际上他的代码是如此出色,以至于不需要测试。 不要相信。 测试至关重要。

图片

测试可以使您的代码更稳定,并减少错误数量。 在您看来,事实并非如此,因为您了解代码的每一点。 毕竟,您编写了它,为什么还要进行测试?

假设您正在创建一个天气应用程序。 您编写了几天或几周的代码,因此您知道了往返的代码。

现在,假设您已经完成了该应用程序的工作,并将在几个月后返回。 您将不会记住旧代码的每个细节。 您更改它……地狱……某些东西坏了。 您如何解决这个问题? 查看您创建的每个文件并将其配置为可以再次使用吗? 它可能会起作用。 但是更改此文件将破坏其他内容。

再举一个例子。 经过几个月的努力,您终于获得了您长期以来想要的职位! 您加入团队并开始创造一些东西。 您可以使用其他开发人员的代码,反之亦然。 有一天,一切都崩溃了。 如果团队尚未将测试集成到他们的应用程序中,那么我不会羡慕您。

每个团队在创建软件或应用程序时必须编写测试。 您不想成为一个不知道如何测试的人?

是的,编写测试需要时间。 是的,一开始很难。 是的,创建应用程序更有趣。 但是测试很重要,如果正确实施,可以节省时间。

我今天的目标是提高测试技能。 我们将通过使用Jest(JavaScript测试工具)进行测试来研究单元测试和开发。 当然,您还可以使用其他测试工具,例如Mocha和Chai。

让我们开始吧!

单元测试


当您决定测试应用程序时,您会面临各种类型的测试:单元测试(单元),集成测试和功能测试。 让我们关注单元测试。

功能测试和集成测试同样重要,但是它们比单元测试更难以配置和实现。 简而言之,单元测试包括测试代码的一小部分:函数,类方法等。您将数据提交到输入并确认您已收到预期的结果。

单元测试的好处:

  • 使代码更稳定;
  • 在不改变功能行为的情况下促进功能实现的更改;
  • 记录您的代码。 您很快就会明白原因。
  • 使您进行正确的设计。 确实,设计不良的代码通常更难测试。

测试开发(TDD)

要通过测试理解和使用开发,请记住以下两个规则:

  1. 在编写代码之前,编写一个失败的测试。
  2. 然后编写可以通过测试的代码。

当使用TDD时,我们正在谈论的是“红色,绿色,重构”循环。

红色:您编写失败的测试而没有编写代码。

绿色:编写可以通过测试的最简单的代码。 即使代码对您来说似乎最愚蠢。

重构:必要时进行代码重构。 如果您更改了代码,并且如果出现问题,则单元测试会中断,请不要担心。

构建测试文件


Jest提供了用于构造测试的功能:

describe:用于对测试进行分组并描述函数/模块/类的行为。 它有两个参数。 第一行描述您的小组。 第二个是回调函数,其中包含测试用例或挂钩函数。

还是测试:您的单元测试。 参数与描述相同。 必须是描述性的。 测试的名称由您决定,但您可以从“应该”开始。

beforeAll(afterAll):钩子函数在所有测试之前(和之后)运行。 它带有一个参数,该参数是您将在所有测试之前(和之后)运行的功能。

beforeEach(afterEach):在每个测试之前(和之后)执行的挂钩函数。 它带有一个参数,该参数是您在每次测试之前(和之后)运行的功能。

在编写任何测试之前,您应该了解以下内容:

您可以在describe及其上使用.skip跳过测试: it.skip(...)describe.skip(...) 。 使用.skip ,您告诉Jest忽略测试或组。

您可以在describe及其上使用.only来选择要运行的测试: it.only(...)describe.only(...) 。 如果您有很多测试,并且只想专注于一件事或想“调试”测试,则此功能很有用。

开玩笑的设置


为了向您展示我们上面检查的测试功能,我们需要配置Jest。 这很简单。

您只需要Node.js和npm或Yarn。 确保您使用的是最新版本的Node.js,因为我们将使用ES6。 创建一个新目录并对其进行初始化。

mkdir test-example && cd test-example npm init -y # OR yarn init -y 

-y对所有npm或yarn问题回答“是”。 他必须创建一个非常简单的package.json文件。

然后将Jest添加到您的开发环境中。

 yarn add jest --dev 

然后将以下脚本添加到package.json中

 "scripts": { "test": "jest" } 

yarn test将在目录中运行您的测试文件。 默认情况下,Jest会识别__tests__目录内的文件或以.spec.js或.test.js结尾的文件。

仅此而已。 您准备好编写第一个测试了吗?

匹配器(样本)


当您检查某项内容时,需要输入和预期结果。 这就是为什么Jest提供样本来测试我们的价值的原因:

 expect(input).matcher(output) 

笑话有很多样本,这是最重要的:

toBe:比较严格相等(===)。

 expect(1 + 1).toBe(2) let testsAreEssential = true expect(testAreEssential).toBe(true) 

toEqual:比较两个变量,数组或对象之间的值。

 let arr = [1, 2] arr.push(3) expect(arr).toEqual([1, 2, 3]) let x= 1 x++ expect(x).toEqual(2) 

toBeTruthy(toBeFalsy):指示值是否为true(或false)。

 expect(null).toBeFalsy() expect(undefined).toBeFalsy() expect(false).toBeFalsy() expect("Hello world").toBeTruthy() expect({foo: 'bar'}).toBeTruthy() 

toContain:检查数组是否包含元素。

 expect(['Apple', 'Banana', 'Strawberry']).toContain('Apple') 

toThrow:检查函数是否引起错误。

 function connect () { throw new ConnectionError() } expect(connect).toThrow(ConnectionError) 

初试


现在,我们将编写第一个测试并使用我们的功能。 首先在目录中创建一个example.spec.js文件,然后粘贴以下内容:

 describe('Example', () => { beforeAll(() => { console.log('running before all tests') }) afterAll(() => { console.log('running after all tests') }) beforeEach(() => { console.log('running before each test') }) afterEach(() => { console.log('running after each test') }) it('Should do something', () => { console.log('first test') }) it('Should do something else', () => { console.log('second test') }) }) 

请注意,我们不需要导入所有使用的功能。 它们已经由Jest提供。

运行纱线测试

图片

由于您在测试中没有语句,因此它们将通过。 您是否看到过不同的console.log说明? 您需要更好地了解功能和测试用例的工作方式。

现在删除所有钩子函数,并将.skip添加到第一个测试中:

 describe('Example', () => { it.skip('Should do something', () => { console.log('first test') }) it('Should do something else', () => { console.log('second test') }) }) 

再次运行纱线测试

图片

如果第一个测试不起作用,也可以。

添加第三项测试并使用.only

 describe('Example', () => { it('Should do something', () => { console.log('first test') }) it('Should do something else', () => { console.log('second test') }) it.only('Should do that', () => { console.log('third test') }) }) 

再次运行纱线测试

图片

在本文的第二部分,我们将使用TDD在JavaScript中对堆栈进行简单的实现。

Source: https://habr.com/ru/post/zh-CN430128/


All Articles