Blog // Exirel.me

Retrouvez tous les articles liés au tag Code Coverage via le flux rss dédié à ce tag.

Python, Makefile, et tests

Par Florian Strzelecki - 19:15 - 24.10.2016

Tags : Python, Bonne pratique, Unit Testing, Code Coverage, Makefile

Depuis quelques temps, j'essaie plusieurs fichiers Makefile pour mes projets en pythons : pour lancer les tests, les validateurs divers, et générer les différents rapports (tests, couverture, et qualité).

Voici ce à quoi j'arrive pour le moment :

# Project tasks
# ==========

test:
    coverage run --source=<package> setup.py test

report: pylint
    coverage html

pylint:
    pylint <package> > pylint.html || exit 0

isort:
    isort -rc <package> test.py

flake8:
    flake8

quality: isort flake8

all: quality test report

En général, je lance simplement avec make all, pour tout faire d'un coup sans me poser de questions. Cela va donc lancer :

Premier constat : inutile pour moi de lancer des tests sur du code qui n'est pas correctement formaté. Le coût d'un code propre est minime voire quasi inexistant - j'ai l'habitude, ça aide beaucoup - alors autant se fixer des règles strictes et s'y tenir.

Second constat : je n'utilise plus (ou presque plus) de lanceur de tests spécifiques (py.test, nosetests, etc.). Pourquoi ? Parce qu'au final, ces outils ne font qu'ajouter de la déco sur les tests, mais ils ne m'aident pas à écrire de meilleurs tests. Je suis habitué à unittest, et la plupart du temps, je n'ai pas besoin d'une explication particulière pour un test.

D'ailleurs, que l'on utilise simplement assert ou les méthodes du framework unittest, un message manuel est souvent préférable à une interprétation du lanceur de tests :

import unittest

class TestIsPositive(unittest.TestCase):
    def test_behavior(self):
        assert is_positive(0) is True, (
            'is_positive must return True with 0')
        assert is_positive(2) is True, (
            'is_positive must return True with > 0')
        self.assertFalse(
            is_positive(-1),
            'is_positive must return False with < 0')

Bien entendu, c'est un cas où le message est un peu accessoire : il faut imaginer des cas plus complexes, où le résultat d'une fonction est d'un type complexe, et donc la raison d'être demande un peu plus qu'une simple "ceci doit être égal à cela".

Quoi qu'il en soit, make all est maintenant ma routine quotidienne, simple, rapide, et efficace.

Couverture menteuse

Par Florian Strzelecki - 18:49 - 03.10.2015

Tags : Python, Programmation, Bonne pratique, Unit Testing, Code Coverage

Le domaine des tests unitaires est vaste, les approches foisonnent, et les polémiques sont nombreuses. Il en est une toute particulière que j'affectionne qui concerne la couverture de code.

Bien sûr, je ne jure que par une bonne couverture de code. Écrire des tests et les exécuter sans regarder la couverture de code (ou "code coverage" dans le jargon), ne représente pas un grand intérêt pour moi. Si je n'ai pas l'assurance que je teste l'ensemble du code, je me sens comme en hiver sans un bon pull : à découvert devant le froid et la colère des éléments.

La couverture de code est un mensonge.

Cette expression, je l'entends très souvent. Trop souvent même, que ce soit par des gens qui sont contre ou des gens qui sont pour - oui, en 2015, il y a encore des gens qui sont contre la couverture de code, et même contre les tests. Ce qui est un peu triste, d'ailleurs - mais passons.

Cependant, rare sont les fois où j'entends des explications claires ou des exemples d'une "bonne" mesure. Comment y parvenir ? Comment détecter les trous ? Comment mieux prévenir les problèmes ?

Je ne vais pas couvrir l'ensemble des cas possibles, mais je suis tombé sur un cas d'école cette semaine à mon travail.