Quality
Как можно повысить качество кода?
1 Code style and Linting
2 Type checking
Testing
JS Doc
TDD
Jest
Jest — это восхитительный фреймворк для тестирования JavaScript с акцентом на простоту
Jest
yarn add --dev jest
or
npm install --save-dev jest
Если нужны дополнительные настройки:
- можно добавить в package.json или в специальном файле jest.config.js
Jest
Run:
"scripts": {
"test": "jest",
}
npm run test
Jest
Jest состоит:
Jest
describe('A suite', () => {
test('contains spec with n expectation', () => {
expect(Math.max(1, 5, 10)).toBe(10);
});
})
Jest
describe('Match calculation', () => {
test('should be true when max value present', () => {
expect(Math.max(1, 5, 10)).toBe(10);
});
})
Jest
function sum(a, b) {
return a + b;
}
describe('sum', () => {
test('should be 3 when called sum with args 1 and 2', () => {
expect(sum(1,2)).toBe(3);
});
})
Unit test by TDD
const englishCode = "en-US";
const spanishCode = "es-ES";
function getAboutUsLink(language){
switch (language.toLowerCase()){
case englishCode.toLowerCase():
return '/about-us';
case spanishCode.toLowerCase():
return '/acerca-de';
}
return '';
}
describe('getAboutUsLink', () => {
test('should return correct route for en', () => {
expect(getAboutUsLink(englishCode)).toBe('/about-us');
});
})
Unit test by TDD
const englishCode = "en-US";
const spanishCode = "es-ES";
function getAboutUsLink(language){
switch (language.toLowerCase()){
case englishCode.toLowerCase():
return '/about-us';
case spanishCode.toLowerCase():
return '/acerca-de';
}
return '';
}
module.exports = getAboutUsLink;
When code in different files
const getAboutUsLink = require("./app"); // file name
describe('getAboutUsLink', () => {
test('should return correct route for en', () => {
expect(getAboutUsLink('en-US')).toBe('/about-us');
});
})
Unit test by TDD
const englishCode = "en-US";
const spanishCode = "es-ES";
function getAboutUsLink(language){
switch (language.toLowerCase()){
case englishCode.toLowerCase():
return '/about-us';
case spanishCode.toLowerCase():
return '/acerca-de';
default:
return new Error('wrong route');
}
}
module.exports = getAboutUsLink;
describe('getAboutUsLink', () => {
test('should return an error', () => {
try {
getAboutUsLink('wrong');
} catch (error) {
expect(error.message).toBe('wrong route');
}
});
})
Testing failed flow
Different methods
function getUserInfo() {
return {
fistName: 'Vic',
lastName: 'Vic2'
}
}
describe('getUserInfo', () => {
test('should return a correct user', () => {
expect(getUserInfo()).toEqual({
fistName: 'Vic',
lastName: 'Vic2'
});
});
});
toEqual
Different methods
spyOn and toHaveBeenCalled
const myObj = {
getUser(id) {
return {
firstName: 'Vic',
lastName: 'Vic2'
}
}
};
describe('myObj', () => {
test('should be called getUser', () => {
const getUserSpy = jest.spyOn(myObj, 'getUser');
myObj.getUser();
expect(getUserSpy).toHaveBeenCalled();
});
test('should be called getUser with params', () => {
const getUserSpy = jest.spyOn(myObj, 'getUser');
myObj.getUser(1);
expect(getUserSpy).toHaveBeenCalledWith(1);
});
});
Complex task with babel
Add import supporting
npm install --save-dev @babel/plugin-transform-modules-commonjs
{
"env": {
"test": {
"plugins": ["@babel/plugin-transform-modules-commonjs"]
}
}
}
Mocking
import { UserStore } from './user'
export function getUserDisplayName(){
const user = UserStore.getUser(1);
return `${user.lastName}, ${user.firstName}`;
}
class User {
getUser(userId){
// logic to get data from a database
return {
firstName: 'Vic',
lastName: 'Vic2'
}
}
setUser(user){
// logic to store data in a database
}
}
let UserStore = new User();
export { UserStore }
Mocking
import { getUserDisplayName } from './app';
jest.mock('./user', () => ({
UserStore: ({
getUser: jest.fn().mockImplementation(arg => ({
firstName: 'Ondrej',
lastName: 'Polesny'
})),
setUser: jest.fn()
})
}));
describe('getUserDisplayName', () => {
test('should return user info', () => {
expect(getUserDisplayName(1)).toBe("Polesny, Ondrej");
});
});
Coverage
Для формирования информации о покрытии тестов используем команду jest --coverage.
"scripts": {
"test": "jest",
"test:coverage": "jest --coverage --collectCoverageFrom=src/**/*.{js,jsx}",
},
После запуска данной команды у нас будет репорт в консоле и также создастся отдельная папка с репортом coverage.
Coverage