Comment tracer sa couverture de tests

Photo d'une couverture Gopher proposée par Redbubble
Crédit image: Redbubble.com

Le SDK Go intègre les rapports de couverture de test depuis Go 1.2.

Comment obtenir un suivi du taux de couverture dans le temps, sans passer par un SaaS ?

Le plus simple est évidemment d’utiliser une solution de suivi de couverture dans le temps prépackagée, comme en fournissent Code Climate, CodeCov ♡, ou Coveralls.io.

C’est très pratique pour l’Open Source, mais coûteux et pas toujours acceptable dans certaines organisations.

Une autre possibilité consiste à utiliser un greffon pour les outils d’intégration continue utilisés. Mais toutes les solutions d’intégration continue n’ont pas forcément cette fonctionnalité : Jenkins l’intègre dans son greffon Cobertura, mais pas GitLab qui n’affiche que le taux de couverture du dernier commit, ni CircleCI, qui renvoie à CodeCov et Coveralls.

En revanche, les mêmes structures disposent en général d’une solution d’observabilité déjà en place : pourquoi ne pas l’utiliser ? C’est l’idée de gocoverstats.

Comment produire un historique de couverture avec GoCoverStats ?

C’est un processus en 3 étapes:

  • produire un rapport de couverture instantané avec go test,
  • reformater ce rapport pour en extraire des vues avec gocoverstats
    • soit un simple taux global
    • soit les taux de couverture par paquet
  • transmettre ces données à un outil de métriques existant
$ go install gitlab.com/fgmarand/gocoverstats@latest         # Télécharger gocoverstats
$ go test -coverprofile=coverage.txt -covermode=atomic ./... # Créer le fichier de rapport
$ gocoverstats -f cover.txt                                  # Extraire le taux global...
0.953
$ gocoverstats -v -f cover.txt                               # ...ou une table de taux par paquet
2021/12/11 21:02:07 loaded 2 profiles                        # Cette ligne sort sur stderr
github.com/owner/repo/package1 0.950                         # Ces résultats sortent sur stdout
github.com/owner/repo/package2 0.981
Global, unweighted             0.953
$

Il suffit alors d’utiliser les résultats obtenus ci-dessus comme des métriques, à transmettre à l’outil déjà utilisé par l’organisation. Voyons deux exemples: DataDog et Graphite.

Comment tracer la couverture dans DataDog ?

Pour publier un taux de couverture global à inclure dans un dashboard DataDog :

  • Installer la bibliothèque Python pour DataDog, en suivant leurs instructions
  • Configurer au choix le fichier ~/.dogrc ou la variable d’environnement DATADOG_API_KEY avec une clef d’API.
  • Poster l’agrégat simple comme une seule métrique:
    • dog metric post foo_project.coverage $(gocoverstats -f coverage.txt)

Pour publier un taux par paquet, afin de produire soit un graphe composite sans l’agrégat, avec des courbes multiples, soit un graphe par paquet, on utilise la même commande dog, mais dans une boucle:

1
2
3
4
5
6
7
8
#!/usr/bin/env bash
# Cet exemple emploie grep de façon à être compatible Linux et macOS
coverage=$(gocoverstats -v -f coverage.txt | grep -v "Global, unweighted" | tr -s '[:blank:]' ',')
for package in $coverage; do
	IFS=,
	read TAG RATIO <<< "${package}"
	dog metrics post foo_project.coverage "${RATIO}" --tags package:"${TAG}"
done

Une fois les données injectées ainsi, il est possible de produire un graphe de dashboard à courbes multiples pour la métrique foo_project.coverage en faisant varier la série sur l’étiquette (tag) package (cf. ligne 7).

Comment tracer la couverture dans Graphite ?

Voyons un exemple avec la file d’attente nsq.io.

$ go test -race -coverprofile=cover.txt ./... > /dev/null
$ gocoverstats -f cover.txt -v 2> /dev/null | grep -v unweighted
github.com/nsqio/nsq/apps/nsq_to_http      0.098
github.com/nsqio/nsq/apps/nsqd             0.587
github.com/nsqio/nsq/internal/clusterinfo  0.007
# ...snip...
$

Le format le plus simple pour l’envoi de métriques à Graphite est le format texte de Carbon:

<name>.<space>.<metric> <value> <timestamps>

Comme ce n’est pas très loin du format de sortie de gocoverstats, quelques lignes de shell vont nous permettre de publier les métriques avec nc, sans nécessiter d’outil spécialisé:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#!/usr/bin/env bash
HOST=127.0.0.1
PORT=2003

ts=`date +%s`
for row in $(gocoverstats -f $ts -v \
    | 2> /dev/null \                # Ignore les informations
    | grep -v unweighted \          # Ignore le taux global
    | sed -E -e 's/github\.com\/nsqio/coverage/' -e 's/\//./g' -e's/ +/:/')
do
    msg=$(echo $(echo $row | tr -s : ' ') $ts)
    echo $msg | tee /dev/tty | nc -w0 $HOST $PORT
done

Il ne reste plus qu’à formater son dashboard dans Graphite, par exemple comme ci-dessous.

Graphes de couverture nsq.io dans Graphite

Ressources additionnelles