Crea una cuenta o inicia sesión

¡Continúa aprendiendo sin ningún costo! Únete y comienza a potenciar tu carrera

Implementando pruebas a promesas

5/16
Recursos

Aportes 30

Preguntas 1

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

para lo typos, les recomiendo este plugin
Code Spell Checker

Para tener soporte de intellisense en VSCode se puede instalar npm i -D @types/jest y van a poder autocompletar las funciones que vienen en el package sin instalar una extension y no agrega peso al bundle de produccion.

Tambien van a poder autocompletar las funciones validas utilizando CTRL + Spacebar:

test('nombre', () => {
  expect(value). // CTRL+Spacebar aca para ver opciones validas
})

Como tienen instalados los tipos, tambien pueden hover por encima de las funciones y van a obtener los argumentos que toman, los tipos de esos argumentos, y una descripcion de que es lo que hace cada funcion.

Hola, me entró la duda de porque en el caso de probar funciones asíncronas teníamos que hacer un return dentro de la función anónima e investigando me encontré con esta sección dentro de la documentación de jest se las comparto por si le quieren echar un ojo https://jestjs.io/docs/asynchronous

Probando promesas .then

test('Probar una promesa', ()=> {
    return reverseString2('hola')
        .then(string => {
            expect(string).toBe('aloh')
        })
})

Probando promesa await

test('Probar async/await', async ()=>{
    const string = await reverseString2('hola');
    expect(string).toBe('aloh')
})

Correr algo antes y después de nuestras pruebas

afterEach( () => console.log('Despues de cada prueba') );
afterAll( () => console.log('Despues de todas las pruebas') );
beforeEach( () => console.log('antes de cada prueba') );
beforeAll( () => console.log('antes de todas las pruebas') );

Para practicar hice una Promise con un random, de ese valor random depende si pasa la prueba o no 😄

Hola! Les comparto otra manera de probar las promesas:

Implementando pruebas a código asíncrono

const reverseStringPromise = str => {
  return new Promise((resolve, reject) => {
    if (!str) {
      reject(Error("There is no string"));
    }
    resolve(str.split("").reverse().join(""));
  });
};

// Test promises
test("The promise should return a reversed word", () => {
  return reverseStringPromise("Platzi").then(str => {
    expect(str).toBe("iztalP");
  });
});

// Test async-await
test("The async-await block code should return a reversed word", async () => {
  const str = await reverseStringPromise("adidas");
  expect(str).toBe("sadida");
});

// Funcion que se ejecuta despues de cada prueba
afterEach(() => console.log("After each test"));
// Funcion que se ejetuta despues de todas las pruebas
afterAll(() => console.log("All the test ended."));

// Funcion que se ejecuta antes de cada prueba
beforeEach(() => console.log("Before each test"));
// Funcion que se ejecuta antes de todas las pruebas
beforeAll(() => console.log("Beginning of all the tests"));

En la prueba de las promesas no es necesario retornar la función de reverseString2, ya que la prueba como tal se realiza dentro del then:

const reverseString2 = str => {
  return new Promise((resolve, reject) => {
    if(!str) {
      reject(Error('Error'));
    }

    resolve(str.split('').reverse().join(''));
  });
};

test('Probando una promesa', () => {
  reverseString2('Hola')
    .then(string => {
      expect(string).toBe('aloH');
    });
});

Algo a tener en cuenta al hacer tests a procesos asíncronos es que podemos delimitar el numero de callbacks que esperamos sean llamados.
.
Esto lo podemos hacer con el método que aparece abajo, designando el número de callbacks o assertions que esperamos pasen.

expect.assertions(3)

Por ejemplo, si la función doAsync llama dos callbacks, podemos numerar que esperamos 2 assertions, como se muestra en el ejemplo.

test('doAsync calls both callbacks', () => {
  expect.assertions(2);
  function callback1(data) {
    expect(data).toBeTruthy();
  }
  function callback2(data) {
    expect(data).toBeTruthy();
  }

  doAsync(callback1, callback2);
});

Si quieren saber más acerca de los métodos que tiene expect, les dejo acá la documentación oficial de Jest 😉

