Jest é uma estrutura de teste de Javascript do Facebook. É usado mais comumente para testes de unidade . O teste de unidade é quando você fornece entrada para uma unidade de código (geralmente, uma função) e combina a saída com a saída esperada.

Características do Jest:

  • configuração zero: como veremos mais adiante neste artigo, quase nenhuma configuração é necessária para começar a escrever testes e implantá-los. No entanto, um arquivo de configuração também pode ser fornecido ao conjunto de testes.
  • snapshots: Jest tem a capacidade de habilitar o teste de snapshots também. Essencialmente, os instantâneos são combinados com o instantâneo salvo e verificam a funcionalidade de correspondência.
  • testes isolados: os testes de brincadeira são executados paralelamente para melhorar o tempo de execução.

Configurando um projeto jest

  • Instale o Jest usando npm:
    npm install jest.  A palavra-chave -D instala jest como dependência dev

    npm install jest. A palavra-chave -D instala jest como dependência dev

  • Estrutura do projeto:
    No diretório raiz do projeto, crie uma pasta de testes . Esta pasta armazenará todos os arquivos de teste.
    Observe que os arquivos js (que devem ser testados) são mapeados por seus nomes.
    Por exemplo, index.js é mapeado para index.test.js . Este arquivo index.test.js é colocado na pasta 'testes'. Esta é a estrutura convencional do projeto.

Comece o teste:

  • Para começar, vamos ver um fluxo de trabalho de teste básico.
    teste - adicionando dois números pos

    teste - adicionando dois números pos

  • Para executar o teste, use o script
    teste de execução npm

    Isso procurará o script de teste mencionado no package.json do projeto.

    pkg-json-test-script-ss

    pkg-json-test-script-ss. Ver teste em scripts

Usaremos o método 'esperar' para testar nossas funções. As funções também podem ser testadas usando 'descrever' e 'isso' .

Um teste básico: somar dois números positivos e verificar o resultado.

//index.js
testForAdd: (a, b) => { return (a + b) },

//index.test.js
test('test adding two positive nums', function() {
    expect(testFns.testForAdd(4, 5)).toBe(9);
});

Quando o 'npm run test' é executado, o arquivo index.test.js é processado . Em seguida, a função testForAdd é executada e colocada no objeto 'testFns' . O toBe é usado para 'combinar' a resposta retornada do teste com o que é esperado. Esta 'correspondência de resultados' leva a uma 'falha' ou a uma 'aprovação' .

teste adicionando dois números pos

teste adicionando dois números pos

O teste a seguir falhará por causa do 'toBe (8)' .

//example of a failing test
 test('test adding two positive nums - failing test', function() {
     expect(testFns.testForAdd(4, 5)).toBe(8);
 });

Oposto de toBe: not.toBe()
O oposto do matcher 'toBe' é criado simplesmente prefixando-o com 'not.'
Por exemplo:

//test successful - test for opposite of a matcher.
//The following test will 'Pass' if the returned value is not equal to 8.
test('test adding two positive nums - failing test', function() {
    expect(testFns.testForAdd(4, 5)).not.toBe(8);
});

Usando 'toBe' com objetos JS:
Vamos pensar em um caso em que cada campo de um objeto JS deve ser testado. Jest nos fornece uma maneira de fazer isso usando 'toEqual' . O 'toEqual' é um matcher profundo (verifica todos os campos e subcampos possíveis).

//expect toEqual example - check every field's value
// testFns.test_toEqual(gfgObj)
test('check gfgObj toEqual', () => {
    let gfgObj = { name: "GFG" };
    gfgObj['type'] = "company";
    expect(gfgObj).toEqual({ name: "GFG", type: "company" });
});

Executar o teste acima irá 'Passar'.

gfgobj toEqual

gfgobj toEqual

Outra variação de fazer isso é combinar dois objetos usando o 'toEqual' .
Isso é feito assim:

test('check gfgObj toEqual', () => {
    let gfgObj = {
        name: "GFG",
        type: "company",
        members: {
            employees: 100,
            contributors: 500
        }
    };

    let testObj = {
        name: "GFG",
        type: "company",
        members: {
            employees: 100,
            contributors: 500
        }
    };
    expect(gfgObj).toEqual(testObj);
});

Este teste demonstra o recurso de correspondência profunda de toEqual.
O teste acima é aprovado porque todos os pares de chaves em gfgObj correspondem a testObj.

gfgobj-testobj-toequal

gfgobj-testobj-toequal

toBeCloseTo - para números de ponto flutuante e outras correspondências aproximadas

//see here that a+b != c even though simple addition is taking place.
> var a = 1.32
> undefined
> var b = 2.31
> undefined
> c = a+b;
> 3.63
> var res = false;
> if(c==(a+b)) {c=true;}
> undefined
> c
> false

Nessas condições, é bom usar o matcher 'toBeCloseTo' da biblioteca Jest.

test('floating point number - use toBeCloseTo instead', function() {
    // const num1 = 0.3;
    // const num2 = 0.2;
    const result = 9.31 + 9.2;

    expect(result).toBeCloseTo(18.51);
})

O teste acima também passa.

correspondência verdadeira e falsa:
https://jestjs.io/docs/en/using-matchers#truthiness
Muitas vezes, os testes são escritos para verificar os valores verdadeiros e falsos retornados por 'esperar'. Valores
falsos em JS. Valores
verdadeiros em JS.

