使用Jest测试JavaScript代码以获取假人。第1部分

哈Ha!本指南是有关Jest这样的出色测试框架的计划文章系列的第一部分。该材料对于初学者和刚熟悉测试的人非常有用,并且他们想研究这个框架。在第一部分中,我们将分析:如何开始开玩笑,如何编写简单的测试以及有哪些方法将要检查的值与预期值进行比较。谁在乎-欢迎来到Kat!

什么是开玩笑?


如项目首页上所示:
Jest是一个了不起的JavaScript测试环境,着重于简单性。
实际上,Jest非常简单。它不需要其他设置,易于理解和使用,并且具有相当好的文档。非常适合使用Node,React,Angular,Vue,Babel,TypeScript等项目。
它也是开源的,并受Facebook支持。

安装


要在项目中安装Jest,请执行以下操作:

npm install --save-dev jest

如果使用纱线:

yarn add --dev jest

安装后,您可以更新package.json的脚本部分:

“scripts” : {
     “test”: “jest”
}

通过这个简单的调用,我们已经可以运行测试(实际上,开玩笑将需要至少一个测试存在)。

您也可以全局安装(但我不建议您这样做,因为对我而言,模块的全局安装是不明智的做法):

npm install jest --global

因此,对于纱线:

yarn global add jest

之后,您可以直接在命令行中使用jest。

通过在项目的根目录中调用jest --init命令,在回答了几个问题之后,您将获得jest.config.js设置文件。或者,您可以将配置直接添加到package.json中。为此,将“ jest”键添加到json根,然后在相应的对象中添加所需的设置。稍后我们将自己分析选项。在这个阶段这是没有必要的,因为开玩笑可以立即使用,而无需其他配置。

第一次测试


让我们创建first.test.js文件并编写我们的第一个测试:

//first.test.js
test('My first test', () => {
    expect(Math.max(1, 5, 10)).toBe(10);
});

