Il s'agit d'un guide complet pour assurer la fiabilité de JavaScript et de Node.js. Voici des dizaines de meilleurs articles, livres et outils.
Tout d'abord, traitez les méthodes d'essai généralement acceptées qui sous-tendent toute application. Et puis, vous pouvez vous plonger dans le domaine qui vous intéresse: frontend et interfaces, backend, CI ou tout ce qui précÚde.
Table des matiĂšres
Section 0. RĂšgle d'or
0. RĂšgle d'or: respectez les tests Lean
Que faire. Le code de test est différent de ce qui est mis en service. Rendez-le aussi simple que possible, court, sans abstractions, célibataire, merveilleux au travail et économe. Une autre personne devrait regarder le test et comprendre immédiatement ce qu'il fait.
Nos tĂȘtes sont occupĂ©es par le code de production, elles n'ont pas d'espace libre pour une complexitĂ© supplĂ©mentaire. Si nous enfonçons une nouvelle partie de code complexe dans notre esprit, cela ralentira le travail de toute l'Ă©quipe sur une tĂąche pour laquelle nous testons. En fait, pour cette raison, de nombreuses Ă©quipes Ă©vitent simplement les tests.
Tests - c'est l'occasion d'avoir un assistant sympathique et souriant, avec qui il est trÚs agréable de travailler et qui donne un énorme retour sur de petits investissements. Les scientifiques pensent que dans notre cerveau, il existe deux systÚmes: l'un pour les actions qui ne nécessitent pas d'effort, comme conduire sur une route vide, et le second pour les opérations complexes nécessitant une prise de conscience, telles que la résolution d'équations mathématiques. Créez vos tests pour le premier systÚme, de sorte que lorsque vous regardez le code, vous obtenez une sensation de simplicité comparable à l'édition d'un document HTML, et non avec une solution
2X(17 Ă 24)
.
Cela peut ĂȘtre rĂ©alisĂ© par une sĂ©lection rigoureuse des mĂ©thodes, des outils et des objectifs de test, afin qu'ils soient Ă©conomiques et offrent un retour sur investissement important. Testez seulement autant que nĂ©cessaire, essayez d'ĂȘtre flexible. Parfois, cela vaut mĂȘme la peine de rejeter certains tests et de sacrifier la fiabilitĂ© dans un souci de rapiditĂ© et de simplicitĂ©.