//checking for truthy values - All the tests will return truthy.
test('check for truthy', function() {
    const gfgObj = {
        first: null,
        second: undefined,
        third: false
    }
    expect(gfgObj.first).not.toBeTruthy(); // True - Pass
    expect(gfgObj.second).toBeUndefined(); // True - Pass
    expect(gfgObj.third).toBeFalsy();      // True - Pass
})

O teste acima foi aprovado.

truthy-test-js-all-test-pass

truthy-test-js-all-test-pass

No entanto, se qualquer um dos ' esperar' acima falhar, Jest retorna mensagens de erro significativos como abaixo.

Observe que, no caso acima, se algum dos 'expect'-s falhar, o teste também falhará completamente.

truthy-test-js-one-expect-failing-so-test-failing

truthy-test-js-one-expect-failing-so-test-failing

Números correspondentes:

//tests for Number matches
test('test for numbers', function() {
    const result = 3 + 9;
    // expect(result).toBe(12); //the plain old matcher
    expect(result).not.toBeLessThan(10); // result > 10
    expect(result).toBeLessThan(15);  // result < 15
    expect(result).not.toBeGreaterThan(15); // result  10
    expect(result).toBeGreaterThanOrEqual(12);  //result >= 12
    // expect(result).not.toBeGreaterThanOrEqual(12); // result == 12, this Fails
    // expect(result).toBeLessThanOrEqual(10); // result >= 10, this Fails
})
número combinando usando jest

número combinando usando jest

Testando valores contidos em arrays:
Também podemos testar se valores específicos estão contidos em um array. Observe que este teste irá 'falhar' se pelo menos um valor não estiver presente na array. Por exemplo,

//testing arrays
const gfgUsers = [
    'user1',
    'user2',
    'user3'
];
test('test for a value in gfgUsers', function() {
    // expect(gfgUsers).toContain('user2');
    // expect(gfgUsers).not.toContain('user2');
    //expect array containing
     expect(gfgUsers).toEqual(expect.arrayContaining(['user1', 'user3']));
})

O teste acima passa quando o usuário1 e o usuário3 estão presentes em gfgUsers.

user1-and-user3-in-gfgUsers

user1-and-user3-in-gfgUsers

No entanto, o teste a seguir falhará porque 'user4' não está presente em gfgUsers.

//testing arrays
const gfgUsers = [
    'user1',
    'user2',
    'user3'
];
test('test for a value in gfgUsers', function() {
    //expect array containing
     expect(gfgUsers).toEqual(expect.arrayContaining(['user1', 'user4']));
})
arraycontaining-fail-due-to-user4-absorbent

arraycontaining-fail-due-to-user4-absorbent

Testando usando Regex:

test('string match tests - toMatch - used for regex-es', function() {
    const str = 'GeeksforGeeks';
    // expect(str).toMatch(/f/);
    // expect(str).toMatch(/Z/);
    //you can create more complex Regexes
    const str1 = 'This is a test paragraph. I wrote it.'
    expect(str1).toMatch(/[pP][hH][\.]/);  //matches 'ph.' in the word 'paragraph'
})
tomatch-matching-ph-in-paragraphq

tomatch-matching-ph-in-paragraph

Estendendo os Matchers
Jest também tem a disposição de estender sua funcionalidade 'Matchers' , que é realizada usando a palavra-chave 'expect.extend()' . A função .extend() é passada matchers como objetos.
Sintaxe: expect.extend ({matcher1, matcher2});
Por exemplo, se quisermos construir um matcher que verifique a presença de uma frase em uma string:

expect.extend({
stringPresent(receivedString, phraseString) {
bool phrasePresent = true;
var re = new RegExp(phraseString);
if (re.test(receivedString)) {
    phrasePresent = true;
} else {
    phrasePresent = false;
}
if (phrasePresent === true) {
      return {
        message: () =>
          `string present`,
        pass: true,
      };
    } else {
      return {
        message: () =>
          `string absent`,
        pass: false,
      };
    }
},
});

Lidando com exceções
Também podemos verificar os tipos de erros que uma unidade de código gera. Podemos verificar o erro lançado por nome, mensagem, objeto, etc.

Sintaxe : expect (fnName()) .toThrow (erro);
O parâmetro / argumento de erro é opcional aqui.

Vamos supor que queremos testar uma função pela mensagem do erro lançado.

function testGFGMessage() {
  throw new Error('this is testGFGMessage function error');
}
test('testing testGFGMessage', function(){
  expect(testGFGMessage).toThrow('this is testGFGMessage function error');
})

Existem muitas outras maneiras de lançar Erros e verificá-los. Uma referência detalhada pode ser encontrada aqui .

Ignorando / executando um subconjunto de testes
https://jestjs.io/docs/en/api#testskipname-fn
Jest também tem uma disposição para ignorar testes específicos durante a execução do conjunto de testes.
Para implementá-lo, basta usar a palavra-chave 'pular' . Por exemplo,

function addFn(num1, num2){
  return num1 + num2;
}

test.skip('skip test example - skipping the addition test', () => {
  expect(addFn(2, 3)).toBe(5);
});

O oposto disso é implementar apenas um subconjunto de testes, que é obtido usando a palavra-chave 'apenas' . Por exemplo,

function addFn(num1, num2){
  return num1 + num2;
}

test.only('skip test example - skipping the addition test', () => {
  expect(addFn(2, 3)).toBe(5);
});