SlideShare a Scribd company logo
1 of 27
Unit Test
React js + Jest
/gabrielcomas
¿Qué es Unit Test y para que sirve?
Es lo que permite llevar un control, a menor escala,
de los componentes para que estos cumplan con
nuestras expectativas.
CLICK ME
Resultado final:
Click Me
Expectativa:
Beneficios
Nuestro código cumple un standard.
Ocurren menos errores en la etapa de producción.
Genera confianza a la hora de programar.
Jest
Framework de Unit Testing
https://jestjs.io/docs/en/getting-started.html
Características de Jest
// No necesita demasiada configuración adicional.
// Tests UI de forma rápida y ágil.
// Pruebas individuales, pueden isolarse.
// Genera reportes del porcentaje de la app testeada.
// Posee gran cantidad de documentación.
// Cuenta con una comunidad activa.
Instalación y configuración
// Buenas prácticas
Cada componente debe tener su carpeta __test__
Todos los archivos de test debe tener la siguiente estructura
// ejemplo.test.js
npm install --save-dev jest
"scripts": {
"test": "jest --verbose"
},
npm run test
// package.json
Estructura
test("Descripción del test", () => {
expect(elemento a testear).verbo()
})
test("It should has React", () => {
const frameworks = ["React", "Vue", "Angular",
"Svelte"];
expect(frameworks).toContain("React"); });
// Ejemplo
// Test arrays
test("It should has React", () => {
const frameworks = ["React", "Vue", "Angular", "Svelte"];
expect(frameworks).toContain("React"); });
// Test numbers
test("It should be greater than", () => {
expect(10).toBeGreaterThan(9); });
// Test Booleans
test("It should be true", () => { expect(true).toBeTruthy(); });
// Reverse strings function
const reverseString = (str, cb) => {
cb(str.split("").reverse().join("")); };
// Test callbacks
test("The callback should return a reversed word", () => {
reverseString("Platzi", str => { expect(str).toBe("iztalP"); }); });
const reverseStringPromise = str => {
return new Promise((resolve, reject) => {
if (!str) {
reject(Error("Error"));
}
resolve(str.split("").reverse().join(""));
});
};
// Test Promise
test(“Test promise", () => {
return reverseStringPromise("hola").then(string => {
expect(string).toBe("aloh");
});
});
// Test Async/Await
test(“Test async/await", async () => {
const string = await reverseStringPromise("hola");
expect(string).toBe("aloh");
});
Describe – Agrupar tests
describe("Test group", () => {
test("It should has React", () => {
const frameworks = ["React", "Vue",
"Angular", "Svelte"];
expect(frameworks).toContain("React");
});
test("It should be greater than", () => {
expect(10).toBeGreaterThan(9);
});
});
Test individual
// Correr el test de un archivo en particular
// package.json
Watch
// Escucha los test y los ejecuta cuando ocurre un cambio en los mismos
"scripts": {
"test": "jest --verbose",
"test:watch": "jest --watch"
},
npm run test:watch
npm install -g jest
jest src/__test__/index.test.js
jest --coverage
Coverage
// Reporte de tests
//coverage/Icov-report/index.html
npm install --save-dev enzyme
Enzyme
Librería Airbnb
npm install --save-dev enzyme-adapter-react-16 //React Versión 16
npm install --save-dev jsdom jsdom-global
¿Qué ofrece Enzyme?
Mount() Shallow()
Realiza un render en el DOM
del componente.
Permitiéndonos testear
interacciones del usuario
(eventos).
Solo necesitas algo
particular del componente.
Al no necesitar el DOM,
el test es rápido.
Configuración
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });
// setupTest.js
"jest": {
"setupFilesAfterEnv": [
"<rootDir>/src/__test__/setupTest.js"
]
}
// package.json
Mocks
Funciones que simulan acciones
Mocks - Estilos
module.exports = {}
//__Mocks__/styleMock.js
"jest": {
"setupFilesAfterEnv": [
"<rootDir>/src/__test__/setupTest.js"
],
"moduleNameMapper": {
".(css)$": "<rootDir>/src/__mocks__/styleMock.js"
}
}
// package.json
Mocks - Provider
import React from 'react';
import { createStore } from 'redux';
import { Router } from 'react-router-dom';
import { Provider } from 'react-redux';
import { createBrowserHistory } from 'history';
import initialState from '../initialState';
import reducer from '../reducers';
const store = createStore(reducer, initialState);
const history = createBrowserHistory();
const ProviderMock = props => (
<Provider store={store}>
<Router history={history}>
{ props.children }
</Router>
</Provider>
);
export default ProviderMock;
//__Mocks__/providerMock.js
Caso de uso - Mocks Provider
describe('<Header/>', () => {
test('render del componente Header', () => {
const header = shallow(
<ProviderMocks>
<Header />
</ProviderMocks>
);
expect(header.length).toEqual(1);
});
test('Render del titulo', () => {
const header = mount(
<ProviderMocks>
<Header />
</ProviderMocks>
);
expect(header.find('.Header-title').text()).toEqual('Mi título');
});
});
npm install --save-dev react-test-renderer
Snapshot
UI Test
¿Cómo se utiliza?
import { create } from 'react-test-renderer';
describe('<Footer/>', () => {
test('Footer UI', () => {
const footer = create(<Footer />);
expect(footer.toJSON()).toMatchSnapshot();
});
});
JSON
"scripts": {
"test:update": "jest --updateSnapshot",
},
npm run test:update
// package.json
Otros Tests
Redux: Acciones y Reducers
Peticiones Fetch
import actions from '../../actions/';
import ProductMock from '../../__mocks__/ProductMock';
describe('Actions', () => {
const payload = ProductMock;
test('addToCart Action', () => {
const expected = {
type: 'ADD_TO_CART',
payload,
};
expect(actions.addToCart(payload)).toEqual(expected);
});
test('removeFromCart', () => {
const expected = {
type: 'REMOVE_FROM_CART',
payload,
};
expect(actions.removeFromCart(payload)).toEqual(expected);
});
});
Acciones
import reducer from '../../reducers';
import ProductMock from '../../__mocks__/ProductMock';
describe('Reducers', () => {
test('Retornar initial State', () => {
expect(reducer({}, '')).toEqual({});
});
test('ADD_TO_CART', () => {
const initialState = {
cart: [],
};
const payload = ProductMock;
const action = {
type: 'ADD_TO_CART',
payload,
};
const expected = {
cart: [
ProductMock,
],
};
expect(reducer(initialState, action)).toEqual(expected);
});
});
Reducers
Fetch
npm install --save-dev jest-fetch-mock
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });
global.fetch = require('fetch-jest-mock')
// setupTest.js
const getData = (api) => {
return fetch(api)
.then(response => response.json())
.then(response => response)
.catch(error => error);
};
export default getData;
// src/utils/getData.js
import getData from '../../utils/getData';
describe('Fetch API', () => {
beforeEach(() => {
fetch.resetMocks();
});
test('Llamar una API y retornar datos', () => {
fetch.mockResponseOnce(JSON.stringify({ data: '12345' }));
getData('https://google.com').then((response) => {
expect(response.data).toEqual('12345');
done();
});
expect(fetch.mock.calls[0][0]).toEqual('https://google.com');
});
});
// src/utils/getData.test.js
¡Muchas Gracias!
/gabrielcomas