Para Jest en general les recomiendo este plugin de vscode, tiene snippets, linteo, permite ejecutar un debugg de cada test e incluso va indicando cuales ya corriste de manera exitosa.
VS Marketplace Link: https://marketplace.visualstudio.com/items?itemName=Orta.vscode-jest

Probando promise y async/await

const reverseStringPromise = str => {
  return new Promise((resolve, reject) => {
    if (!str) {
      reject(Error("Error"));
    }
    resolve(
      str
        .split("")
        .reverse()
        .join("")
    );
  });
};

test("Probar una promesa", () => {
  return reverseStringPromise("hola").then(string => {
    expect(string).toBe("aloh");
  });
});

test("Probar async/await", async () => {
  const string = await reverseStringPromise("hola");
  expect(string).toBe("aloh");
});

afterEach(() => {
  console.log("Despues de cada prueba");
});

afterAll(() => {
  console.log("Despues de todas las pruebas");
});

beforeEach(() => {
  console.log("Antes de cada prueba");
});

beforeAll(() => {
  console.log("Antes de todas las pruebas");
});

Scoping
Para agrupar cada grupo de test , es posible utilizar el bloque describe .

beforeAll(() => console.log('1 - beforeAll'));
afterAll(() => console.log('1 - afterAll'));
beforeEach(() => console.log('1 - beforeEach'));
afterEach(() => console.log('1 - afterEach'));
test('', () => console.log('1 - test'));
describe('Scoped / Nested block', () => {
  beforeAll(() => console.log('2 - beforeAll'));
  afterAll(() => console.log('2 - afterAll'));
  beforeEach(() => console.log('2 - beforeEach'));
  afterEach(() => console.log('2 - afterEach'));
  test('', () => console.log('2 - test'));
});

// 1 - beforeAll
// 1 - beforeEach
// 1 - test
// 1 - afterEach
// 2 - beforeAll
// 1 - beforeEach
// 2 - beforeEach
// 2 - test
// 2 - afterEach
// 1 - afterEach
// 2 - afterAll
// 1 - afterAll

Dejo los tests escritos hasta ahora:

const text = "Hello World";
const fruits = ['apple', 'mellon', 'banana'];

// Strings
test('Should render a Hello World', () => {
  expect(text).toMatch(/Hello World/)
});

// Arrays
test('Do we have Banana?', () => {
  expect(fruits).toContain('banana')
});

test('> than', () => {
  expect(10).toBeGreaterThan(9)
})

// Boolean
test('True', () => {
  expect(true).toBeTruthy()
});

// Callbacks
const reverseString = (str, callback) => {
  callback(str.split("").reverse().join(""))
};

test('Test Callback', () => {
  reverseString('Hola', (str) => {
    expect(str).toBe('aloH')
  })
});

// Promises
const reversePromiseString = str => {
  return new Promise((resolve, reject) => {
    if (!str) {
      reject(Error('Error'))
    }
    resolve(str.split("").reverse().join(""))
  });
};

test('Test Promise',  () => {
  return reversePromiseString('Hola')
    .then(string => {
      expect(string).toBe('aloH')
    });
});

// Async & Await
test('Test async/Await', async ()  => {
  const string = await reversePromiseString('Hola');
  expect(string).toBe('aloH')
});

// Run code we need after each test
afterEach(() => console.log('After each test'));
afterAll(() => console.log('After all tests'));

// Run code we need before each test
beforeEach(() => console.log('Before each test'));
beforeAll(() => console.log('Before all tests'));

Esta genial el after y el before.

Si por alguna razón al utilizar Async/Await y corren la prueba reciben el siguiente error

ReferenceError: regeneratorRuntime is not defined

deben agregar en el archivo .babelrc el siguiente objeto

{ "presets": [ [ "@babel/preset-env", { "targets": { "node": “current” } } ] ] }

‘node’:current es para que detecte la version de node que tengas instaladas y detectara automaticamente si tienes Async/Await

despues de esto vamos a instalar

nom i @babel/preset-env -D

Async/Await:

Función:

const reverseString2 = str => {
    return new Promise((resolve, reject) => {
        if(!str) {
            reject(Error('Error'))
        }
        resolve(str.split("").reverse().join(""))
    })
};

Test:

test('Probar async/await', async() => {
    const string = await reverseString2('Prueba');
    expect(string).toBe('abeurP')
});

