Bdd – [Blog] du Java et du Freelance https://java-freelance.fr Vis ma vie de freelance java : techno et entreprise Mon, 12 Oct 2015 14:45:01 +0000 fr-FR hourly 1 https://wordpress.org/?v=4.4.4 Spock-(3/X) – Spock, EasyMock, Mockito et les arguments https://java-freelance.fr/java/spock-easymock_mockito_argument https://java-freelance.fr/java/spock-easymock_mockito_argument#respond Mon, 08 Nov 2010 08:30:27 +0000 https://java-freelance.fr/?p=1010 L’article précédent a permis de comparer la syntaxe des trois frameworks sur les cas classiques. Un cas où Spock se détache vraiment des deux autres frameworks, c’est sur la gestion des arguments des méthodes mockées.

Les wildcards

Il est possible d’utiliser des wildcards au niveau des arguments appelés. Ainsi 1 * calendarDao
.getInfosByDay(_) veut dire ‘la méthode calendarDao.getInfosByDay est appelée une fois (1 *) avec n’importe quel paramètre (_). On peut également spécifier la classe de l’argument : 1 * calendarDao.getInfosByDay(_ as String) .

Il est également possible par exemple de compter le nombre d’appel aux méthodes d’un simulacre (quel quel soit : 3 * calendarDao._ passera uniquement si les instructions du bloc when font exactement appel à 3 méthodes de l’instance calendarDao. Il est également possible de donner des intervalles plutôt qu’une valeur, ce qui n’est pas permis par les autres frameworks (à part le ‘au moins 1 fois’) :
(1..3) * calendarDao.getInfosByDay(_) [entre 1 et 3 fois]
(5.._) * calendarDao.getInfosByDay(_) [=> au moins 5 fois]
(_..5) * calendarDao.getInfosByDay(_) [=> au plus 5 fois]

Il existe de nombreux wildcard, la plupart ne servent pas à grand chose. Ceux qui me semblent le plus important :
calendarDao.getInfosByDay(_) : n’importe quel argument
calendarDao.getInfosByDay(!null) : n’importe quel argument non null
calendarDao.getInfosByDay(_ as String) tous les éléments de type String

Equivalent EasyMock

expect(calendarDao.getInfosByDay((String)anyObject())) : n’importe quel argument, obligation d’être une String
expect(calendarDao.getInfosByDay((String)notNull())): n’importe quel argument non null
expect(calendarDao.getInfosByDay(isA(String.class))):tous les élements de type String

Equivalent Mockito

when(calendarDao.getInfosByDay(anyString())) : n’importe quel argument, obligation d’être une String
when(calendarDao.getInfosByDay((String)notNull())): n’importe quel argument non null
when(calendarDao.getInfosByDay(isA(String.class))): tous les élements de type String

Vous pouvez trouver la liste ici : http://code.google.com/p/spock/wiki/Interactions

Les contraintes personnalisées

Les contraintes personnalisées sont très utiles dans certains cas, par exemple lorsque la méthode equals est déjà défini dans le code et qu’elle ne correspond pas à notre besoin ou que nous avons par exemple un champ date que nous souhaitons exclure de la comparaison. En règle général, il vaut mieux redéfinir la méthode equals qui est spontannément utilisée par les 3 frameworks pour comparer l’égalité des arguments attendus et reçus.

Nous allons chercher avec les 3 frameworks à créer des contraintes personnalisés (spock) ou des argument matcher (Mockito & Easymock).  Notre but est de faire en sorte que l’appel à listSpockData.add avec un paramètre ayant comme variable de classe img égale à « a » soit bien simulée. Pour cela, nous créons un objet spockData ayant bien img = « a » ainsi qu’une liste d’objets SpockData. Nous appelons ensuite la méthode listSpockData avec l’objet spockData et vérifions que cette dernière a bien été appelée.

Avec Spock :

  def "should list Spock Data"() {
    given:
    SpockData spockData = new SpockData("a", "accroche", "details", 6);
    List listSpockData = Mock();
    when :
    listSpockData.add spockData;
    then :
     1*listSpockData.add({it.img=="a"})
  }

Spock permet via les conditions particulières de définir un bloc à l’aide d’une closure , avec { } et de définir à l’intérieur plusieurs conditions. It signifie ici l’objet qui sera passé en paramètre à la méthode. Il est possible d’utiliser plusieurs expression (it.img== »img »&&it.day==6) ou une fonction définie dans la classe de test.

Avec Mockito,  qui utilise en fait les ArgumentMatcher du framework Hamcrest.

class isImgEqualToA extends ArgumentMatcher { //creation d un argument matcher
	      public boolean matches(Object spockData) {
	          return ((SpockData) spockData).getImg() == "a";
	      }
	   }
	@Test
	public void testArgumentMockito(){
		       List mock = mock(List.class);
			   when(mock.add(argThat(new isImgEqualToA()))).thenReturn(true);
			   mock.add(newSpockData("a", "b", "c", 2));
			   verify(mock).add(argThat(new isImgEqualToA()));

	}

Avec Easymock, l’opération se révèle être très verbeuse. [Pour voir une implémentation plus conforme] :

	static class Matcher implements IArgumentMatcher { //creation du matcher

		@Override// implementer cette methode permet de definir
                             // un message d erreur
		public void appendTo(StringBuffer arg0) {
		}

		@Override// definition de la methode qui verifiera que
                             // l argument img est bien egal a A. smell code.
		public boolean matches(Object spockData) {
			return ((SpockData) spockData).getImg() == "a";
		}
                // definition d une methode static pour déclarer le matcher
		public static SpockData isImgEqualToA() {
		    EasyMock.reportMatcher(new Matcher());
		    return null;
		}
	}

	@Test //Test
	public void testArgumentEasyMock() {
		List mock = createMock(List.class);
		expect(mock.add(Matcher.isImgEqualToA())).andReturn(true);
		replay(mock);
		mock.add(new SpockData("a", "b", "c", 2));
		verify(mock);
	}

Les tests mockito et easymock sont bien plus verbeux et au final sont plus restrictifs car elles utilisent des classes séparées pour définir les matchers. Spock évite la lourdeur d’avoir à définir une autre classe

Néanmoins, dans le cas de tests avec ArgumentMatcher, EasyMock & Mockito permettent de définir des messages d’erreurs personnalisés, via la méthode appendTo pour le premier et describeTo pour le deuxième. Notons que pour le premier, il faut la coder nous même alors que le deuxième en propose une par défaut construite à partir du nom de la classe isImgEqualToA donne ‘Img equal to A’. En règle général, on affiche un toString() de l’objet pour aider au debuggage et on regarde alors les 2 chaînes pour trouver les différences (ou en pas à pas en debug). Spock ne propose rien de tel dans sa version actuelle (0.4) mais en version 0.5 il est prévu de pouvoir utiliser les matchers d’Hamcrest, revenant à avoir la même syntaxe qu’avec Mockito, en un peu plus courte.

Crédit Photo : Oskay – http://www.flickr.com/photos/oskay/339996940/sizes/m/in/photostream/

]]>
https://java-freelance.fr/java/spock-easymock_mockito_argument/feed 0
Spock (1/3) – Spock, JUnit et le Data Driven Testing https://java-freelance.fr/java/spock-13-spock-junit-et-le-data-driven-testing https://java-freelance.fr/java/spock-13-spock-junit-et-le-data-driven-testing#respond Tue, 02 Nov 2010 08:10:00 +0000 https://java-freelance.fr/?p=875 Au cours de mes tribulations, je suis tombée sur un nouveau framework de test : Spock, basé sur Groovy & JUnit.  Il est facile à prendre en main et est beaucoup moins verbeux que certains autres framework de tests même quand on ne maitrîse pas Groovy. Les tests sont structurés à l’aide de blocs  given/when/then et setup/expect/where ce qui permet d’améliorer la lisibilité et l’écriture. Ce framework est à suivre, il est rapidement pris en main mais il manque encore certaines fonctionnalités avancées. Cet article est le premier d’une série de trois, il permettra de comparer spock à d’autres frameworks similaires.

