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.
À 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.
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:
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:
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.
Remise réglable.
La taxe est établie.
Lorsqu'un client passe une commande:
Commandez ensuite les options.
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.
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.
Lorsqu'un élément est mis à jour.
Puis des données mises à jour.
Vous pouvez également vérifier que les données mises à jour sont utilisées pour calculer la remise.
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.
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.
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!