Test des projets Node.js. Partie 1. Anatomie d'essai et types d'essai

L'auteur du matériel, dont nous publions aujourd'hui la première partie de la traduction, dit qu'en tant que consultant indépendant sur Node.js, il analyse plus de 10 projets chaque année. Ses clients, ce qui est tout à fait justifié, lui demandent de porter une attention particulière aux tests. Il y a quelques mois, il a commencé à prendre des notes concernant les techniques de test précieuses et les erreurs qu'il a rencontrées. Le résultat était un matériel contenant trois douzaines de recommandations pour les tests.

image

En particulier, il se concentrera sur la sélection des types de tests qui conviennent à une situation particulière, sur leur conception appropriée, sur l'évaluation de leur efficacité et sur l'endroit exact dans les chaînes CI / CD dont vous avez besoin pour les placer. Certains des exemples ici sont illustrés en utilisant Jest, certains en utilisant Mocha. Ce matériel est principalement axé non pas sur les outils, mais sur la méthodologie de test.

Test des projets Node.js. Partie 2. Évaluation des performances des tests, intégration continue et analyse de la qualité du code

▍0. Règle d'or: les tests doivent être très simples et directs


Connaissez-vous quelqu'un - un ami, un membre de la famille, le héros du film, qui est toujours chargé de bonne humeur et toujours prêt à offrir un coup de main sans rien exiger en retour? C'est ainsi que de bons tests doivent être conçus. Ils doivent être simples, bénéfiques et susciter des émotions positives. Ceci peut être réalisé par une sélection rigoureuse des méthodes de test, des outils et des objectifs. Ceux dont l'utilisation justifie le temps et les efforts consacrés à la préparation et à la réalisation des tests et donne en même temps de bons résultats. Vous n'avez qu'à tester ce qui doit être testé, vous devez vous efforcer de vous assurer que les tests sont simples et flexibles, et parfois vous pouvez refuser certains tests, sacrifiant ainsi la fiabilité du projet pour sa simplicité et sa rapidité de développement.

Les tests ne doivent pas être considérés comme du code d'application normal. Le fait est qu'une équipe typique engagée dans le développement d'un projet, dans tous les cas, fait tout son possible pour le maintenir en état de fonctionnement, c'est-à-dire s'efforce, disons, d'un produit commercial pour fonctionner comme l'attendent ses utilisateurs. Par conséquent, une telle équipe peut ne pas avoir le sentiment qu'il devra soutenir un autre «projet» complexe représenté par un ensemble de tests. Si les tests du code principal se développent, attirant de plus en plus l'attention sur eux-mêmes et devenant une source de préoccupation constante, alors le travail sur eux sera soit abandonné, soit en essayant de maintenir un niveau décent, cela leur donnera tellement de temps et d'énergie que cela ralentira le travail sur le projet principal.

Par conséquent, le code de test doit être aussi simple que possible, avec un nombre minimum de dépendances et de niveaux d'abstraction. Les tests doivent ressembler pour pouvoir être compris en un coup d'œil. La plupart des recommandations que nous examinerons ici découlent de ce principe.

Section 1. Anatomie des tests


▍1. Concevez vos tests de sorte que le rapport vous indique ce qui est testé, dans quel scénario et ce qui est attendu des tests


Recommandations


Le rapport de test doit indiquer si la version actuelle de l'application répond à ses exigences. Cela doit être fait sous une forme qui sera compréhensible pour ceux qui n'ont pas à se familiariser avec le code d'application. Il peut s'agir d'un testeur, d'un spécialiste DevOps qui déploie le projet ou du développeur lui-même, qui a examiné le projet quelque temps après avoir écrit son code. Cela peut être réalisé si, lors de la rédaction des tests, se concentrer sur les exigences du produit. Avec cette approche, la structure du test peut être imaginée en trois parties:

  1. Qu'est-ce qui est testé exactement? Par exemple, la méthode ProductsService.addNewProduct .
  2. Dans quel scénario et dans quelles circonstances le test est-il effectué? Par exemple, la réaction du système est vérifiée dans une situation où le prix des marchandises n'a pas été transmis à la méthode.
  3. Quels sont les résultats des tests attendus? Par exemple, dans une situation similaire, le système refuse de confirmer l'ajout d'un nouveau produit à celui-ci.

