Développement de microservices avec BDD et IOD

BDD - développement par le comportement. BDD for microservices est une collaboration du client, des développeurs et des testeurs. BDD est un développement qui prend en compte à la fois les intérêts techniques et les exigences commerciales. Cette approche est généralement utilisée pour décrire les interfaces d'application, et puisque les microservices sont les détails de la mise en œuvre du système, BDD convient également pour développer des microservices. Comment faire - dans la traduction de Ken Pugh.

image

À propos de l'auteur: Ken Pugh enseigne aux entreprises à développer la flexibilité, crée des systèmes de haute qualité en utilisant le développement piloté par les tests d'acceptation, BDD, l'accélération DevOps. Ken a écrit plusieurs livres sur le développement de logiciels, a été un gagnant du Jolt Award 2006 Prefactoring, l'un des créateurs du cours SAFe Agile Software Engineering.

Le comportement dans BDD est souvent exprimé par la construction Given / When / Then. On nous donne un certain état lorsqu'une action ou un événement se produit, puis l' état change et / ou les informations sont retournées.

Par exemple, la logique sans état, telle que les règles métier et les calculs, décrit simplement la conversion de l'entrée en sortie.

La conception orientée interface utilise le principe de «conception d'interfaces, pas d'implémentations» . Les consommateurs du service utilisent l'interface qu'il fournit, pas les internes. Cela signifie qu'une telle interface doit être clairement pensée, y compris le comportement d'erreur. Pour la définition des termes dans la description de l'interface ou de son comportement, il est possible d'utiliser DDD - Domain Driven Design.

Les microservices peuvent être synchrones lorsque le consommateur appelle directement un autre service et attend le résultat, ou asynchrones lorsque le service répond à un message que le client a placé dans la file d'attente .

Prenons un exemple de service synchrone.

Service synchrone


Imaginez un service qui calcule une remise sur une commande client. L'ensemble du processus est un ensemble d'opérations connexes.



Le comportement de ce service peut être décrit comme suit:

Get discount for a customer Given these inputs Customer category Order Amount Then service outputs Discount Amount 

Le service peut calculer la remise à l'aide d'algorithmes dans le code, sur la base de la base de données de données locale ou en contactant d'autres services.

Il peut utiliser JSON ou XML comme format de message. Cependant, la description du service sans spécifier les détails d'implémentation permet de séparer la sémantique des opérations de la syntaxe.

Quel est le comportement?


À l'aide de BDD, vous pouvez commencer à concevoir avec des exemples de données pour vous faire une idée du comportement souhaité. Les développeurs de services, clients et testeurs peuvent trouver cet exemple. Les deux premières colonnes sont l'entrée du service et la colonne de droite est la sortie.

Catégorie de client
Montant de la commande
Montant de la remise?
Bon
100,00 USD
1,00 USD
Excellent
100,00 USD
2,00 USD

L'exemple montre des termes de domaine qui peuvent nécessiter un raffinement supplémentaire - par exemple, décrivent des valeurs valides.



Il est entendu que le service renvoie le résultat correct si les données d'entrée tombent dans la plage de valeurs acceptables.

La description du comportement, en particulier pour les microservices, inclut souvent des réponses en cas d'échecs et d'erreurs. Une description des pannes potentielles aide le consommateur à comprendre quoi faire dans de tels cas. Les clients du service peuvent utiliser des bibliothèques spéciales, par exemple Hystrix de Netflix, pour corriger certaines de ces défaillances.

Quelques erreurs potentielles de notre service:

Crash
Syntaxe de requête non valide
Délai d'appel des services dépendants
Valeur de paramètre de demande non valide

Les échecs peuvent être exprimés sous forme de constantes numériques ou de caractères dans le protocole de communication.

L'utilisation de noms significatifs dans BDD permet de souligner la sémantique d'un échec, et non sa syntaxe.