La plupart des recommandations ci-dessous découlent de ce principe.
Ătes-vous prĂȘt?Section 1. Anatomie du test
1.1 Le nom de chaque essai doit ĂȘtre composĂ© de trois parties
Que faire. Le rapport de test doit indiquer si la rĂ©vision actuelle de l'application rĂ©pond aux exigences des personnes qui ne connaissent pas le code: les testeurs impliquĂ©s dans le dĂ©ploiement des ingĂ©nieurs DevOps, ainsi que vous-mĂȘme dans deux ans. Il sera prĂ©fĂ©rable que les tests fournissent des informations dans la langue des exigences et que leurs noms se composent de trois parties:
- Qu'est-ce qui est testé exactement? Par exemple, la méthode
ProductsService.addNewProduct
. - Dans quelles conditions et scénarios? Par exemple, le prix n'est pas transmis à la méthode.
- Quel est le résultat attendu? Par exemple, un nouveau produit n'est pas approuvé.
Sinon. Le déploiement échoue, le test appelé «Ajouter un produit» échoue. Comprenez-vous exactement ce qui fonctionne mal?
Remarque Chaque chapitre a un exemple de code et parfois une illustration. Voir spoilers.
Exemples de codeComment le faire correctement. Le nom du test se compose de trois parties.
1.2 Structurer les tests selon le modĂšle AAA
Que faire. Chaque test doit comprendre trois sections clairement séparées: organiser (préparation), agir (action) et affirmer (résultat). L'adhésion à une telle structure garantit que le lecteur de votre code n'a pas à utiliser le processeur du cerveau pour comprendre le plan de test:
Organiser: tout le code qui amÚne le systÚme à un état selon le scénario de test. Cela peut inclure la création d'une instance du module dans le concepteur de test, l'ajout d'enregistrements à la base de données, la création de stubs au lieu d'objets et tout autre code qui prépare le systÚme pour l'exécution du test.
Act: exécution de code dans le cadre d'un test. Habituellement, une seule ligne.
Affirmer: s'assurer que la valeur obtenue répond aux attentes. Habituellement, une seule ligne.
Sinon. Vous passerez non seulement de longues heures Ă travailler avec le code principal, mais votre cerveau gonflera Ă©galement de ce qui devrait ĂȘtre un travail simple - des tests.
Exemples de codeComment le faire correctement. Un test structuré selon le modÚle AAA.
describe.skip('Customer classifier', () => { test('When customer spent more than 500$, should be classified as premium', () => {
Un exemple d'anti-modÚle. Aucune séparation, en un seul morceau, n'est plus difficile à interpréter.
test('Should be classified as premium', () => { const customerToClassify = {spent:505, joined: new Date(), id:1} const DBStub = sinon.stub(dataAccess, "getCustomer") .reply({id:1, classification: 'regular'}); const receivedClassification = customerClassifier.classifyCustomer(customerToClassify); expect(receivedClassification).toMatch('premium'); });
1.3 Décrire les attentes dans la langue du produit: énoncer dans le style du BDD
Que faire. La programmation des tests dans un style déclaratif permet à l'utilisateur de comprendre immédiatement l'essence sans passer par un seul cycle du processeur cérébral. Lorsque vous écrivez du code impératif emballé dans une logique conditionnelle, le lecteur doit faire beaucoup d'efforts. De ce point de vue, vous devez décrire les attentes dans un langage de type humain dans un style BDD déclaratif en utilisant expect / should et non en utilisant du code personnalisé. Si dans Chai et Jest il n'y a pas d'assertion nécessaire, ce qui est souvent répété, alors vous pouvez
étendre le matcher Jest ou écrire
votre propre plugin pour Chai .
Sinon. L'équipe rédigera moins de tests et décorera les tests ennuyeux
with .skip()
.
Exemples de codeUn exemple utilisant Mocha .
Un exemple d'anti-modÚle. Pour comprendre l'essence du test, l'utilisateur est obligé de passer par un code impératif assez long.
it("When asking for an admin, ensure only ordered admins in results" , ()={
Comment le faire correctement. La lecture de ce test déclaratif est simple.
it("When asking for an admin, ensure only ordered admins in results" , ()={
1.4 Respecter les tests de la boßte noire: tester uniquement les méthodes publiques
Que faire. Tester l'intĂ©rieur entraĂźnera d'Ă©normes frais gĂ©nĂ©raux et ne rapportera presque rien. Si votre code ou votre API fournit les rĂ©sultats corrects, cela vaut-il la peine de passer trois heures Ă tester COMMENT il fonctionne en interne, puis Ă prendre en charge ces tests fragiles? Lorsque vous vĂ©rifiez le comportement public, vous vĂ©rifiez simultanĂ©ment implicitement l'implĂ©mentation elle-mĂȘme, vos tests Ă©chouent uniquement en cas de problĂšme spĂ©cifique (par exemple, sortie incorrecte). Cette approche est Ă©galement appelĂ©e test comportemental. D'un autre cĂŽtĂ©, si vous testez les composants internes (la mĂ©thode de la «boĂźte blanche»), alors au lieu de planifier la sortie des composants, vous vous concentrerez sur les petits dĂ©tails, et vos tests peuvent se casser en raison de petites modifications du code, mĂȘme si les rĂ©sultats sont corrects, mais l'escorte prendra beaucoup plus de ressources.
Sinon. Vos tests se comporteront comme un
garçon criant "Loup!" : Signalez fortement les faux positifs (par exemple, le test échoue en raison d'un changement de nom d'une variable privée). Il n'est pas surprenant que bientÎt les gens commencent à ignorer les notifications CI, et un jour ils manqueront un vrai bug ...
Exemples de codeUn exemple d'anti-modÚle. tester l'intérieur sans raison valable.
Un exemple utilisant Mocha .
class ProductService{
1.5 Choisissez la bonne mise en Ćuvre simulĂ©e: Ă©vitez les faux objets au profit des talons et des espions
Que faire. Les implémentations simulées (test double) sont un mal nécessaire car elles sont associées aux internes de l'application, et certaines sont de grande valeur (
rafraßchissent la mémoire des implémentations imitées: faux objets (mocks), stubs (stubs) et objets espions (espions) ) Cependant, toutes les techniques ne sont pas équivalentes. Les espions et les talons sont conçus pour tester les exigences, mais ont un effet secondaire inévitable - ils affectent également légÚrement l'intérieur. Et les faux objets sont conçus pour tester l'intérieur, ce qui entraßne d'énormes frais généraux, comme décrit au chapitre 1.4.
Avant d'utiliser des implémentations simulées, posez-vous la question la plus simple: "Est-ce que je l'utilise pour tester des fonctionnalités qui sont apparues ou peuvent apparaßtre dans la documentation avec les exigences?" Sinon, ça sent les tests en boßte blanche.
Par exemple, si vous souhaitez savoir si l'application se comporte comme elle le devrait lorsque le service de paiement n'est pas disponible, vous pouvez crĂ©er un talon Ă la place et retourner «Pas de rĂ©ponse» pour vĂ©rifier si le module testĂ© teste la bonne valeur. Vous pouvez donc vĂ©rifier le comportement / la rĂ©ponse / la sortie de l'application dans certains scĂ©narios. Vous pouvez Ă©galement confirmer avec l'aide d'un espion que lorsque le service n'Ă©tait pas disponible, la lettre a Ă©tĂ© envoyĂ©e, il s'agit Ă©galement d'un test de comportement, qui est mieux reflĂ©tĂ© dans la documentation avec les exigences ("Envoyer une lettre si les informations de paiement ne peuvent pas ĂȘtre enregistrĂ©es"). Dans le mĂȘme temps, si vous effectuez un faux service de paiement et assurez-vous qu'il est appelĂ© en utilisant les bons types JS, votre test vise les internes qui ne sont pas liĂ©s Ă la fonctionnalitĂ© de l'application et qui sont susceptibles de changer souvent.
Sinon. Toute refactorisation de code implique la recherche et la mise Ă jour de tous les faux objets dans le code. Les tests d'un ami assistant se transforment en fardeau.
Exemples de codeUn exemple d'anti-modĂšle. Les faux objets sont pour les tripes.
Exemple utilisant Sinon .
it("When a valid product is about to be deleted, ensure data access DAL was called once, with the right product and right config", async () => {
Comment le faire correctement. Les espions sont conçus pour tester les exigences, mais il y a un effet secondaire - ils affectent inévitablement l'intérieur.
it("When a valid product is about to be deleted, ensure an email is sent", async () => {
1.6 N'utilisez pas «foo», utilisez une entrée réaliste
Que faire. Souvent, des bogues de production se produisent avec des données d'entrée trÚs spécifiques et surprenantes. Plus les données sont réalistes pendant les tests, plus elles sont susceptibles de détecter des bogues à temps. Pour générer des données pseudo-réelles qui simulent la variété et le type de données de production, utilisez des bibliothÚques spéciales, par exemple,
Faker . Ces bibliothĂšques peuvent gĂ©nĂ©rer des numĂ©ros de tĂ©lĂ©phone rĂ©alistes, des surnoms d'utilisateurs, des cartes bancaires, des noms de sociĂ©tĂ©s, voire le texte «lorem ipsum». Vous pouvez crĂ©er des tests (en plus des tests unitaires, et non Ă leur place) qui randomisent de fausses donnĂ©es pour adapter le module Ă un test, ou mĂȘme importer des donnĂ©es rĂ©elles Ă partir d'un environnement de production. Envie d'aller encore plus loin? Lisez le chapitre suivant (sur les tests basĂ©s sur les propriĂ©tĂ©s).
Sinon. Vos tests de développement seront réussis en utilisant des entrées synthétiques comme «Foo», et les données de production peuvent se bloquer lorsqu'un pirate
@3e2ddsf . ##' 1 fdsfds . fds432 AAAA
ligne délicate comme
@3e2ddsf . ##' 1 fdsfds . fds432 AAAA
@3e2ddsf . ##' 1 fdsfds . fds432 AAAA
@3e2ddsf . ##' 1 fdsfds . fds432 AAAA
.
Exemples de codeUn exemple d'anti-modÚle. Une suite de tests qui s'exécute avec succÚs en raison de l'utilisation de données irréalistes.
Un exemple utilisant Jest .
const addProduct = (name, price) =>{ const productNameRegexNoSpace = /^\S*$/;
Comment le faire correctement. Rendre aléatoire une entrée réaliste.
it("Better: When adding new valid product, get successful confirmation", async () => { const addProductResult = addProduct(faker.commerce.productName(), faker.random.number());
1.7 Utiliser des tests basés sur les propriétés pour valider plusieurs combinaisons d'entrées
Que faire. Habituellement, pour chaque test, nous sĂ©lectionnons plusieurs Ă©chantillons de donnĂ©es d'entrĂ©e. MĂȘme si le format d'entrĂ©e est similaire aux donnĂ©es rĂ©elles (voir le chapitre «Ne pas utiliser« foo »), nous ne couvrons que quelques combinaisons de donnĂ©es d'entrĂ©e (mĂ©thode
('', true, 1)
, méthode
("string" , false" , 0)
Mais en fonctionnement, une API appelĂ©e avec cinq paramĂštres peut ĂȘtre appelĂ©e avec des milliers de combinaisons diffĂ©rentes, dont l'une peut entraĂźner un
plantage du processus (
fuzzing ). Et si vous pouviez Ă©crire un test qui envoie automatiquement 1000 combinaisons de donnĂ©es d'entrĂ©e et fixant, Ă quelles combinaisons le code ne renvoie pas la bonne rĂ©ponse? La mĂȘme chose que nous faisons avec m todike test basĂ© sur les propriĂ©tĂ©s: en envoyant toutes les combinaisons possibles de donnĂ©es d'entrĂ©e dans l'unitĂ© de test , nous augmenter les chances d'une dĂ©tection de bogue, par exemple, nous avons une mĂ©thode.
addNewProduct(id, name, isDiscount)
Soutenir sa bibliothÚque appellera cette méthode avec un certain nombre de combinaisons.
(, , )
, par exemple,
(1, "iPhone", false)
,
(2, "Galaxy", true)
, etc. Vous pouvez tester en fonction des propriétés à l'aide de votre lanceur de test préféré (Mocha, Jest etc.) et des bibliothÚques comme
js-verify ou
testcheck (il a une bien meilleure documentation). Vous pouvez également
essayer la bibliothÚque de vérification rapide , qui offre des fonctionnalités supplémentaires et est activement accompagnée par l'auteur.
Sinon. Vous choisissez sans réfléchir les données d'entrée pour le test, qui ne couvre que les chemins d'exécution de code qui fonctionnent bien. Malheureusement, cela réduit l'efficacité des tests comme moyen de détecter les erreurs.
Exemples de codeComment le faire correctement. Testez de nombreuses combinaisons avec le test moka.
require('mocha-testcheck').install(); const {expect} = require('chai'); const faker = require('faker'); describe('Product service', () => { describe('Adding new', () => {
1.8 Si nécessaire, utilisez uniquement des plans courts et en ligne.
Que faire. Lorsque vous devez effectuer un
test basé sur des instantanés , utilisez uniquement des instantanés courts sans tout le supplément (par exemple, sur 3 à 7 lignes), en les incluant dans le cadre du test (
instantané en ligne ), et non en tant que fichiers externes. En suivant cette recommandation, vos tests resteront évidents et plus fiables.
D'un autre cÎté, les guides et outils «instantanés classiques» nous poussent à stocker de gros fichiers (par exemple, le balisage pour le rendu des composants ou les résultats de l'API JSON) sur des supports externes et à comparer les résultats avec la version enregistrée à chaque exécution du test. Il peut, par exemple, associer implicitement notre test à 1 000 lignes contenant 3 000 valeurs que l'auteur du test n'a jamais vues et auxquelles il ne s'attendait pas. Pourquoi est-ce mauvais? Parce qu'il y a 1000 raisons pour lesquelles le test échoue. Une seule ligne peut invalider un instantané, ce qui peut se produire souvent. Combien AprÚs chaque espace, commentaire ou modification mineure dans CSS ou HTML. De plus, le nom du test ne vous informera pas de l'échec, car il vérifie seulement que 1000 lignes n'ont pas changé, et encourage également l'auteur du test à prendre aussi longtemps que souhaité un long document qu'il n'a pas pu analyser et vérifier. Ce sont tous les symptÎmes d'un test obscur et hùtif qui n'a pas de tùche claire et essaie de faire trop.
Il convient de noter qu'il existe plusieurs situations dans lesquelles il est acceptable d'utiliser des images longues et externes, par exemple, pour confirmer le schéma, et non les données (extraire des valeurs et se concentrer sur les champs), ou lorsque les documents reçus changent rarement.
Sinon. Les tests d'interface utilisateur Ă©chouent. Le code semble bien, les pixels idĂ©aux sont affichĂ©s Ă l'Ă©cran, alors que se passe-t-il? Vos tests avec des instantanĂ©s ont juste rĂ©vĂ©lĂ© la diffĂ©rence entre le document original et celui qui vient d'ĂȘtre reçu - un caractĂšre d'espace a Ă©tĂ© ajoutĂ© au balisage ...
Exemples de codeUn exemple d'anti-modĂšle. Associer un test Ă quelques 2000 lignes de code inconnues.
it('TestJavaScript.com is renderd correctly', () => {
Comment le faire correctement. Les attentes sont visibles et Ă l'honneur.
it('When visiting TestJavaScript.com home page, a menu is displayed', () => {
1.9 Ăvitez les bancs de test globaux et les donnĂ©es initiales, ajoutez des donnĂ©es Ă chaque test sĂ©parĂ©ment
Que faire. Selon la rÚgle d'or (chapitre 0), chaque test doit ajouter et travailler dans son propre ensemble de lignes dans la base de données afin d'éviter les liaisons, et il était plus facile pour les utilisateurs de comprendre le test. En réalité, les testeurs violent souvent cette rÚgle, avant d'exécuter des tests remplissant la base de données avec des données initiales (graines) (
également appelées «banc d'essai» ) afin d'augmenter la productivité. , (. « »), . . , , (, ).
. , , , ? , , , .
Un exemple d'anti-modÚle. Les tests ne sont pas indépendants et utilisent une sorte de hook global pour obtenir des données globales de la base de données. before(() => {
Comment le faire correctement. Vous pouvez rester dans le test, chaque test ne fonctionne qu'avec ses propres données. it("When updating site name, get successful confirmation", async () => {
1.10 ,
. , - , try-catch-finally , . ( ), .
Chai:
expect(method).to.throw
( Jest:
expect(method).toThrow()
). , , . , , .
. (, CI-) , .
Un exemple d'anti-modÚle. Un cas de test long qui tente de détecter une erreur à l'aide de try-catch. /it("When no product name, it throws error 400", async() => { let errorWeExceptFor = null; try { const result = await addNewProduct({name:'nest'});} catch (error) { expect(error.code).to.equal('InvalidInput'); errorWeExceptFor = error; } expect(errorWeExceptFor).not.to.be.null;
. , , , QA .
it.only("When no product name, it throws error 400", async() => { expect(addNewProduct)).to.eventually.throw(AppError).with.property('code', "InvalidInput"); });
1.11
. :
- smoke-,
- IO-less,
- , , ,
- , pull request', .
, , , #cold #api #sanity. . , Mocha :
mocha â grep 'sanity'
.
. , , , , , , , .
. '#cold-test' (Cold=== , - , ).
1.12
. , Node.js . , Node.
TDD . , , , .
-- , - . , , . , . , , , , (, ..).
. , .
2:
ïž2.1 :
. 10 , . . , 10 (, , ), , ,
? ?
: 2019- , TDD , , , . , , ,
. IoT-, Kafka RabbitMQ, , - . , , ? (, , ), , - .
( ) , , (« API, , !» (consumer-driven contracts)). , : , , , .
: TDD - . TDD , . , .
. ROI, Fuzz, , 10 .
. Cindy Sridharan 'Testing Microservices â the sane way'

Un exemple:
2.2
. , . , . , , ? â . : TDD-, .
«», API, , (, , in-memory ), , , . , , « », .
. , , 20 %.
. Express API ( ).

2.3 , API
. , ( ). - , ! â , , . «
-22 » : , , .
(consumer-driven contracts) PACT : , ⊠! PACT â «», . PACT- â . , API CI, .
. â .
.
2.4
. , Express-. . , , , JS- {req,res}. , (,
Sinon ) {req,res}, , .
node-mock-http {req,res} . , , HTTP-, res- (. ).
. Express- === .
2.5
. . CI- , . (, ), (, ), .
Sonarqube (2600+
)
Code Climate (1500+
). ::
Keith Holliday. , .
. CodeClimate, :

2.6 , Node
. , . ( ) . , - , ? ? , API 50 % ? , Netflix - (
Chaos Engineering ). : , . , Netflix,
chaos monkey , , , , - ( Kubernetes
kube-monkey , ). , . , , Node- , , v8 1,7 , UX , ?
node-chaos (-), , Node.
. , production .
. Node-chaos , Node.js, .

2.7 ,
. ( 0), , , . , (seeds) (
« » ) . , (. « »), , . . , , (, ).
. , , , ? , , , .
. - .
before(() => {
. , .
it("When updating site name, get successful confirmation", async () => {
3:
3.1. UI
. , , , . , , ( HTML CSS) . , (, , , ), , , .
. 10 , 500 (100 = 1 ) - - .
. .
test('When users-list is flagged to show only VIP, should display only VIP members', () => {
. UI . test('When flagging to show only VIP, should display only VIP members', () => {
3.2 HTML- ,
. HTML- , . , , CSS-. , 'test-id-submit-button'. . , , .
. , , . â , , Ajax . . , CSS 'thick-border' 'thin-border'
. , .
. CSS-.
<!-- the markup code (part of React component) --> <span id="metric" className="d-flex-column">{value}</span> <!-- what if the designer changes the classs? -->
3.3
. , , . , , . , â - , (.
« » ). (, ) , .
, : , . ( ) . , .
. , . ?
. .
class Calendar extends React.Component { static defaultProps = {showFilters: false} render() { return ( <div> A filters panel with a button to hide/show filters <FiltersPanel showFilter={showFilters} title='Choose Filters'/> </div> ) } } //Examples use React & Enzyme test('Realistic approach: When clicked to show filters, filters are displayed', () => { // Arrange const wrapper = mount(<Calendar showFilters={false} />) // Act wrapper.find('button').simulate('click'); // Assert expect(wrapper.text().includes('Choose Filter')); // This is how the user will approach this element: by text })
. .
test('Shallow/mocked approach: When clicked to show filters, filters are displayed', () => {
3.4 .
. (, ). (,
setTimeOut
) , . (,
Cypress cy.request('url') ), API,
wait(expect(element)) @testing-library/DOM . , API, , . , ,
hurry-up the clock . â , , ( ). , , - npm- , ,
wait-for-expect .
. , . , . .
. E2E API (Cypress).
. , DOM- (@testing-library/dom).
. .
test('movie title appears', async () => {
3.5.
. - , . , , . :
pingdom , AWS CloudWatch
gcp StackDriver , , SLA. , , (,
lighthouse ,
pagespeed ), . â , :
,
(TTI) . , , , , , DOM, SSL . , CI, 247 CDN.
. , , , , - CDN.
. Lighthouse .

3.6 API
. ( 2), , , ( ). API (,
Sinon ,
Test doubles ), API. . API , ( ). API, . , , API . , : .
. , API 100 , 20 .
3.7 ,
. E2E (end-to-end, ) UI (. 3.6). , , . , , - . , â (, ), . - , , UI-
Cypress Pupeteer . , : 50 , , . 10 . , , , â . , .
. UI , , ( , UI) .
3.8
. , API , , . (before-all), - . , : . , . - API- . , . (, ), , , . , : , API (. 3.6).
. , 200 , 100 , 20 .
. (before-all), (before-each) (, Cypress).
Cypress .
let authenticationToken;
3.9 smoke-,
. production- , , . , , , , . smoke- . production, , , . , smoke- , .
. , , production . /Payment.
. Smoke- .
it('When doing smoke testing over all page, should load them all successfully', () => {
3.10
. , . «» , , , , . , ( ) , , -, , , . « », .
. ,
Cucumber JavaScript .
StoryBook UI- , (, , , ..) , . , , .
. , .
. cucumber-js.
. Storybook , .

3.11
. , . , . , . , - . , . , , , . , - . UI « ». , (,
wraith , PhantomCSS), . (,
Applitools ,
Perci.io ) , , « » (, ), DOM/CSS, .
. , ( ) , ?
. : , .

. wraith UI.
â# Add as many domains as necessary. Key will act as a labelâ domains: english: "http://www.mysite.com"â â# Type screen widths below, here are a couple of examplesâ screen_widths: - 600â - 768â - 1024â - 1280â â# Type page URL paths below, here are a couple of examplesâ paths: about: path: /about selector: '.about'â subscribe: selector: '.subscribe'â path: /subscribe
4:
4.1 (~80 %),
. â , . , . â (, ), . ? , 10-30 % . 100 % , . . , : Airbus, ; , 50 % . , , 80 % (
Fowler: «in the upper 80s or 90s» ), , , .
: (CI), (
Jest ) , . , . , ( ) â . , â , , . , .
. . , , . .
.
. ( Jest).

4.2 ,
. , . , , , , . , , - , .
PricingCalculator
, , , 10 000 ⊠, , . , . 80- , . : , , , . , - .
. , , , .
. ? , QA . : , - . , - API .

4.3
. : 100 %, . ? , , , . . - : , , , .
, . JavaScript-
Stryker :
- « ». ,
newOrder.price===0
newOrder.price!=0
. «» .
- , , : , . , , .
, , , .
. , 85- 85 % .
. 100 %, 0 %.
function addNewOrder(newOrder) { logger.log(`Adding new order ${newOrder}`); DB.save(newOrder); Mailer.sendMail(newOrder.assignee, `A new order was places ${newOrder}`); return {approved: true}; } it("Test addNewOrder, don't use such test names", () => { addNewOrder({asignee: "John@mailer.com",price: 120}); });
. Stryker reports, , ().

4.4 -
. ESLint. ,
eslint-plugin-mocha , (
describe()
),
, .
eslint-plugin-jest , ( ).
. 90- , , , . , .
. , , .
describe("Too short description", () => { const userToken = userService.getDefaultToken()
5: CI
5.1 ,
. â . , . , ( !). , . (
ESLint standard Airbnb ), . ,
eslint-plugin-chai-expect , .
Eslint-plugin-promise ( ).
Eslint-plugin-security , DOS-.
eslint-plugin-you-dont-need-lodash-underscore , , V8, ,
Lodash._map(âŠ)
.
. , , . Que se passe-t-il? , , . . , , .
. , . , ESLint production-.

5.2
. CI , , ..? ,
. Pourquoi? : (1) -> (2) -> (3) . , , .
, , , , - .
CI- ( ,
CircleCI local CLI ) . ,
wallaby , ( ) . npm- package.json, , (, , , ). (non-zero exit code)
concurrently . â ,
npm run quality
. githook (
husky ).
. , .
. Npm-, , , .
"scripts": { "inspect:sanity-testing": "mocha **/**--test.js --grep \"sanity\"", "inspect:lint": "eslint .", "inspect:vulnerabilities": "npm audit", "inspect:license": "license-checker --failOn GPLv2", "inspect:complexity": "plato .", "inspect:all": "concurrently -c \"bgBlue.bold,bgMagenta.bold,yellow\" \"npm:inspect:quick-testing\" \"npm:inspect:lint\" \"npm:inspect:vulnerabilities\" \"npm:inspect:license\"" }, "husky": { "hooks": { "precommit": "npm run inspect:all", "prepush": "npm run inspect:all" } }
5.3 production-
. â CI-. . â
Docker-compose . (, ) production-.
AWS Local AWS-.
, serverless
AWS SAM Faas-.
Kubernetes CI-, . , « Kubernetes»
Minikube MicroK8s , , . « Kubernetes»: CI- (,
Codefresh ) Kubernetes-, CI- ; .
. .
: CI-, Kubernetes-
(Dynamic-environments Kubernetes )
deploy: stage: deploy image: registry.gitlab.com/gitlab-examples/kubernetes-deploy script: - ./configureCluster.sh $KUBE_CA_PEM_FILE $KUBE_URL $KUBE_TOKEN - kubectl create ns $NAMESPACE - kubectl create secret -n $NAMESPACE docker-registry gitlab-registry --docker-server="$CI_REGISTRY" --docker-username="$CI_REGISTRY_USER" --docker-password="$CI_REGISTRY_PASSWORD" --docker-email="$GITLAB_USER_EMAIL" - mkdir .generated - echo "$CI_BUILD_REF_NAME-$CI_BUILD_REF" - sed -e "s/TAG/$CI_BUILD_REF_NAME-$CI_BUILD_REF/g" templates/deals.yaml | tee ".generated/deals.yaml" - kubectl apply --namespace $NAMESPACE -f .generated/deals.yaml - kubectl apply --namespace $NAMESPACE -f templates/my-sock-shop.yaml environment: name: test-for-ci
5.4
. , , . , 500 , , . , CI- (
Jest ,
AVA Mocha ) , . CI- (!), . , CLI , , .
. â , .
5.5
. , . 10 ? CI- npm-
license check plagiarism check ( ), , , Stackoveflow .
. , , .
.

5.6
. , Express, .
npm audit ,
snyk ( ). CI .
. . .
: NPM Audit

5.7
. package-lock.json Yarn npm ( ): .
npm install
npm update
, . , â . , package.json
ncu .
, . :
- CI , , npm outdated npm-check-updates (ncu). .
- , pull request' .
: ? , ( ,
eslint-scope ). « »:
latest , , (, 1.3.1, â 1.3.8).
. , .
5.8 CI-, Node
. , Node . , Node.
- . , Jenkins .
- Docker.
- , . . smoke-, (, , ) .
- , , , , , .
- , . , -. - ( ).
- . .
- , , .
- (, Docker-).
- , .
node_modules
.
. , .
5.9 : CI-, Node
. , , . Node, CI . , MySQL, Postgres. CI- «», MySQl, Postgres Node. , - (, ). CI, , .
. - ?
: Travis ( CI) Node.
language: node_js node_js: - "7" - "6" - "5" - "4" install: - npm install script: - npm run test