Conséquences de la dérogation aux recommandations


Supposons que le système ne puisse pas être déployé, et à partir du rapport de test, vous pouvez seulement découvrir qu'il n'a pas réussi le test appelé Add product , qui vérifie l'ajout d'un certain produit à celui-ci. Cela donnera-t-il des informations sur ce qui s'est exactement passé?

Bonne approche


Les informations de test se composent de trois éléments d'information.

 //1.   describe('Products Service', function() { //2.  describe('Add new product', function() {   // 3. ,       it('When no price is specified, then the product status is pending approval', ()=> {     const newProduct = new ProductService().add(...);     expect(newProduct.status).to.equal('pendingApproval');   }); }); }); 

Bonne approche


Le rapport de test ressemble à un document contenant une déclaration des exigences du produit.

Voici à quoi cela ressemble à différents niveaux.


Document sur les exigences du produit, dénomination des tests, résultats des tests

  1. Un document avec les exigences du produit peut être, en fait, un document spécial, ou il peut exister sous la forme d'un e-mail.
  2. Lorsque vous nommez des tests, décrivez l'objectif du test, son scénario et les résultats attendus, vous devez respecter le langage utilisé pour formuler les exigences du produit. Cela vous aidera à comparer le code de test et les exigences du produit.
  3. Les résultats des tests doivent être clairs même pour ceux qui ne connaissent pas le code d'application ou qui l'ont complètement oublié. Ce sont des testeurs, des spécialistes DevOps, des développeurs qui retournent travailler avec le code quelques mois après l'avoir écrit.

▍2. Décrivez ce que vous attendez des tests dans le langage du produit: utilisez des instructions de style BDD


Recommandations


Le développement de tests dans un style déclaratif permet à ceux qui travaillent avec eux de saisir instantanément leur essence. Si les tests sont écrits en utilisant une approche impérative, ils sont remplis de constructions conditionnelles qui compliquent grandement leur compréhension. Selon ce principe, les attentes doivent être décrites dans un langage proche de l'ordinaire. Le style BDD déclaratif utilise des constructions expect ou should , plutôt qu'un code spécial de leur propre conception. S'il n'y a pas de déclarations nécessaires dans Chai ou Jest, et qu'il s'avère que de telles déclarations sont souvent nécessaires, envisagez d' ajouter de nouveaux «chèques» à Jest ou d'écrire vos propres plugins pour Chai .

Conséquences de la dérogation aux recommandations


Si vous ne suivez pas les recommandations décrites ci-dessus, cela se terminera par le fait que les membres de l'équipe de développement écriront moins de tests et .skip() les vérifications ennuyeuses à l'aide de la méthode .skip() .

Mauvaise approche