Al igual en la prueba realizada en async/await no es necesario realizar la siguiente línea de código:

const string = await reverseString2('Hola');

Ya que, podemos ejecutar reverseString2() directamente en el expect:

test('Probando async/await', async () => {
  /* const string = await reverseString2('Hola'); */
  expect(await reverseString2('Hola')).toBe('aloH');
});

Pdta: No sé que tan buena práctica sea, pero nos estamos ahorrando una línea de código

const reverseString2 = (str) => {
    return new Promise( (resolve, reject) => {
        if(!str || str == ''){
            reject(new Error('no existe el texto'));
        }else{
            resolve(str.split("").reverse().join(""));
        }
    })
}

test('probando promesas', () => {
    return reverseString2('Hola')
        .then(string => {
            expect(string).toBe('aloH');
        })
})

Creo que es importante verificar si los test realmente funcionan como los necesitamos. La prueba de la promesa vista en la clase no funciona al 100%

const reverseString2 = (str) => {
  return new Promise((resolve, reject)=>{
    if(!str){
      reject(Error('error'))
    }
    resolve(str.split('').reverse().join(""))
  })
}

test('Promise Test', () => {
  reverseString2('hola')
  .then(string =>  expect(string).toBe('chao'))
})

// El test pasa sin que la salida cumpla el test

Claramente cometí un error a proposito para comprobar que el test funciona evaluando la salida de la promesa y para este caso no se está verificando lo que retorna la promesa, para que que este funcione bien debemos agregar un return al resultado de la ejecución de la promesa dentro de la función anónima

const reverseString2 = (str) => {
return new Promise((resolve, reject)=>{
if(!str){
reject(Error(‘error’))
}
resolve(str.split(’’).reverse().join(""))
})
}

test(‘Promise Test’, () => {
return reverseString2(‘hola’)
.then(string => expect(string).toBe(‘aloh’))
})

Para quien lo necesite la aplicacion con todos los TEST vistos hasta esta clase. Repositorio GIT
una vez descargada: npm install y npm jest para iniciar.
descargar

Pienso que mucho de los errores presentados ya son solventados implementando typescript en los proyectos

qué pasa si quiero ejecutar código antes de una prueba específica? o eso no es muy común?

Si es que les falla el async/await a mi me sirvió crear un archivo setupTest.js importando dentro runtime (import ‘regenerator-runtime/runtime’) y llamando a este archivo desde el package.json como “jest”: {
“setupFilesAfterEnv”: [
"./setupTests.js"
]
}

justo después de las devDependencies

Hay forma de que los metodos:
afterEach
afterAll
beforeEach
beforeAll

generen el console.log al momento de que se ejecutan y no todos al final? y como especificar la prueba de la cual queremos que se ejecute, ya sea antes o despues?

PROMESAS:

const reverseString2 = str => {
    return new Promise((resolve, reject) => {
        if(!str) {
            reject(Error('Error'))
        }
        resolve(str.split("").reverse().join(""))
    })
};

test('Probar una promesa', () => {
    return reverseString2('Hola')
        .then(string => {
            expect(string).toBe('aloH');
        });
});

muy bueno, como siempre

Para poder manejar promesas y async/await con Jest, es necesario entender algo que viene en la documentación de Jest:

De forma predeterminada, los test de Jest se completan una vez que llegan al final de su ejecución. El problema con las promesas es que el test se completará tan pronto como se resuelva la promesa ( antes de realizar la devolución de la llamada de la función ).
[…]
Retorne una promesa de su test y Jest esperará a que esa promesa se resuelva. Si se rechaza la promesa, la prueba fallará automáticamente.

  • Asegúrese de devolver la promesa: si omite este return, su test se completará antes de que la promesa devuelta se resuelva y then() tenga la oportunidad de ejecutar el callback.
test('the data is peanut butter', () => {
  return fetchData().then(data => {
    expect(data).toBe('peanut butter');
  });
});

Aqui esta la liga para mayor detalle de las funciones auxiliares hooks. No confudnir con las funciones de react hooks.

el return no es necesario para ejecutar la promesa ya que lo que devuelve se ejecuta en .then

test('Probando una Promesa', () => {
    reverseString2('Hola')
    .then(string => {
        expect(string).toBe('aloh')
    })
})```

espero no salga algo raro en react 😦