Posts tagged: JUnit

Tests HTTP avec Arquillian

Pour commencer 2013 en beauté, rien de mieux que de finir l’année avec une mission pleine de nouveaux challenges et de nouvelles technos : Cassandra, Play!, EJB3 (!) et Arquillian.

Arquillian est un outil qui permet de faire des tests d’intégration. Il permet notamment de construire programmatiquement des jar, war et ear très simplement et de déployer ces pseudos-livrables dans un serveur embarqué.

Étant adepte du TDD, quand on me demande de faire un service web, j’aime me mettre à la place du client web et manger du HTTP afin de vérifier le contenu des retours mais aussi les entêtes, les E-Tag, la compression etc… C’est que nous permet de faire Rest-Assured. Nous allons justement voir dans cet article comment tester un service web par la couche HTTP en se servant d’Arquillian pour déployer le service de manière embarqué.

Dans cet exemple, nous utilisons le serveur glassfish embedded. Nous testons un service REST permettant de consulter des logs applicatifs. Ainsi on souhaite vérifier que la requête HTTP : « GET http://localhost:8181/logs?severity=error » retourne bien un code HTTP 200 OK.

Le Test

Voici le code test que nous souhaitons faire :

Read more »

Let’s make this test suite run faster! SoftShake 2010

Qui n’a jamais attendu de nombreuses minutes pour builder un projet ? Et qui n’en a jamais profité pour aller boire un café/regarder twitter/… ? :) Parce que l’on teste fréquemment, il est important d’essayer d’optimiser et de réduire la durée d’exécution des tests.  Tester souvent ne veux pas dire attendre souvent ! Il est donc primordial d’essayer de réduire cette durée en jouant sur différents paramètres. Comment obtenir le résultat des tests le plus rapidement possible ?