Le lecteur de ce test devra examiner entièrement le code impératif assez long uniquement pour comprendre ce qui est testé exactement dans le test.

 it("When asking for an admin, ensure only ordered admins in results" , ()={   //,       — "admin1"  "admin2",   "user1"   const allAdmins = getUsers({adminOnly:true});   const admin1Found, adming2Found = false;   allAdmins.forEach(aSingleUser => {       if(aSingleUser === "user1"){           assert.notEqual(aSingleUser, "user1", "A user was found and not admin");       }       if(aSingleUser==="admin1"){           admin1Found = true;       }       if(aSingleUser==="admin2"){           admin2Found = true;       }   });   if(!admin1Found || !admin2Found ){       throw new Error("Not all admins were returned");   } }); 

Bonne approche


Vous pouvez littéralement comprendre ce test en un coup d'œil.

 it("When asking for an admin, ensure only ordered admins in results" , ()={   //,        const allAdmins = getUsers({adminOnly:true});     expect(allAdmins).to.include.ordered.members(["admin1" , "admin2"]) .but.not.include.ordered.members(["user1"]); }); 

▍3. Effectuer des tests de code linting à l'aide de plugins spéciaux


Recommandations


Il existe un ensemble de plug-ins pour ESLint conçus spécifiquement pour analyser le code de test et pour trouver des problèmes dans ce code. Par exemple, le plug-in eslint-plugin-mocha donnera des avertissements si le test est écrit au niveau global (et n'est pas un descendant de describe() ), ou si les tests s'avèrent être ignorés , ce qui peut donner de faux espoirs que tous les tests s'avèrent être réussis. Le plugin eslint-plugin-jest fonctionne de manière similaire, par exemple, en avertissant des tests qui n'ont pas d'instructions, c'est-à-dire de ceux qui ne vérifient rien.

Conséquences de la dérogation aux recommandations


Le développeur sera heureux de voir que le code est couvert à 90% dans les tests et que 100% des tests réussissent. Cependant, il ne restera dans cet état que jusqu'à ce qu'il s'avère que de nombreux tests, en fait, ne vérifient rien, et que certains scripts de test sont simplement ignorés. On ne peut qu'espérer que personne ne déploiera des projets «testés» de cette manière en production.

Mauvaise approche


Le scénario de test est plein d'erreurs qui, heureusement, peuvent être détectées à l'aide du linter.

 describe("Too short description", () => { const userToken = userService.getDefaultToken() // *error:no-setup-in-describe, use hooks (sparingly) instead it("Some description", () => {});//* error: valid-test-description. Must include the word "Should" + at least 5 words }); it.skip("Test name", () => {// *error:no-skipped-tests, error:error:no-global-tests. Put tests only under describe or suite expect("somevalue"); // error:no-assert }); it("Test name", () => {*//error:no-identical-title. Assign unique titles to tests }); 

▍4. Respectez la méthode de la boîte noire - testez uniquement les méthodes publiques


Recommandations


Tester certains mécanismes de code interne signifie une augmentation significative de la charge sur les développeurs et ne donne presque aucun avantage. Si une certaine API produit les bons résultats, vaut-il la peine de passer plusieurs heures à tester ses mécanismes internes et à continuer à supporter ces tests, qui se cassent très facilement, à jour? Lors du test des méthodes accessibles au public, leur implémentation interne, bien qu'implicitement, est également vérifiée. Un tel test donnera une erreur si un problème survient dans le système, ce qui entraîne l'émission de données incorrectes. Cette approche est également appelée «test comportemental». D'autre part, en testant les mécanismes internes d'une certaine API (c'est-à-dire en utilisant la technique de la «boîte blanche»), le développeur se concentre sur les petits détails de l'implémentation, et non sur le résultat final du code. Les tests qui vérifient de telles subtilités peuvent commencer à générer des erreurs, par exemple, après une petite refactorisation de code, même si le système continue de produire des résultats corrects. En conséquence, cette approche augmente considérablement la charge du programmeur associée à la prise en charge du code de test.

Conséquences de la dérogation aux recommandations


Les tests qui tentent de capturer les mécanismes internes d'un certain système se comportent comme un berger d'une fable qui appelait les paysans avec des cris de «Help! Loup! »Quand il n'y avait pas de loup à proximité. Les gens ont couru à l'aide pour découvrir qu'ils avaient été trompés. Et quand le loup est vraiment apparu, personne n'est venu à la rescousse. De tels tests produisent des résultats faussement positifs, par exemple, dans les cas où les noms de certaines variables internes changent. En conséquence, il n'est pas surprenant que celui qui procède à ces tests commence bientôt à ignorer leurs "cris", ce qui, finalement, conduit au fait qu'une fois qu'une véritable erreur grave peut passer inaperçue.

Mauvaise approche


Ce test teste les mécanismes internes d'une classe sans raison particulière pour de tels contrôles.

 class ProductService{ //      //     ,      calculateVAT(priceWithoutVAT){   return {finalPrice: priceWithoutVAT * 1.2};   //           } //  getPrice(productId){   const desiredProduct= DB.getProduct(productId);   finalPrice = this.calculateVATAdd(desiredProduct.price).finalPrice; } } it("White-box test: When the internal methods get 0 vat, it return 0 response", async () => {   //       VAT,      .  ,   ,        expect(new ProductService().calculateVATAdd(0).finalPrice).to.equal(0); }); 

▍5. Choisissez les objets de sauvegarde appropriés: évitez les foules, préférant les talons et les espions


Recommandations


L'utilisation de test double lorsque le test est un mal nécessaire, car ils sont associés aux mécanismes internes de l'application. Sans certains d'entre eux, c'est tout simplement impossible à faire. Voici du matériel utile sur ce sujet. Cependant, diverses approches de l'utilisation de tels objets ne peuvent pas être qualifiées d'équivalentes. Ainsi, certains d'entre eux - les talons (talon) et les espions (espion), visent à tester les exigences du produit, mais, comme effet secondaire inévitable, ils sont obligés d'affecter légèrement les mécanismes internes de ce produit. Les simulations, d'autre part, visent à tester les mécanismes internes du projet. Par conséquent, leur utilisation entraîne une énorme charge inutile sur les programmeurs, dont nous avons parlé ci-dessus, offrant d'adhérer à la méthodologie de la "boîte noire" lors de l'écriture des tests.

Avant d'utiliser des objets en double, posez-vous une question simple: "Est-ce que je les utilise pour tester la fonctionnalité qui est décrite, ou pourrait-elle être décrite dans les exigences techniques du projet?". Si la réponse à cette question est négative, cela peut signifier que vous allez tester le produit en utilisant l'approche de la «boîte blanche», dont nous avons déjà parlé des lacunes.

Par exemple, si vous souhaitez savoir si votre application fonctionne correctement dans une situation où un service de paiement n'est pas disponible, vous pouvez arrêter ce service et faire en sorte que l'application reçoive quelque chose indiquant qu'il n'y a pas de réponse. Cela vous permettra de vérifier la réaction du système à une situation similaire, pour savoir s'il se comporte correctement. Au cours d'un tel test, une vérification est faite du comportement, ou de la réponse, ou du résultat de l'application dans certaines conditions. Dans cette situation, vous pouvez utiliser l'espion pour vérifier si, lors de la détection d'une chute dans le service de paiement, un certain e-mail a été envoyé. Il s’agit là encore d’une vérification du comportement du système dans une certaine situation, qui, à coup sûr, est enregistrée dans les exigences techniques de celui-ci, par exemple, sous la forme suivante: «Envoyez un e-mail à l’administrateur si le paiement n’est pas effectué». D'autre part, si vous utilisez un objet simulé pour représenter un service de paiement et vérifiez l'opération lors de l'accès avec le transfert de ce qu'il attend de lui, alors nous parlerons de tester des mécanismes internes qui ne sont pas directement liés à la fonctionnalité de l'application, et, tout à fait peut peut-être changer souvent.

Conséquences de la dérogation aux recommandations


Avec tout refactoring de code, vous devrez rechercher tous les moki, refactoring et leur code. En conséquence, le test de support deviendra un lourd fardeau, ce qui en fera des ennemis du développeur, pas de ses amis.

Mauvaise approche


Cet exemple montre un objet factice concentré sur le test des mécanismes internes de l'application.

 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 () => {   //,        const dataAccessMock = sinon.mock(DAL);   // ,           dataAccessMock.expects("deleteProduct").once().withArgs(DBConfig, theProductWeJustAdded, true, false);   new ProductService().deletePrice(theProductWeJustAdded);   mock.verify(); }); 

Bonne approche


Les espions visent à tester la conformité des systèmes avec leurs exigences, mais, comme effet secondaire, ils affectent inévitablement les mécanismes internes des systèmes.

 it("When a valid product is about to be deleted, ensure an email is sent", async () => {   //,        const spy = sinon.spy(Emailer.prototype, "sendEmail");   new ProductService().deletePrice(theProductWeJustAdded);   //  .       ? ,               (  ) }); 

▍6. Pendant les tests, utilisez une entrée réaliste, non limitée à quelque chose comme "foo"


Recommandations


Souvent, les erreurs de production se manifestent dans une combinaison de circonstances très spécifique et même surprenante. Et cela signifie que plus les données d'entrée utilisées lors des tests sont proches de la réalité, plus la probabilité d'une détection précoce des erreurs est élevée. Permet de générer des données ressemblant à de véritables bibliothèques spécialisées telles que Faker . Par exemple, ces bibliothèques génèrent des numéros de téléphone, des noms d'utilisateur, des numéros de cartes bancaires, des noms d'entreprises et même des textes «lorem ipsum» aléatoires mais réalistes. En outre, envisagez d'utiliser les données des environnements de production dans les tests. Si vous souhaitez porter ces tests à un niveau encore plus élevé, reportez-vous à notre prochaine recommandation sur les tests basés sur les propriétés.

Conséquences de la dérogation aux recommandations


Lors du test d'un projet au cours de son développement, tous les tests ne peuvent être réussis que s'ils sont effectués à l'aide de données irréalistes comme les lignes «foo». Mais en production, le système échouera dans une situation où le pirate lui donnera quelque chose comme @3e2ddsf . ##' 1 fdsfds . fds432 AAAA @3e2ddsf . ##' 1 fdsfds . fds432 AAAA @3e2ddsf . ##' 1 fdsfds . fds432 AAAA .

Mauvaise approche


Le système réussit ces tests uniquement parce qu'ils utilisent des données irréalistes.

 const addProduct = (name, price) =>{ const productNameRegexNoSpace = /^\S*$/;//  if(!productNameRegexNoSpace.test(name))   return false;// , -   ,  .     //  -    return true; }; it("Wrong: When adding new product with valid properties, get successful confirmation", async () => {   // "Foo",    ,    ,    false   const addProductResult = addProduct("Foo", 5);   expect(addProductResult).to.be.true;   // :     - ,     //         }); 

Bonne approche


Il utilise des données randomisées similaires aux données réelles.

 it("Better: When adding new valid product, get successful confirmation", async () => {   const addProductResult = addProduct(faker.commerce.productName(), faker.random.number());   //   : {'Sleek Cotton Computer',  85481}   expect(addProductResult).to.be.true;   //  ,         ,    .   //     ,    ! }); 

▍ 7. Systèmes de test utilisant plusieurs combinaisons d'entrées à l'aide de tests basés sur les propriétés


Recommandations


En règle générale, les tests utilisent de petits ensembles de données d'entrée. Même s'ils ressemblent à des données réelles (nous en avons parlé dans la section précédente), ces tests ne couvrent qu'un nombre très limité de combinaisons possibles d'entrées de l'entité étudiée. Par exemple, cela pourrait ressembler à ceci: (method('', true, 1), method("string" , false" , 0)) . Le problème est que dans l'API de production, qui est appelée avec cinq paramètres, elle peut obtenir l'entrée de milliers de variantes différentes de leurs combinaisons, dont l'une peut entraîner un échec (il serait approprié de rappeler le flou ici ). Que faire si vous pouviez écrire un seul test qui vérifie automatiquement une certaine méthode pour 1000 combinaisons de ses entrées et découvre laquelle est-ce que la méthode ne répond pas correctement? nous dans une telle situation est utile. A savoir, au cours de ce module vérifie d'essai, appelant avec toutes les combinaisons possibles de données d'entrée, ce qui augmente la probabilité de trouver quelques bugs. Supposons que nous ayons une méthode addNewProduct(id, name, isDiscount) et Bibliothèque effectuer des tests, l'appelle avec de nombreuses combinaisons de paramètres de type numérique, chaîne et logique, par exemple - (1, "iPhone", false) , (2, "Galaxy", true) . Il est possible d'effectuer des tests basés sur la vérification des propriétés en utilisant l'environnement d'exécution de test habituel (Mocha, Jest, etc.) et en utilisant des bibliothèques spécialisées comme js-verify ou testcheck (cette bibliothèque a une très bonne documentation).

Conséquences de la dérogation aux recommandations


Le développeur, inconsciemment, sélectionne ces données de test qui ne couvrent que les parties du code qui fonctionnent correctement. Malheureusement, cela réduit l'efficacité des tests comme moyen de détecter les erreurs.

Bonne approche


Test de nombreuses options d'entrée à l'aide de la bibliothèque mocha-testcheck.

 require('mocha-testcheck').install(); const {expect} = require('chai'); const faker = require('faker'); describe('Product service', () => { describe('Adding new', () => {   //  100         check.it('Add new product with random yet valid properties, always successful',     gen.int, gen.string, (id, name) => {       expect(addNewProduct(id, name).status).to.equal('approved');     }); }) }); 

▍8. Efforcez-vous que le code de test soit autosuffisant, minimisant les aides externes et les abstractions


Recommandations


Il est probablement maintenant évident que je m'engage à des tests extrêmement simples. Le fait est qu'autrement, l'équipe de développement d'un certain projet doit en fait gérer un autre projet. Pour comprendre son code, ils doivent passer un temps précieux, qu'ils n'ont pas tant. Il est très bien écrit sur ce phénomène: «Un code de production de haute qualité est un code bien pensé, et un code de test de haute qualité est un code tout à fait compréhensible ... Lorsque vous écrivez un test, pensez à qui verra le message d'erreur affiché par lui. Cette personne ne voudrait pas, pour comprendre les causes de l'erreur, lire le code de l'ensemble de la suite de tests ou le code de l'arbre d'héritage des utilitaires utilisés pour les tests. "

Pour que le lecteur comprenne le test sans quitter son code, minimisez l'utilisation d'utilitaires, de crochets ou de tout mécanisme externe lors de l'exécution du test. Si pour ce faire, vous devez recourir trop souvent au copier-coller de code, vous pouvez vous arrêter à un mécanisme auxiliaire externe, dont l'utilisation ne violera pas l'intelligibilité du test. Mais, si le nombre de ces mécanismes augmente, le code de test perdra sa compréhensibilité.

Conséquences de la dérogation aux recommandations


, 4 , 2 , ? ! , , .


. ?

 test("When getting orders report, get the existing orders", () => {   const queryObject = QueryHelpers.getQueryObject(config.DBInstanceURL);   const reportConfiguration = ReportHelpers.getReportConfig();//   ?        userHelpers.prepareQueryPermissions(reportConfiguration);//  ?         const result = queryObject.query(reportConfiguration);   assertThatReportIsValid();//  ,           -    expect(result).to.be.an('array').that.does.include({id:1, productd:2, orderStatus:"approved"});   //      ?        }) 

Bonne approche


, .

 it("When getting orders report, get the existing orders", () => {   // ,           const orderWeJustAdded = ordersTestHelpers.addRandomNewOrder();   const queryObject = newQueryObject(config.DBInstanceURL, queryOptions.deep, useCache:false);   const result = queryObject.query(config.adminUserToken, reports.orders, pageSize:200);   expect(result).to.be.an('array').that.does.include(orderWeJustAdded); }) 

▍9. :


Recommandations


, , , , . . , ( ) . — , ( , ). — , , , , . , , . — , , , , ( , , , ).

Conséquences de la dérogation aux recommandations


, . . . . , , , .


. , .

 before(() => { //       .   ? - ,  -   json-. await DB.AddSeedDataFromJson('seed.json'); }); it("When updating site name, get successful confirmation", async () => { // ,  ,  "Portal", ,           const siteToUpdate = await SiteService.getSiteByName("Portal"); const updateNameResult = await SiteService.changeName(siteToUpdate, "newName"); expect(updateNameResult).to.be(true); }); it("When querying by site name, get the right site", async () => { // ,  ,  "Portal", ,           const siteToCheck = await SiteService.getSiteByName("Portal"); expect(siteToCheck.name).to.be.equal("Portal"); //!      :[ }); 

Bonne approche


, , .

 it("When updating site name, get successful confirmation", async () => { //           const siteUnderTest = await SiteService.addSite({   name: "siteForUpdateTest" }); const updateNameResult = await SiteService.changeName(siteUnderTest, "newName"); expect(updateNameResult).to.be(true); }); 

▍10. , . expect


Recommandations


, , try-catch-finally catch . , , , .

Chai, expect(method).to.throw . Jest: expect(method).toThrow() . , . , , .

Conséquences de la dérogation aux recommandations


, , , .


, 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; //    ,         //  ,     null,       }); 

Bonne approche


expect , , .

 it.only("When no product name, it throws error 400", async() => { expect(addNewProduct)).to.eventually.throw(AppError).with.property('code', "InvalidInput"); }); 

▍11. ,


Recommandations


. , (smoke test), -, , . - . , , , #cold , #api , #sanity . . , Mocha -g ( --grep ).

Conséquences de la dérogation aux recommandations


, , , , , , . .

Bonne approche


#cold-test , . , -, , — .

 //    ( ,    ),     // ,        //   describe('Order service', function() { describe('Add new order #cold-test #sanity', function() {   it('Scenario - no currency was supplied. Expectation - Use the default currency #sanity', function() {     //-    }); }); }); 

▍12.


Recommandations


, Node.js-. , , Node.js .

TDD — , , . , . , , Red-Green-Refactor . , - , , , , , . , . ( — , , ).

Conséquences de la dérogation aux recommandations


— , . .

2.


▍13. ,


Recommandations


, , 10 , . , . , . , (, ), , , , ? - ?

, . , 2019 , , TDD, — , . , , , . , IoT-, , , - Kafka RabbitMQ, . - , , , . , , , , ? (, , Alexa) , , .

, ( ). , , , , , , . , , - API — Consumer-Driven Contracts . , , , , . , , , , , . , , .

, TDD . , TDD , . , , , .

Conséquences de la dérogation aux recommandations


— ( ), .

Bonne approche


. . , , Node.js, .

▍14. ,


Recommandations


. — . , , . , , - , , - ? , . , : TDD, — .

«». API, - , (, , , , , ). , , , (, ). , , , , , , .

Conséquences de la dérogation aux recommandations


, , , , 20.

Bonne approche


supertest , API, Express, .


API, Express

▍15. , API, Consumer-Driven Contracts


Recommandations


, , , , . , , - , , , - . «-22» : . , , . , Consumer-Driven Contracts PACT .

. . PACT , ( «»). , , PACT, , , . , , , , .

Conséquences de la dérogation aux recommandations


.

Bonne approche



Consumer-Driven Contracts

, , B , . B .

▍16.


Recommandations


(middleware) - , , - , Express-. . , , . , , JS- {req,res} . , «» (, Sinon ) , {req,res} . , , , . node-mock-http , , , . , , HTTP-, -.

Conséquences de la dérogation aux recommandations


Express .

Bonne approche


Express-.

 // ,     const unitUnderTest = require('./middleware') const httpMocks = require('node-mocks-http'); //  Jest,     Mocha    describe()  it() test('A request without authentication header, should return http status 403', () => { const request = httpMocks.createRequest({   method: 'GET',   url: '/user/42',   headers: {     authentication: ''   } }); const response = httpMocks.createResponse(); unitUnderTest(request, response); expect(response.statusCode).toBe(403); }); 

▍17.


Recommandations


, , , , , , . , , - . , , , ( , , ), , ( — ) . , : SonarQube ( 2600 GitHub) Code Climate ( 1500 ).

Conséquences de la dérogation aux recommandations


, , . . , .

Bonne approche


Code Climate.


Code Climate

▍18. , Node.js


Recommandations


, , . , , , - , . , - , , , , ? , , ? , API ?

Netflix - . , , , , . , - — Chaos Monkey . , , , . Kubernetes — kube-monkey . , Node.js? , , , V8 1.7 . . node-chaos , -.

Conséquences de la dérogation aux recommandations


, , , .

Bonne approche


npm- chaos-monkey , Node.js.


chaos-monkey

Résumé


, Node.js-. , . .

Chers lecteurs! - ?

Source: https://habr.com/ru/post/fr435462/


All Articles