More Related Content

What's hot

用 Javascript 實現你的想像
用 Javascript 實現你的想像用 Javascript 實現你的想像
用 Javascript 實現你的想像Anna Su
 
GRUNT - The JavaScript Task Runner
GRUNT - The JavaScript Task RunnerGRUNT - The JavaScript Task Runner
GRUNT - The JavaScript Task RunnerLarry Nung
 
Gradle - next generation of build tools
Gradle - next generation of build toolsGradle - next generation of build tools
Gradle - next generation of build toolsIgor Khotin
 

What's hot (6)

Ejercicio progra
Ejercicio prograEjercicio progra
Ejercicio progra
 
用 Javascript 實現你的想像
用 Javascript 實現你的想像用 Javascript 實現你的想像
用 Javascript 實現你的想像
 
Spring Boot 소개
Spring Boot 소개Spring Boot 소개
Spring Boot 소개
 
GRUNT - The JavaScript Task Runner
GRUNT - The JavaScript Task RunnerGRUNT - The JavaScript Task Runner
GRUNT - The JavaScript Task Runner
 
Discover ServiceWorker
Discover ServiceWorkerDiscover ServiceWorker
Discover ServiceWorker
 
Gradle - next generation of build tools
Gradle - next generation of build toolsGradle - next generation of build tools
Gradle - next generation of build tools
 

