Vous avez dit Gatling ?

Gatling est un outil permettant de réaliser des tests de montée en charge (stress tool) open source. Vous pouvez le télécharger sur Github

Gatling permet de mettre en place des scénarii ayant pour but de décrire le comportement d’un utilisateur sur l’application à tester. Pour ceux qui connaissent JMeter, le concept est le même, tous les deux tournent d’ailleurs sur une Java Virtual Machine.

Pourquoi utiliser Gatling ?

Ceux qui ont déjà manipulé JMeter ne pourront pas me contredire, injecter une multitude d’utilisateurs simultanément dans une application demande beaucoup de ressources machine. Ainsi, vous devez prévoir une machine performante sur laquelle installer JMeter afin de lancer les tests. Gatling est beaucoup moins gourmand. D’après un benchamrk effectué par Flood.io  Gatling supporterait  jusqu’à 20000 utilisateurs concurrents sur une JVM de 4GB (https://flood.io/blog/13-stress-testing-jmeter-and-gatling). Les performances de Gatling sont dues à son implémentation basée sur le  framework Akka (permettant de gérer très efficacement des applications multithread et concurrentes) et les IO non bloquants.

Définition des scénarii

Gatling permet d'enregistrer un parcours utilisateur  grâce à son « scénario recorder ». Ce mode lance un proxy qui vous permet de naviguer sur le site que vous voulez tester afin d’enregistrer un scénario qui sera joué lors de votre test de charge.

gatling-recorder

Gatling permet également d’écrire les scénarii en SCALA (plus compréhensible que le format XML utilisé par JMeter). Personnellement j’utilise le recorder dans un premier temps puis je customise ensuite le scénario à la main. Voici un exemple de scénario :

class MySimulation extends Simulation {

	val httpProtocol = http
		.baseURL("http://mydomain.com")
		.acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
		.acceptEncodingHeader("deflate")
		.acceptLanguageHeader("fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3")
		.connection("keep-alive")
		.userAgentHeader("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0")

	val headers_3 = Map("""Accept""" -> """*/*""")
	val headers_4 = Map("""Accept""" -> """text/css,*/*;q=0.1""")
	val headers_5 = Map("""Content-Type""" -> """application/x-www-form-urlencoded""")
	val headers_16 = Map("""Accept""" -> """image/png,image/*;q=0.8,*/*;q=0.5""")

	val scenario1 = scenario("Affichage basique type edito")
	    .group("Affichage basique type edito"){
			exec(http("scenario1 request_1")
				.get("""/"""))
			.pause(10)
			.exec(http("scenario1 request_2")
				.get("""/img-theme/images/favicon.ico"""))
			.pause(3)
			.exec(http("scenario1 request_3")
				.get("""/combo/?browserId=firefox&minifierType=&languageId=en_US&b=6120&t=1382088615000&p=/html/js&m=/aui/widget-base/assets/skins/sam/widget-base.css""")
				.headers(headers_4))
			.pause(6)
			.exec(http("scenario1 request_4")
				.post("""/web/portail/authentication?p_auth=YBAeIud5&p_p_id=58&p_p_lifecycle=1&p_p_state=maximized&p_p_mode=view&saveLastPath=0&_58_struts_action=/login/login&_58_doActionAfterLogin=false""")
				.headers(headers_5)
				.param("""_58_formDate""", """1382357885933""")
				.param("""_58_redirect""", """/""")
				.param("""_58_login""", """myLogin""")
				.param("""_58_password""", """myPassword""")
				.param("""_58_rememberMe""", """false"""))
			.pause(2)
		}
		
	setUp(scenario1.inject(ramp(100 user) over 1)).protocols(httpProtocol)
}

Vous remarquerez qu’on a simulé les temps de pause de l’utilisateur via la méthode « pause() ». Il est également possible, via la fonction « Feed() » de charger dynamiquement des variables depuis un fichier csv par exemple.

Tirs

L’exécution des scenarii s’effectue en ligne de commande (uniquement). C’est la dernière ligne du snippet précédent qui permet de configurer le tir :

setUp(scenario1.inject(ramp(100 user) over 1)).protocols(httpProtocol)

Ici on précise le scenario à exécuter, le nombre d’utilisateurs à injecter ainsi que la méthode à utiliser. Il en existe plusieurs :

  • atOnce : injecte tous les utilisateurs en une seule fois
  • ramp : injecte progressivement les utilisateurs
  • constantRate : injecte les utilisateurs de manière constante
  • je vous laisse consulter ce très bon article pour plus d’informations : http://blog.roddet.com/2013/06/gatling2-new-inject-api/

Rapport

Gatling permet de consolider les résultats des tirs grâce à différents rapports statistiques formalisés soit au travers de tableaux de données agrégées, soit au travers de graphiques:

gatling-error

Pour conclure

Gatling est un outil certes récent mais très aboutit, qui permet d'effectuer simplement des tests de montée en charge sur une application web. Pour moi, ses deux principaux atouts sont :

  • ses performances (moins gourmand que JMeter)
  • ses rapports (complets et faciles à interpréter)

Pour plus d’informations, n’hésitez pas à consulter la documentation officielle : https://github.com/excilys/gatling/wiki.