Ce qui suit est tiré de la conférence de David Gageot [ @dgageot / http://javabien.net ] à SoftShake 2010.

Sur une vingtaine de personnes présentes dans la salle, les durées de build vont de quelques minutes à plusieurs heures. David présente brièvement quelques frameworks comme Infinitest et JUnitMax. Ce sont des plugins pour IDE Java qui permettent de lancer les tests unitaires en continu et de manière intelligente, c’est à dire uniquement ceux impactés par le code modifié.
La première idée lorsque l’on cherche à optimiser cette durée d’exécution, c’est de vouloir déléguer le problème. C’est faire  tourner les tests sur des serveurs distribués qui permettront d’exécuter les tests en tâches de fond. C’est une mauvaise idée, les serveurs coûtent chers et on peut se retrouver submerger. Il existe des méthodes plus simples pour réduire cette durée.

Le KISS ( Keep It Simple, Stupid ) est également applicable lorsque l’on crée des tests. Chercher à optimises ses tests peut améliorer votre produit : ce qui est simple à tester sera simple à coder et à utiliser. Ce qui est compliqué n’en vaut surement pas la peine. Read more »

Bouchon (stub) ou Simulacre (mock) ?

Le test unitaire est un test qui provoque l’exécution d’une partie du code et qui l’analyse.  Il permet de garantir que le code exécuté fonctionne correctement. Il se doit donc d’être automatisé et répétable. Pour cela, cela nécessite fréquemment le besoin d’isoler le test unitaire des systèmes extérieurs (base de données, appels web-service distants).

Pour ce faire, il existe plusieurs méthodes, l’utilisation de bouchon (‘stub’) ou de simulacre (‘mock’). L’article de référence est un article de Martin Fowler « Les simulacres ne sont pas des bouchons« . Pour résumer, une méthode bouchonnée est appelée sur un objet bouchon réel, centré sur le système testé. Il ne peut jamais faire échouer le test. On regarde l’état de l’objet final à la fin du test et non les étapes qui ont permis d’obtenir cet état. C’est un test basé sur des états. Read more »

Les erreurs courantes avec EasyMock

logo easymockEasyMock est un framework de test qui peut dérouter dans un premier abord. Une fois qu’on a compris comment l’utiliser, on tombe sur un certain nombre d’erreurs qui reviennent très souvent et qui ne sont pas souvent explicites. Même si EasyMock 3.0 a clarifié un certain nombre d’erreurs, cet article (fait sous la 2.5.2) servira de pense-bête à ceux qui débutent avec ce framework. Read more »

Kawa BarCamp 2

J’ai participé hier à la deuxième édition du kawa barcamp. Un bar camp c’est une rencontre ouverte autour de thèmes choisis par les participants. Nous étions hier une trentaine de personnes réunis pendant environ 3 heures. Après un bref tour de table où nous nous sommes présentés (nom + prénom + 3 mots clés), 8 personnes ont inscrits des thèmes d’ateliers sur un tableau. Nous devions choisir parmis 2 sujets au choix : Read more »

java.lang.IllegalStateException: 1 matchers expected, 2 recorded

« java.lang.IllegalStateException: 1 matchers expected, 2 recorded » est une exception bien connue du développeur utilisant EasyMock. Elle veut tout simplement dire que lorsque l’on utilise un matcher (genre eq,anyObject …) il faut en utiliser pour tous les paramètres de la méthode, j’y reviendrai plus en détail dans un prochain article. Ainsi :

expect(maMethode("XYZ","BZT")).andReturn("XXX")
// est correct tout comme :
expect(maMethode((String)anyObject(),eq("BZT"))).andReturn("XXX")
// mais pas :
expect(maMethode((String)anyObject(),"BZT")).andReturn("XXX")

Sauf que mon erreur du jour, c’est que cette expression arrive sur la méthode :
« expect(formatServiceMock.scale(eq(BigDecimal.valueOf(10)))).andReturn(c) » qui elle est correcte a première vue.

Read more »

PowerMock Mock Mock

PowerMock c’est quoi ?

PowerMock est une extension de 2 API bien connues des mockeurs (Ha ha), EasyMock et Mockito. Qui n’as jamais été obligé de supprimer un final, rendre une méthode private protected ou galérer sur des appels statiques pour faire ses tests ? PowerMock nous permet de « tester l’intestable » sans toucher au code. Bonne idée ? Oui, mais attention, cette bonne idée a un coût qu’il ne faut pas négliger. L’exécution des tests peut prendre jusqu’à 10 fois plus de temps.

De plus, si on ne fait pas attention, on peut tomber sur des anomalies qui peuvent être difficile à résoudre si on n’a pas saisi le « truc ». L’objet de cet article est de vous présenter ce qui me crash le plus souvent mes tests.

Read more »

Premiers pas avec Scala

Je suis tombé amoureux de Scala. Et je suis fier de vous présenter mes premières lignes de code en Scala :

import java.io._

class Reader(dir: String) {

	// Concatène les contenus de n fichiers dans une liste
	def readAll() = {

		// Mets toutes les lignes d'un fichier dans une liste
		def readLines (name : String) = {

			// Mets toutes les lignes d'un bufferedReader dans une liste
			def read(buf : BufferedReader, acc : List[String] ) : List[String] = buf.readLine match {
				case null => acc
				case s => read(buf, s::acc)  // Appel recursif optimisé par Scala
			}

			// Compose le nom complet du fichier et appel read
			read(new BufferedReader(new FileReader(dir + "/" + name)), Nil).reverse
		}

		// Applique readLine sur tous les fichiers et renvoi la concaténation des listes
		// Pas de return : En scala c'est la derniere expression qui fait office de retour
		new File(dir).list.flatMap(readLines)
	}
}

13 lignes de code, pour lire tous les fichiers d’un répertoire puis concaténer l’ensemble des lignes dans une liste chaîné.

Une compatibilité à 100% avec Java

Ce qui n’est pas une surprise, car Scala est compilé en ByteCode.

Cela se traduit par la possibilité d’importer  n’importe quelle classe pourvu qu’elle soit dans le classpath :

import java.io._

Et d’appeler des méthodes Java dans le code Scala :

buf.readLine
new BufferedReader(new FileReader(dir + "/" + name))

Et même d’utiliser très simplement un framework comme JUnit :

import org.junit.Test

class ReaderTest() {
  @Test
  def unTest() : Unit = {
    val read = new Reader("src/test/resources/cotations")
    read.readAll().map((x) =>println(x));
  }
}

Oui je sais, ce test n’est pas un test, c’est juste un exemple :)

