=== Tests

[quote,Robert C. Martin, Clean Architecture]
Tests are part of the system.

==== Types de tests

Les *tests unitaires* ciblent typiquement une seule fonction, classe ou méthode, de manière isolée, en fournissant au développeur l'assurance que son code réalise ce qu'il en attend. Pour plusieurs raisons (et notamment en raison de performances), les tests unitaires utilisent souvent des données stubbées - pour éviter d'appeler le "vrai" service.

> The aim of a unit test is to show that a single part of the application does what programmer intends it to.

Les *tests d'acceptance* vérifient que l'application fonctionne comme convenu, mais à un plus haut niveau (fonctionnement correct d'une API, validation d'une chaîne d'actions effectuées par un humain, ...).

> The objective of acceptance tests is to prove that our application does what the customer meant it to.

Les *tests d'intégration* vérifient que l'application coopère correctement avec les systèmes périphériques.

De manière plus générale, si nous nous rendons compte que les tests sont trop compliqués à écrire ou nous coûtent trop de temps, c'est sans doute que l'architecture de la solution n'est pas adaptée et que les composants sont couplés les uns aux autres. Dans ces cas, il sera nécessaire de refactoriser le code, afin que chaque module puisse être testé indépendamment des autres. cite:{clean_architecture}

[quote,Robert C. Martin, Clean Architecture]
Martin Fowler observes that, in general, "a ten minute build [and test process] is perfectly within reason...
[We first] do the compilation and run tests that are more localized unit tests with the database completely stubbed out.
Such tests can run very fast, keeping within the ten minutes guideline.
However any bugs that involve larger scale intercations, particularly those involving the real database, won't be found.
The second stage build runs a different suite of tests [acceptance tests] that do hit the real database and involve more end-to-end behavior.
This suite may take a couple of hours to run.

Au final, le plus important est de toujours corréler les phases de tests indépendantes du reste du travail (de développement, ici), en l'automatisant au plus près de sa source de création.

En résumé, il est recommandé de:

1. Tester que le nommage d'une URL (son attribut `name` dans les fichiers `urls.py`) corresponde à la fonction que l'on y a définie
2. Tester que l'URL envoie bien vers l'exécution d'une fonction (et que cette fonction est celle que l'on attend)

TODO: Voir comment configurer une `memoryDB` pour l'exécution des tests.

==== Tests de nommage

[source,python]
----
from django.core.urlresolvers import reverse
from django.test import TestCase


class HomeTests(TestCase):
    def test_home_view_status_code(self):
        url = reverse("home")
        response = self.client.get(url)
        self.assertEquals(response.status_code, 200)
----

==== Tests d'urls

[source,python]
----
from django.core.urlresolvers import reverse
from django.test import TestCase

from .views import home


class HomeTests(TestCase):
    def test_home_view_status_code(self):
        view = resolve("/")
        self.assertEquals(view.func, home)
----