Premier test setup/expect/where

def "String param should correspond to numeric spockInfoDay - classical syntax"() {
    setup:
     def spockResource = new SpockResource(new CalendarDaoStatic())
    expect:
    spockResource.findCalendarByDay(day).day == dayNumeric

    where:
    day  <<   ["1", "2", "3"]
    dayNumeric << [1, 2, 3]
  }

Le test est organisé en 3 blocs : setup, expect et where le tout placé dans un objet dont le nom est défini par def « nom du test ».  Le premier bloc setup sert à déclarer les variables qui vont être utilisées dans la suite du test. Ici c’est par exemple l’instanciation de l’objet spockResource. Dans le bloc where, je définis deux variables : l’une day qui prendra successivement les valeurs ‘1’,’2′ et ‘3’ et l’autre dayNumeric les valeurs 1,2,3 [groovy est un langage dynamique donc pas besoin d’indiquer le type des variables, il sera déterminé automatiquement]. Dans le bloc expect, j’indique mon test : je vérifie que la méthode spcokResource.findCalendarByDay retourne bien un objet comportant un attribut day dont la valeur correspond à la valeur en tant qu’entier d’une chaîne de caractère [c’est à dire que ma fonctionnalité ne fait pas grand chose d’autre qu’un Integer.valueOf].  Lors de l’exécution, il y a en réalité 3 tests JUnit qui sont exécutés, un pour chaque couple de paramètre day=’1′ & dayNumeric=1 / day=’2′ & dayNumeric=2 / day=’3′ & dayNumeric=3