Chaque méthode que j’ai écrite ne fait qu’un seul traitement. Cela les rends faciles à comprendre, à maintenir et à tester. La programmation fonctionnelle n’étant pas « impérative », il est de toute façon très difficile d’écrire une méthode sur 1000 lignes alors qu’il est malheureusement très fréquent d’en trouver dans du code Java…

Pas de boucle

En programmation fonctionnelle il est tout à fait possible, et même conseillé de ne pas utiliser de boucle. La façon de penser et de concevoir son programme n’est plus la même. C’est je  pense, la principale raison qui rend les langages fonctionnel « obscurs » pour un développeur impératif.

En programmation impérative, on pense « enchaînements d’instructions », c’est un peu comme écrire une recette de cuisine : faire ci, puis ça, puis ça.

En programmation fonctionnelle on s’attache au « comment ». Comment transformer tel fichier en liste et tel liste en table de base de données. C’est le principe d’une fonction : transformer une entrée en « autre chose ». Les éléments impératifs, comme les boucles ne sont utiles que dans un langage impératif (encore que..).

On utilisera plutôt la récursion :

			def read(buf : BufferedReader, acc : List[String] ) : List[String] = buf.readLine match {
				case null => acc
				case s => read(buf, s::acc)  // Appel recursif optimisé par Scala
			}

			// Compose le nom complet du fichier et appel read
			read(new BufferedReader(new FileReader(dir + "/" + name)), Nil).reverse

Notez qu’il ne se produira pas de StackOverflowError car ce code récursif est traduit par une boucle. Oui ne riez pas, c’est vrai. Un code récursif identique en java produira un beau StackOverflowError lorsque les fichiers dépasseront un certain nombre de lignes.

Scala a quand même une petite faiblesse, il n’optimisera que si l’appel récursif est direct. Une pile {read, read, read, read, read} sera optimisée alors qu’une pile {read2, read1, read2, read1} ne le sera pas. Ce qui nous empêche d’écrire ce code qui aurait été plus élégant :

def read(buf : BufferedReader) : List[String] = buf.readLine match {
      case null => Nil
       case s => s::read(buf)  // Appel recursif
}

  // Compose le nom complet du fichier et appel read
  read(new BufferedReader(new FileReader(dir + "/" + name)))

La stack ici est {read, ::, read, ::, read, ..} « :: » est la fonction d’ajout d’élément à une liste en Scala !

En fait, Java nous interdit carrément d’utiliser la récursion sur une trop grande profondeur, ce qui est clairement une énorme lacune du compilateur Java, qui pourrait très bien optimiser les fonctions récursives pour éviter les stackOverflow. Scala à une longueur d’avance sur ce point. Ceci dit je pense que cela donnera des idées pour Java7.

Cette traduction en Java ne sera pas optimisée malgré une pile d’appel optimisable :