Si la valeur transmise en tant que catégorie ne figure pas dans la liste des valeurs valides, le service renverra un indicateur d'échec: "Valeur non valide des paramètres de requête". Cela peut être représenté, par exemple, en renvoyant le code HTTP 400 et la description textuelle correspondante.

Vous pouvez également déterminer la valeur de remise qui sera retournée, par exemple 0 si l'un des paramètres est incorrect. Dans ce cas, le service devrait être responsable de l'enregistrement de ce problème afin que ses conséquences puissent être analysées.

Les tests BDD de service peuvent constituer un contexte pour ses tests unitaires. Dans le processus de conception, la responsabilité de réussir les tests BDD incombe aux classes et aux méthodes . Les tests unitaires déterminent ces responsabilités.

Bouts


Lors du test d'un service, des talons de services dépendants qu'il appelle sont souvent requis. Ils sont particulièrement nécessaires pour les services lents, coûteux ou aléatoires. Si le comportement du service de remise n'a jamais changé, alors lors du test du client, vous pouvez utiliser l'instance de combat.

Le changement est souvent inévitable, donc des talons sont généralement nécessaires.



Un stub peut toujours renvoyer les mêmes valeurs, par exemple:

Catégorie de client
Montant de la commande
Montant de la remise?
Bon
100,00 USD
1,00 USD
Excellent
100,00 USD
2,00 USD

Les tests clients peuvent s'appuyer sur ces valeurs. Dans cet exemple, un comportement constant peut être suffisant. Pour d'autres tests, une réponse de talon personnalisée est préférable.

Alternativement, le talon du service de remise peut simplement retourner le même montant, quelle que soit l'entrée.

Comment ce talon peut-il s'intégrer dans un scénario plus large? Considérez le comportement du système pour une commande, qui comprend à la fois une remise et une taxe. La taxe est calculée par le microservice, similaire à la remise.



Il y a un acheteur.

Catégorie d'acheteur
Emplacement
Bon
Caroline du Nord

Remise réglable.

Catégorie de client
Montant de la commande
Montant de la remise?
Bon
100,00 USD
1,00 USD

La taxe est établie.

Emplacement
La quantité
Taxe?
Caroline du Nord
99.00 USD
6.60 USD

Lorsqu'un client passe une commande:

Montant de la commande
100,00 USD

Commandez ensuite les options.

Montant de la commande
remise
Montant après remise
taxe
Total à payer
100 USD
1,00 USD
99.00 USD
6.60 USD
105.60 USD

Services avec l'Etat


Si le service de remise utilise la base de données pour obtenir des informations pour le calcul de la remise, son contenu correspond à l'état du service. Les changements d'état en réponse aux mises à jour des données doivent être documentés. Supposons que le service ait cet état.

Catégorie de client
Niveau seuil
Pourcentage de remise
Bon
100,00 USD
1%
Excellent
50,00 USD
2%

Dans ce cas, le service doit permettre de modifier ces données. La mise à jour peut être organisée de manière à mettre à jour les éléments individuels ou à mettre à jour la table entière immédiatement. Voici un exemple de test de comportement pour une mise à jour individuelle.

Compte tenu des données actuelles.

Catégorie de client
Niveau seuil
Pourcentage de remise
Bon
100,00 USD
1%
Excellent
50,00 USD
2%

Lorsqu'un élément est mis à jour.

Catégorie de client
Niveau seuil
Pourcentage de remise
Excellent
50,00 USD
3,5%

Puis des données mises à jour.

Catégorie de client
Niveau seuil
Pourcentage de remise
Bon
100,00 USD
1%
Excellent
50,00 USD
3,5%

Vous pouvez également vérifier que les données mises à jour sont utilisées pour calculer la remise.

Catégorie de client
Niveau seuil
Montant de la remise?
Excellent
100,00 USD
3,50 USD