并使用npm run test或直接使用jest命令(如果已全局安装)运行我们的测试。启动后,我们将看到有关通过测试的报告。

 <b>PASS</b>  ./first.test.js
  ✓ My first test (1 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.618 s, estimated 1 s

让我们打破测试,然后再次开玩笑:

//first.test.js
test('My first test', () => {
    expect(Math.max(1, 5, 10)).toBe(5);
});

如我们所见,现在我们的测试未通过测试。 Jest显示有关问题发生的位置,预期的结果以及我们得到的结果的详细信息。

现在,让我们分析测试本身的代码。测试功能用于创建新测试。它需要三个参数(在示例中,我们使用了带有两个参数的调用)。第一个是带有测试名称的行,其笑话将显示在报告中。第二个是包含测试逻辑的函数。您也可以使用第三个参数-超时。它是可选的,其默认值为5秒。以毫秒为单位设置。当我们使用异步代码并从测试函数返回promise时,此参数是必需的。它指示开玩笑必须等待多长时间才能解决诺言。在这个时间的最后,如果诺言没有得到解决,那么开玩笑就会认为测试失败了。以下部分将提供有关使用异步调用的更多信息。另外,您可以使用它()代替测试()。。这些调用之间没有区别。it()只是test()函数的别名

在测试函数内部,我们首先调用Expect()。我们将要检查的值交给他。在我们的例子中,这是调用Math.max(1、5、10)的结果Expect()返回一个包装器对象,该包装器对象具有许多用于将结果值与期望值进行比较的方法。我们使用的这些方法之一是toBe

让我们看一下这些方法的主要内容:

  • toBe() — , , . Object.is(). === 0 -0, NaN c NaN.
  • toEqual() — , . . . .

    test('toEqual with objects', () => {
        expect({ foo: 'foo', subObject: { baz: 'baz' } })
            .toEqual({ foo: 'foo', subObject: { baz: 'baz' } });  // 
        expect({ foo: 'foo', subObject: { num: 0 } })
            .toEqual({ foo: 'foo', subObject: { baz: 'baz' } });  //    .
    });
    
    test('toEqual with arrays', () => {
        expect([11, 19, 5]).toEqual([11, 19, 5]); // 
        expect([11, 19, 5]).toEqual([11, 19]); // 
    });
    

  • toContain() — . ===.

    const arr = ['apple', 'orange', 'banana'];
    expect(arr).toContain('banana');
    expect(new Set(arr)).toContain('banana');
    expect('apple, orange, banana').toContain('banana');
    

  • toContainEqual() — .

    expect([{a: 1}, {b: 2}]).toContainEqual({a: 1});
    

  • toHaveLength() — length .

    expect([1, 2, 3, 4]).toHaveLength(4);
    expect('foo').toHaveLength(3);
    expect({ length: 1 }).toHaveLength(1);
    

  • toBeNull() — null.
  • toBeUndefined() — undefined.
  • toBeDefined()toBeUndefined. !== undefined.
  • toBeTruthy() — true. false, null, undefined, 0, NaN .
  • toBeFalsy()toBeTruthy(). false.
  • toBeGreaterThan() toBeGreaterThanOrEqual() — , >, >=.
  • toBeLessThan() toBeLessThanOrEqual()toBeGreaterThan() toBeGreaterThanOrEqual()
  • toBeCloseTo() — , , . .

    const num = 0.1 + 0.2; // 0.30000000000000004
    expect(num).toBeCloseTo(0.3);
    expect(Math.PI).toBeCloseTo(3.14, 2);
    

  • toMatch() — .

    expect('Banana').toMatch(/Ba/);
    

  • toThrow() -在有必要检查异常时使用。您可以通过错误消息或消息与正则表达式的对应关系来检查错误本身的事实并检查是否抛出某个类的异常。

    function funcWithError() {
        throw new Error('some error');
    }   
    expect(funcWithError).toThrow();
    expect(funcWithError).toThrow(Error);
    expect(funcWithError).toThrow('some error');
    expect(funcWithError).toThrow(/some/);
    

  • -此属性使您可以检查不等式。它提供了具有上面列出的所有方法的对象,但是它们将以其他方式起作用。

    expect(true).not.toBe(false);
    expect({ foo: 'bar' }).not.toEqual({});
    
    function funcWithoutError() {}
    expect(funcWithoutError).not.toThrow();
    

让我们编写一些简单的测试。首先,创建一个简单的模块,其中将包含用于处理圆的几种方法。

// src/circle.js
const area = (radius) => Math.PI * radius ** 2;
const circumference = (radius) => 2 * Math.PI * radius;
module.exports = { area, circumference };

接下来,添加测试:

// tests/circle.test.js
const circle = require('../src/circle');

test('Circle area', () => {
    expect(circle.area(5)).toBeCloseTo(78.54);
    expect(circle.area()).toBeNaN();
});

test('Circumference', () => {
    expect(circle.circumference(11)).toBeCloseTo(69.1, 1);
    expect(circle.circumference()).toBeNaN();
});

在这些测试中,我们检查了两种方法的结果- 面积周长使用toBeCloseTo方法我们检查了预期结果。在第一种情况下,我们检查或计算出的半径为5的圆的面积大约等于78.54,而与获得的值的差(它将为78.53981633974483)不大并且将对测试进行计数。在第二个中,我们表示我们有兴趣检查到小数点后1位。我们还调用了不带参数的方法,并使用toBeNaN检查了结果由于执行结果为NaN,因此测试将成功通过。

让我们再举一个例子。让我们创建一个函数,该函数将按价格过滤一系列产品:

// src/productFilter.js
const byPriceRange = (products, min, max) =>
         products.filter(item => item.price >= min && item.price <= max);
module.exports = { byPriceRange };

并添加一个测试:

// tests/product.test.js
const productFilter = require('../src/producFilter');

const products = [
    { name: 'onion', price: 12 },
    { name: 'tomato', price: 26 },
    { name: 'banana', price: 29 },
    { name: 'orange', price: 38 }
];

test('Test product filter by range', () => {
    const FROM = 15;
    const TO = 30;
    const filteredProducts = productFilter.byPriceRange(products, FROM, TO);

    expect(filteredProducts).toHaveLength(2);
    expect(filteredProducts).toContainEqual({ name: 'tomato', price: 26 });
    expect(filteredProducts).toEqual([{ name: 'tomato', price: 26 }, { name: 'banana', price: 29 }]);
    expect(filteredProducts[0].price).toBeGreaterThanOrEqual(FROM);
    expect(filteredProducts[1].price).toBeLessThanOrEqual(TO);
    expect(filteredProducts).not.toContainEqual({ name: 'orange', price: 38 });
});

在此测试中,我们将检查byRangePrice 函数的结果。首先,我们检查了结果数组的长度与预期数组2的对应关系。下一次检查要求该元素包含元素-{name:'tomato',price:26}。数组中的对象和传递给ContainEqual的对象是两个不同的对象,而不是对同一对象的引用。但是toContainEqual将比较每个属性。由于两个对象相同,因此验证将成功。接下来,我们使用toEqual来检查整个数组及其元素的结构。该toBeGreaterThanOrEqualtoBeLessThanOrEqual方法将帮助我们检查数组的第一个和第二个元素的价格。最后,调用not.toContainEqual将检查元素是否包含在数组中-{name:'orange',price:38},根据条件,该数组不应存在。

在这些示例中,我们使用上述验证功能编写了一些简单的测试。在以下各部分中,我们将讨论异步代码的使用,教程本部分未介绍的开玩笑的功能,我们将讨论其配置等。

All Articles