private List readLines(final BufferedReader buf, final List acc) {
		String line;
		try {
			line = buf.readLine();
			if (line != null) {
				acc.add(line);
				return readLines(buf, acc);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

		return acc;
	}

Voici une autre façon de ne pas utiliser de boucle :

// flatMap est une méthode native.
new File(dir).list.flatMap(readLines)

Ici on créé un objet java.io.File, on appel la fonction list() puis on appel la fonction readLines sur chacun des fichiers.

La méthode « map » applique la méthode readLines à tous éléments de la liste et retourne cette nouvelle liste. On effectue donc bien un mapping d’une liste de valeurs vers une nouvelle liste de valeurs : List<FileName> => List<ContenuDuFichierFileName>. Le tout, sans boucle !

La méthode flatMap() diffère de la méthode map() car au lieu de renvoyer une List<List<String>> (ReadLines renvoie une List<String>, elle va « aplanir » (ou concaténer) les listes, ce qui donnera une simple List<String> contenant toutes les lignes de tous les fichiers situés dans le répertoire « dir ».

Alors en vérité, et je pense que c’est une lacune du langage Scala, il existe un mot clé « for » qui permet d’écrire certaine ligne de mon code d’une autre manière faisant grandement penser à une boucle « for » Java… mais sans l’être.. bref, je conseil d’éviter cette écriture, Scala étant déjà assez difficile à appréhender pour un programmeur impératif, inutile d’ajouter de la confusion en codant un truc ressemblant à de l’impératif..

Et pas de variable

Scala encourage l’utilisation d’objet immutable. C’est à dire avec un état fixe, sans setters par exemple. Je vous renvoie à la lecture de l’excellent livre « Effective Java » pour en savoir plus sur les avantages de l’immutabilité en Java, et donc a fortiori en Scala. Et bien entendu il beaucoup plus simple de faire de l’immutable en Scala qu’en Java !

Scala permet de différencier très clairement les valeurs des variables via les mots clé « val » et « var ». « val s : MyObject  » est l’équivalent de « final MyObject o; » alors que « var s : MyObject  » sera l’équivalent de « MyObject o; » En Scala les paramètres des fonctions sont des « val ». Un objet immutable sera forcément une valeur.

Il est donc tout à fait possible et même conseillé de ne jamais utiliser de variables. En fait, lorsqu’on aura besoin d’un objet avec état changeant on utilisera le pattern « Actor », dont Scala fourni le support et qui permet d’avoir des objets mutables « sans risques ».

Développer avec le Bloc-notes : Facile !

Le gros défaut de Scala, c’est qu’il n’existe pas d’IDE aussi avancé que pour Java. Ceci dit, je n’ai pas du tout souffert de ce manque. J’utilise le plugin eclipse fourni sur le site officiel, qui permet l’auto complétion et rajoute de la couleur et honnêtement, ça suffit largement. C’est à se demander si une grosse partie de l’outillage nécessaire en Java n’était finalement pas lié aux lacunes de Java !

Pour comparer voici les 2 codes Java et Scala mis côte à côte. J’ai essayé de réduire au maximum le code Java ! On remarquera qu’en Java, j’ai été obligé d’avoir une variable non final.

import java.io.*;
import java.util.*;

public class Reader {

	private final String directory;

	public Reader(final String dir) {
		this.directory = dir;
	}

	public final List<String> readAll() {
		final String[] fileNames = new File(directory).list();
		final List<String> ret = new LinkedList<String>();

		for (String name : fileNames) {
			try {
				BufferedReader buf = new BufferedReader(new FileReader(directory + "/" + name));
				String line = buf.readLine();
				while (line != null) {
					ret.add(line);
				}
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		return ret;
	}
}

No comment :

import java.io._

class Reader(dir: String) {
    def readAll() = {

        def readLines (name : String) = {

            def read(buf : BufferedReader, acc : List[String] ) : List[String] = buf.readLine match {
                case null => acc
                case s => read(buf, s::acc)
            }

            read(new BufferedReader(new FileReader(dir + "/" + name)), Nil).reverse
        }

        new File(dir).list.flatMap(readLines)
    }
}

Réactiver votre cerveau

Apprendre un nouveau langage, c’est apprendre à penser autrement, cela bouscule nos neurones et comment dire : Ça fait du bien !

Scala offre beaucoup d’autres choses intéressantes, comme les traits,  les actors, sa gestion native du XML, son framework web « Lift », Comet etc. J’espère avoir le temps d’approfondir tout ça et d’en faire quelques articles.

Plus généralement, la programmation fonctionnelle offre d’énormes avantages, rendant obsolète bon nombre de patterns et de framework qui n’existent finalement que parce que, Java et les langages impératifs en général ont de nombreuses imperfections.

Source : http://www.scala-lang.org/