D'une part, je ne m'assois presque jamais là et j'écris des tests unitaires. Les tests unitaires sont un moyen d'arriver à une fin, pas une fin en soi. Ils sont un moyen de répondre «ce code fait-il la tâche de base qu'il est censé faire».
Par exemple, certaines personnes écriront une fonction, puis ouvriront une session interactive pour la tester sur quelques valeurs et s'assurer qu'elle fonctionne:
def fact x
if x == 0
1
else
x * fact(x-1)
end
end
>> fact 10
=> 3628800
>> fact 7
=> 5040
Mais maintenant, vous découvrez un bug:
>> fact -1
SystemStackError: stack level too deep
from (irb):2:in `fact'
from (irb):5:in `fact'
from (irb):10
Donc vous le corrigez:
def fact x
if x < 0
raise "Can't take the factorial of a negative number"
elsif x == 0
1
else
x * fact(x-1)
end
end
>> fact -1
RuntimeError: Can't take the factorial of a negative number
from (irb):3:in `fact'
from (irb):10
Mais maintenant, vous devez vraiment tester pour vous assurer que cela fonctionne toujours:
>> fact 10
=> 3628800
>> fact 7
=> 5040
Comme vous pouvez le voir, vous continuez à répéter les mêmes tests ... et vous devez comparer les résultats visuellement. Les tests unitaires sont un moyen d'éviter la répétition dans ce cas; cela réduit la quantité de travail que vous devez faire. Et bien que ce soit un petit exemple stupide, dans le monde réel, il devient de plus en plus important et de plus en plus difficile à tester manuellement. Cela signifie, bien sûr, que les gens ne testent tout simplement pas les composants individuels; ils testent tout le programme. Mais ensuite, des bogues surgissent et ils sont beaucoup plus difficiles à trouver. Ou des bugs se produisent, et ils sont corrigés, mais quelqu'un réintroduit le même bogue, car personne n'a ajouté un cas de test pour s'assurer que cela ne s'est pas produit. Ou quelqu'un regarde un gros morceau de code et dit: "Je n'ai aucune idée de ce que cela est censé faire, car il n'est pas documenté et n'a pas de tests ... si je corrige ce bogue, je n'ai aucune idée si je vais casser quelque chose d'autre en fonction de lui; peut-être que je vais juste réécrire ça à partir de zéro. "
Les tests unitaires réduisent tout le travail supplémentaire dans ces cas. La meilleure façon de les rendre amusants est de s'assurer que les gens comprennent tout le travail qu'ils remplacent et la flexibilité supplémentaire qui vient de savoir ce que chaque morceau de code est censé faire. Dans une certaine mesure, les gens doivent avoir un peu plus d'expérience avec l'écriture et le maintien d'une grande base de code pour comprendre l'importance des tests unitaires; si tout leur code est quelque chose qu'ils écrivent une fois et jettent, ils ne l'obtiendront jamais tout à fait.
Et les tests unitaires ne devraient pas être écrits après coup, comme une corvée supplémentaire une fois que vous avez du code que vous "connaissez" déjà fonctionne. Les tests unitaires doivent être écrits en premier, ou à tout le moins (puisque vous oubliez parfois de les écrire en premier) juste après avoir écrit le code en question. C'est ce qu'on appelle le développement piloté par les tests, et cela peut aider à améliorer vos API; si vous écrivez d'abord les tests qui exercent les API, vous apprendrez où les API sont difficiles à utiliser avant même d'écrire le code, et vous pourrez repenser beaucoup plus facilement que si vous ajoutez uniquement les tests par la suite.
MbUnit
bibliothèque a changé ma vie. Le test automatique est important. Le test automatique fait gagner du temps. Le test automatique permet d'économiser de l'argent. Les tests automatiques peuvent sauver des vies. Le test automatique est le seul moyen. L'autotest est un autre filet de sécurité. Quand je fais partie d'une cinquantaine de personnes travaillant sur une immense architecture, j'ai l'impression d'être encore une autre brique dans un mur. Avec des tests unitaires, je contrôle.