Test avec structure en tableau

Le même test peut être écrit d’une manière différente en utilisant une autre syntaxe, encore plus lisible.

def "String param should correspond to numeric spockInfoDay"() {
    setup:
    def spockResource = new SpockResource(new CalendarDaoStatic())
    expect:
    spockResource.findCalendarByDay(day).day == dayNumeric

    where:
    day     | dayNumeric
    "1"  | 1
    "2"  | 2
    "3"  | 3
  }

Ici même principe,  3 tests seront joués , avec les paramètres day = ‘1’ et dayNumeric = 1 / day = ‘2’ et dayNumeric = 2 /day = ‘3’ et dayNumeric = 3 . Les paramètres étant les uns à la suite des autres et  séparés par des | cela permet de mieux visualiser ses données de test.

Le choix entre la première et la deuxième méthode dépend du contexte. Si les données à tester sont statiques, la deuxième méthode est plus claire. Mais la première méthode permet de tester avec des données dynamiques comme par exemple :

where:
[a, b, c] << sql.rows("select a, b, c from maxdata")

Ces deux syntaxes permettent de faire du data-driven testing, c’est à dire du test piloté par les données : il est possible de vérifier plusieurs test cases en injectant les données de départ et les données attendues via une source externe, ici le bloc where. Nettement plus simple que de lancer trois tests JUnit différent pour le même comportement, le tout en restant très lisible.

JUnit

Si on regarde l’équivalent JUnit

 @RunWith(Parameterized.class)
public class DataDrivenSimpleTest {
  private Integer day;
  private Integer dayNumeric;

  @Parameters
  public static Collection data() {
    return Arrays.asList(new Object[][] { { 1, 1 }, { 2, 2 },
              { 3, 3 } });
  }

  public DataDrivenSimpleTest(Integer day, Integer dayNumeric) {
    super();
    this.day = day;
    this.dayNumeric = dayNumeric;
  }

  @Test
  public void shouldReturnTheNumericValueOfDay() {
    FoetusCalendarResource calendar = new FoetusCalendarResource(
        new CalendarDaoStatic());
    assertEquals(calendar.findCalendarByDay(day).getNbJour(), dayNumeric);

  }
}

Voilà l’exemple avec l’annotation @Parameters incluse dans JUnit depuis la version 4.0 et il n’y a que l’essentiel pour tester la méthode findCalendarByDay. Tout d’abord, la classe doit être lancée avec un runner spécifique Parameterized.class (à la ligne 1). Elle a besoin de deux variables de classes day et dayNumeric ainsi que d’un constructeur qui initialise ses deux variables. Il y a aussi besoin d’une méthode public static qui retourne une collection d’object représentant les différentes données pouvant être prises par les deux paramètres day et dayNumeric annotée avec @Parameters. Seulement ensuite apparait la méthode de test, shouldReturnTheNumericValueOfDay qui utilise les variables de classes day et dayNumeric. Il est également possible dans la méthode annotée par @Parameters de définir de manière dynamique des jeux de données, on peut par exemple penser à l’importation de données à partir d’un fichier excel ou d’une requête SQL par exemple comme avec Spock. Outre la verbosité de cette méthode, il n’est possible que d’avoir un seul test paramétré par classe.

Les pré-requis à l’utilisation des tests paramétrés avec JUnit (variables de classe, runner, constructeur …) font que je préfère largement utiliser Spock pour faire du data-driven testing.

]]>
https://java-freelance.fr/java/spock-13-spock-junit-et-le-data-driven-testing/feed 0
Revue de presse https://java-freelance.fr/web/revue-de-presse https://java-freelance.fr/web/revue-de-presse#respond Wed, 16 Sep 2009 00:08:25 +0000 https://java-freelance.fr/?p=137 Voici une liste des sites qui nous ont intéressés récement :

http://www.waterfallmanifesto.org :  Site parodique sur les anciennes méthodes de développement (mais hélas toujours d’actualités) .

http://blog.crisp.se : Vue artistique d’une journée de dev avec la méthode Kanban.

http://www.scala-lang.org/ : Nouveau langage à typage fort, à la fois objet et fonctionnel, qui fonctionne sur la plateforme Java (compilé en bytecode). Formidable language sur le papier, je reste perplexe quant à son adoption par le plus grand nombre.

http://www.kiad.org/ :  Blog généraliste du PDG d’Owlient. Articles sur le Web de très bonne qualité.

Bases de données dénormalisées : Article très instructif sur la nouvelle génération de bases de données dites « Dénormalisées », utiles pour les applications effectuant un très grand nombre de lectures et peu de modification.

]]>
https://java-freelance.fr/web/revue-de-presse/feed 0