Le service de remise peut avoir un stockage local pour enregistrer les données dans cet exemple, mais il peut également dépendre d'un service de stockage distinct pour ces données. Si tel est le cas, les tests de la section précédente s'appliquent à un service distinct. Mais chaque dépendance ajoute des problèmes. Quel devrait être le comportement d'un service si ses dépendances ne sont pas disponibles? Pour un service de remise, cela doit-il indiquer un échec ou doit-il simplement renvoyer la valeur par défaut, le même 0? Parfois, vous pouvez utiliser des stratégies globales de gestion des erreurs, mais souvent la décision dépend du contexte du service .

Formulation et automatisation des tests


Une fois que le comportement du microservice est cohérent, il peut être formulé sous forme de tests automatisés. Il existe plusieurs systèmes de test de microservices, tels que PACT ou Karaté. De plus, vous pouvez utiliser des frameworks BDD tels que Cucumber ou FIT.

Par exemple, Cucumber utilise des bibliothèques pour interroger les services. Ensuite, des informations supplémentaires sur l'environnement peuvent être présentées dans le cadre du script.

Par exemple, un fichier objet Cucumber peut inclure.

Scénario: calculer la remise pour un montant de commande
La configuration donnée est:
| URL | myrestservice.com |
Lorsque la remise est calculée avec:
| Méthode | GET |
| Chemin | remise |
| Version | 1 |
Les résultats pour chaque instance sont alors:
| Catégorie de client | Montant de la commande | Montant de la remise? |
| Bon | 100,00 USD | 1,00 USD |
| Excellent | 100,00 USD | 2,00 USD |

Les options d'étape dépendent de vos conventions de test.

Les valeurs des deux premières colonnes peuvent être transférées vers n'importe quelle convention d'appel, par exemple, pour interroger des paramètres. Le résultat dans body doit correspondre à la troisième colonne. Si les noms et les valeurs de la requête sont les noms et les valeurs des colonnes, cela réduit les différences entre le test et l'implémentation.

Pour la réutilisation, des étapes peuvent être écrites pour un service arbitraire qui effectue des calculs ou détermine le résultat d'une règle métier. Dans l'exemple ci-dessus, l'utilisation du symbole «?», Comme dans le «montant de la remise» ci-dessus, aide l'analyseur à distinguer l'entrée et la sortie.

Les tests doivent également inclure des échecs, par exemple.

Catégorie de clientMontant de la commande et nbspMontant de la remise? & NbspRésultat
Bon et nbsp100,00 USD et nbsp
1,00 USD et nbsp
Ok
Pas si bon & nbsp100,00 USD et nbsp2,00 USD et nbspValeur de paramètre non valide
Excellent & nbsp100,00 ZZZ & nbsp2,00 USD et nbspValeur de paramètre non valide

Conclusion


Les microservices dépendent d'autres services et systèmes, ce qui nécessite une spécification claire des interfaces et de leurs tests précis. Ceci peut être réalisé en décrivant le comportement et les interfaces définis par les tests. En utilisant BDD, la fonctionnalité des services est décrite par des tests exécutables qui se concentrent sur la sémantique des opérations plutôt que sur la syntaxe . L'automatisation de tels tests nécessite généralement la mise en place de stubs d'autres services, dont le comportement est décrit par leurs tests BDD individuels.

Conception orientée interface - IOD, comprend des obligations supplémentaires du service: restriction sur l'utilisation des ressources, bande passante et rapport d'erreurs. Ensemble, BDD et IOD aident à décrire le comportement du service afin que les clients puissent facilement le comprendre et s'y fier.

  • BDD pour microservices se concentre sur la coopération de la triade - le développeur de services, le développeur client et le testeur.
  • Créez des conventions clairement définies pour les interfaces de microservices à l'aide de l'IOD.
  • Les microservices nécessitent généralement des fiches de test pour accélérer les tests.
  • Les tests doivent être indépendants.
  • Testez les scénarios négatifs dans les tests.
Les 27 et 28 mai, lors du festival RIT ++ à la conférence QualityConf, Artyom Malyshev parlera de l'importance d'exprimer clairement le modèle de domaine dans le code et montrera comment le faire avec des exemples.

Venez parler de développement de produits de qualité et partagez vos idées!

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


All Articles