Pour les projets en cours et pour améliorer notre processus de développement, nous avons envisagé d'adopter TDD comme philosophie de développement. En recherchant les meilleures pratiques et comment "vendre" la nouvelle approche à mes collègues/développeurs, je suis tombé sur BDD et je l'ai trouvé encore plus approprié à ce que nous allions besoin et en quelque sorte être la prochaine itération de TDD. Le problème est que jusqu'à présent, j'ai essayé uniquement le outil développé par Dan North , JBehave et je ne peux pas dire que je suis étonné.
La configuration me semble lourde et je n'ai pas pu trouver de documentation très appropriée. D'un autre côté, j'ai également essayé spock l'outil groovy et jusqu'à présent, je l'aime un peu.
Q: existe-t-il des outils appropriés à utiliser pour BDD?
Q: utiliseriez-vous plutôt spock et gérer les frais généraux liés à l'introduction d'une autre langue?
Le développement axé sur le comportement n'est qu'une technique qui peut être utilisée sans aucun outil. Vous pouvez simplement écrire des tests dans le style BDD - par exemple démarrer les méthodes de test avec should
et introduire une fonctionnalité distincte avec cette méthode. Les sections When
et then
peuvent être remplacées par des commentaires, par exemple.
@Test
public void should_do_something() {
// given
Something something = getSomething();
// when
something.doSomething();
// then
assertSomething();
// when
something.doSomethingElse();
// then
assertSomethingElse();
}
Mon avis sur les cadres mentionnés:
Le problème avec JBehave est que les tests ressemblent à un vaisseau spatial complexe. D'un autre côté, il a une jolie sortie pour vos spécifications.
spock est vraiment cool. Syntaxe compacte, jolie sortie, beaucoup de fonctionnalités, écrites avec le puissant langage groovy, ce qui signifie la possibilité d'utilisation en conjonction avec geb . [~ # ~] mais [~ # ~] c'est groovy et ça peut être très important pour quelqu'un.
scalatest (écrit avec scala) et easyb (écrit avec groovy) ont tous les deux le même inconvénient que spock. La notation "... devrait ..." et "Étant donné ... Alors". Les spécifications sont dans des fichiers .story, et les implémentations des étapes sont dans les classes Java. Cette approche fonctionne très bien comme un outil de collaboration et de communication pour définir les spécifications, mais serait généralement trop de frais généraux pour une faible codage de niveau.
Je pense également que les frameworks BDD les plus performants pour Java sont ceux qui ne sont pas écrits en Java, car le langage Java n'a pas une telle flexibilité pour DSL (Domain Création d'un langage spécifique) que Groovy ou Scala possède.
En tant qu'auteur de JGiven je dois être en désaccord avec sody qui Java n'a pas assez de flexibilité pour la création DSL. Dans JGiven, les tests BDD se présentent comme suit:
@Test
public void users_can_login {
given()
.a_registered_user()
.and().the_login_page_is_shown();
when()
.the_user_enters_correct_credentials()
.and().the_login_button_is_pressed();
then()
.the_welcome_page_is_shown();
}
JGiven est utilisé avec JUnit ou TestNg et vous écrivez vos tests en Java simple.
Sauf si votre propriétaire de produit/qa/client doit être en mesure de lire les tests, utilisez Spock . C'est un outil très simple, mais améliore la lisibilité des tests. Grâce à ses fonctionnalités puissantes, vous n'avez pas besoin de Mockito, Hamcrest ni AssertJ. Et il a de superbes tests paramétrés. En fait, c'est "juste" une meilleure JUnit - un outil général pour l'exécution automatisée de tâches simples, que ce soit des tests unitaires, des tests d'intégration ou des tests d'acceptation.
Craignant Groovy? Pourquoi? Il est très similaire à Java. Plus vous l'apprenez, plus votre code est expressif et court. Vos tests seront plus courts et plus lisibles. Groovy est un médicament de passerelle vers le meilleur côté de la JVM.
Vous n'aimez pas les langues dynamiques? Eh bien, ce sont tests , et les tests sont exécutés par le serveur CI après chaque commit , droite? Si votre code casse, vous le saurez après quelques minutes. Vous n'avez pas de serveur CI ou vous n'effectuez pas de tests régulièrement? Alors ne vous embêtez pas avec le choix d'un framework de test et allez réparer votre processus. Les tests cassés sont inutiles et si vous ne les exécutez pas régulièrement, ils se briseront bientôt.
Allez avec JBehave/Cucumber si vous en avez besoin; Sinon, utilisez Spock.
Une autre alternative serait Spectrum - voir https://github.com/greghaskins/spectrum
Spectrum prend en charge la syntaxe RSpec/Mocha et dans sa prochaine version prendra également en charge la syntaxe Gherkin, ainsi que l'intégration des règles JUnit (il interagit donc avec Mockito, Spring, etc. via le @Rule
et @ClassRule
membres).
Divulgation complète - Je contribue à ce projet de système d'exploitation
Exemple:
@RunWith(Spectrum.class)
public class TestSomething {{
Supplier<Something> freshTestObject = let(Something::new);
describe("The component", () -> {
it("is tested by specs", () -> {
// the "let` above gives us a new instance of the object
// in each spec
freshTestObject.get().doSomething();
// using your favourite assertion framework
assertThat(something.get().getSomething()).isEqualTo(42);
});
});
}}
Spectrum génère un résultat de test hiérarchique dans votre console JUnit. La force de celui-ci est de mélanger l'implémentation Java de l'exécution de la spécification avec la définition de la spécification - cela peut être plus direct que les frameworks qui s'appuient sur des fichiers de fonctionnalités et du code de collage pour les analyser, surtout si il faut passer les résultats d'une étape du test à une autre.
Spectrum se veut polyglotte et devrait donc sembler familier aux utilisateurs de plusieurs frameworks existants.
Belle discussion! Je ne connaissais pas JGiven, mais je vais y jeter un œil.
De plus, je suis l'auteur de COLA Tests , un nouveau framework qui prend en charge la syntaxe complète des cornichons (exactement la même que Cucumber), il est vraiment facile à configurer, spécialement par rapport à JBehave et ne nécessite pas Coureur JUnit.
Fondamentalement, utilisez simplement les bibliothèques auxquelles vous êtes déjà habitué!
Voici un exemple de test de contrôleur de printemps (les histoires peuvent être chargées à partir d'un fichier):
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = { WebAppContext.class })
public class HelloWorldControllerTest extends BaseColaTest {
private final String stories =
"Feature: Introduce REST endpoint\n"
+ "Scenario: Should say hello\n"
+ "Given a web endpoint\n"
+ "When hit by a get request\n"
+ "Then the HTTP status will be OK\n"
+ "And the body will say hello world";
@Resource
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
private ResultActions result;
@Given("a web endpoint")
public void given() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@When("hit by a get request")
public void when() throws Exception {
result = mockMvc.perform(get("/helloWorld"));
}
@Then("the HTTP status will be OK")
public void thenOk() throws Exception {
result.andExpect(status().isOk());
}
@Then("the body will say hello world")
public void thenHello() throws Exception {
result.andExpect(content().string("Hello World!"));
}
}
Donnez Ginkgo4j un aller. Il utilise Java 8 lamda's pour refléter l'approche utilisée par Ruby RSpec et Go's Ginkgo.
Cette bibliothèque vous permet de créer des tests expressifs et riches en contenu.
`` ''
package com.github.paulcwarren.ginkgo4j.examples;
import static com.github.paulcwarren.ginkgo4j.Ginkgo4jDSL.*;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import org.junit.runner.RunWith;
import com.github.paulcwarren.ginkgo4j.Ginkgo4jRunner;
@RunWith(Ginkgo4jRunner.class)
public class BookTests {
private Book longBook;
private Book shortBook;
{
Describe("Book", () -> {
BeforeEach(() -> {
longBook = new Book("Les Miserables", "Victor Hugo", 1488);
shortBook = new Book("Fox In Socks", "Dr. Seuss", 24);
});
Context("Categorizing book length", () -> {
Context("With more than 300 pages", () -> {
It("should be a novel", () -> {
assertThat(longBook.categoryByLength(), is("NOVEL"));
});
});
Context("With fewer than 300 pages", () -> {
It("should be a short story", () -> {
assertThat(shortBook.categoryByLength(), is("NOVELLA"));
});
});
});
});
}
}
`` ''
Prend également en charge Spring.
(Divulgation complète. Je suis l'auteur de cette bibliothèque).