Unit Testing con Jest + Enzime para ReactJs

  • 1. Unit Test React js + Jest /gabrielcomas
  • 2. ¿Qué es Unit Test y para que sirve? Es lo que permite llevar un control, a menor escala, de los componentes para que estos cumplan con nuestras expectativas. CLICK ME Resultado final: Click Me Expectativa:
  • 3. Beneficios Nuestro código cumple un standard. Ocurren menos errores en la etapa de producción. Genera confianza a la hora de programar.
  • 4. Jest Framework de Unit Testing https://jestjs.io/docs/en/getting-started.html
  • 5. Características de Jest // No necesita demasiada configuración adicional. // Tests UI de forma rápida y ágil. // Pruebas individuales, pueden isolarse. // Genera reportes del porcentaje de la app testeada. // Posee gran cantidad de documentación. // Cuenta con una comunidad activa.
  • 6. Instalación y configuración // Buenas prácticas Cada componente debe tener su carpeta __test__ Todos los archivos de test debe tener la siguiente estructura // ejemplo.test.js npm install --save-dev jest "scripts": { "test": "jest --verbose" }, npm run test // package.json
  • 7. Estructura test("Descripción del test", () => { expect(elemento a testear).verbo() }) test("It should has React", () => { const frameworks = ["React", "Vue", "Angular", "Svelte"]; expect(frameworks).toContain("React"); }); // Ejemplo
  • 8. // Test arrays test("It should has React", () => { const frameworks = ["React", "Vue", "Angular", "Svelte"]; expect(frameworks).toContain("React"); }); // Test numbers test("It should be greater than", () => { expect(10).toBeGreaterThan(9); }); // Test Booleans test("It should be true", () => { expect(true).toBeTruthy(); }); // Reverse strings function const reverseString = (str, cb) => { cb(str.split("").reverse().join("")); }; // Test callbacks test("The callback should return a reversed word", () => { reverseString("Platzi", str => { expect(str).toBe("iztalP"); }); });
  • 9. const reverseStringPromise = str => { return new Promise((resolve, reject) => { if (!str) { reject(Error("Error")); } resolve(str.split("").reverse().join("")); }); }; // Test Promise test(“Test promise", () => { return reverseStringPromise("hola").then(string => { expect(string).toBe("aloh"); }); }); // Test Async/Await test(“Test async/await", async () => { const string = await reverseStringPromise("hola"); expect(string).toBe("aloh"); });
  • 10. Describe – Agrupar tests describe("Test group", () => { test("It should has React", () => { const frameworks = ["React", "Vue", "Angular", "Svelte"]; expect(frameworks).toContain("React"); }); test("It should be greater than", () => { expect(10).toBeGreaterThan(9); }); });
  • 11. Test individual // Correr el test de un archivo en particular // package.json Watch // Escucha los test y los ejecuta cuando ocurre un cambio en los mismos "scripts": { "test": "jest --verbose", "test:watch": "jest --watch" }, npm run test:watch npm install -g jest jest src/__test__/index.test.js
  • 12. jest --coverage Coverage // Reporte de tests //coverage/Icov-report/index.html
  • 13. npm install --save-dev enzyme Enzyme Librería Airbnb npm install --save-dev enzyme-adapter-react-16 //React Versión 16 npm install --save-dev jsdom jsdom-global
  • 14. ¿Qué ofrece Enzyme? Mount() Shallow() Realiza un render en el DOM del componente. Permitiéndonos testear interacciones del usuario (eventos). Solo necesitas algo particular del componente. Al no necesitar el DOM, el test es rápido.
  • 15. Configuración import Enzyme from 'enzyme'; import Adapter from 'enzyme-adapter-react-16'; Enzyme.configure({ adapter: new Adapter() }); // setupTest.js "jest": { "setupFilesAfterEnv": [ "<rootDir>/src/__test__/setupTest.js" ] } // package.json
  • 17. Mocks - Estilos module.exports = {} //__Mocks__/styleMock.js "jest": { "setupFilesAfterEnv": [ "<rootDir>/src/__test__/setupTest.js" ], "moduleNameMapper": { ".(css)$": "<rootDir>/src/__mocks__/styleMock.js" } } // package.json
  • 18. Mocks - Provider import React from 'react'; import { createStore } from 'redux'; import { Router } from 'react-router-dom'; import { Provider } from 'react-redux'; import { createBrowserHistory } from 'history'; import initialState from '../initialState'; import reducer from '../reducers'; const store = createStore(reducer, initialState); const history = createBrowserHistory(); const ProviderMock = props => ( <Provider store={store}> <Router history={history}> { props.children } </Router> </Provider> ); export default ProviderMock; //__Mocks__/providerMock.js
  • 19. Caso de uso - Mocks Provider describe('<Header/>', () => { test('render del componente Header', () => { const header = shallow( <ProviderMocks> <Header /> </ProviderMocks> ); expect(header.length).toEqual(1); }); test('Render del titulo', () => { const header = mount( <ProviderMocks> <Header /> </ProviderMocks> ); expect(header.find('.Header-title').text()).toEqual('Mi título'); }); });
  • 20. npm install --save-dev react-test-renderer Snapshot UI Test
  • 21. ¿Cómo se utiliza? import { create } from 'react-test-renderer'; describe('<Footer/>', () => { test('Footer UI', () => { const footer = create(<Footer />); expect(footer.toJSON()).toMatchSnapshot(); }); }); JSON "scripts": { "test:update": "jest --updateSnapshot", }, npm run test:update // package.json
  • 22. Otros Tests Redux: Acciones y Reducers Peticiones Fetch
  • 23. import actions from '../../actions/'; import ProductMock from '../../__mocks__/ProductMock'; describe('Actions', () => { const payload = ProductMock; test('addToCart Action', () => { const expected = { type: 'ADD_TO_CART', payload, }; expect(actions.addToCart(payload)).toEqual(expected); }); test('removeFromCart', () => { const expected = { type: 'REMOVE_FROM_CART', payload, }; expect(actions.removeFromCart(payload)).toEqual(expected); }); }); Acciones
  • 24. import reducer from '../../reducers'; import ProductMock from '../../__mocks__/ProductMock'; describe('Reducers', () => { test('Retornar initial State', () => { expect(reducer({}, '')).toEqual({}); }); test('ADD_TO_CART', () => { const initialState = { cart: [], }; const payload = ProductMock; const action = { type: 'ADD_TO_CART', payload, }; const expected = { cart: [ ProductMock, ], }; expect(reducer(initialState, action)).toEqual(expected); }); }); Reducers
  • 25. Fetch npm install --save-dev jest-fetch-mock import Enzyme from 'enzyme'; import Adapter from 'enzyme-adapter-react-16'; Enzyme.configure({ adapter: new Adapter() }); global.fetch = require('fetch-jest-mock') // setupTest.js const getData = (api) => { return fetch(api) .then(response => response.json()) .then(response => response) .catch(error => error); }; export default getData; // src/utils/getData.js
  • 26. import getData from '../../utils/getData'; describe('Fetch API', () => { beforeEach(() => { fetch.resetMocks(); }); test('Llamar una API y retornar datos', () => { fetch.mockResponseOnce(JSON.stringify({ data: '12345' })); getData('https://google.com').then((response) => { expect(response.data).toEqual('12345'); done(); }); expect(fetch.mock.calls[0][0]).toEqual('https://google.com'); }); }); // src/utils/getData.test.js

Editor's Notes

  1. A diferencia de un test integral, que es el test que se genera sobre un conjunto de funcionabilidades, o un test E2E, que hace lo mismo, pero utilizando un escenario real, con sus servicios.
  2. Establece una regla para componentes que no cambian normalmente, sin logica, y que representa una estructura visual
  3. Se instala “react-test-renderer” ya que se necesita convertir el component a un objeto JSON para hacer el Snapshot
  4. Establece una regla para componentes que no cambian normalmente, sin logica, y que representa una estructura visual
  5. Para hacer fetch hay que instalar el mock de fetch y agregarlo a la configuracion
  6. Para hacer fetch hay que instalar el mock de fetch y agregarlo a la configuracion