Introduction :

Toute application se doit d’être testée. Cela est vrai pour toutes les applications quel que soit leur public (application personnelle, interne d’entreprise ou grand public), mais c’est encore plus vrai lorsqu’une application est destinée à être publiée sur le Store. En effet il faut pouvoir fournir une nouvelle version de l’application sans remettre en cause l’existant ni introduire de régressions (des bugs).

Une solution qui permet de tester les non régressions de façon automatique existe : il s’agit de la mise ne place de tests unitaires.

Si cette solution est utilisée dans la plupart des projets informatiques, leur mise en œuvre dans le cadre d’application Metro fait intervenir un chalenge supplémentaire : le test unitaire des méthodes asynchrones.

          

Le Problème :

Dans le cas d’un test unitaire faisant appel à une méthode asynchrone (marquée du mot clef async et retourne un Task<T>), l’approche naturelle est d’écrire un test de façon classique :

        [TestMethod]
        public async void TestGetDataAsync_NotGood()
        {
            IService svc = new MyService();
            string returnedData = await svc.GetDataAsync();
        }

 

Notez que nous utilisons le nouveau mot clef await qui permet l’'exécution de la méthode de notre service dans un contexte dédié. Comme nous utilisons le mot clef await dans le corps de notre test, il nous faut le marquer du mot clef async (qui indique qu’une partie du contenu de cette méthode sera asynchrone, et que donc la méthode elle-même peut être considérée comme pouvant être asynchrone).

Nous avons alors, lors de l’exécution du test, le comportement suivant : La méthode asynchrone est exécutée dans un thread parallèle différent de celui du test lui-même. Le test se terminera avant que la méthode testée ne retourne une donnée….

Dans ce cas, impossible de déterminer si une régression a été introduite dans le code testé.

 

La solution :

Dans la TPL (Task Parallel Librairy dont sont issus les mots clefs async et await) une classe est fournie dans les exemples qui permet d’exécuter les méthodes asynchrones dans un contexte compatible avec les tests unitaires : GeneralThreadAffineContext.

Malheureusement cette classe n’est pas disponible directement pour les applications Metro.

Voici donc une implémentation de la classe GeneralThreadAffineContext qui permet les tests unitaires de méthodes asynchrones au sein d’application Metro.

En utilisant cette classe, vous pouvez maintenant réellement tester vos méthode asynchrones dans vos applications Metro :

 

        [TestMethod]
        public void TestGetDataAsync()
        {
            GeneralThreadAffineContext.Run(async () =>
              {
                  IService svc = new MyService();
                  string returnedData = await svc.GetDataAsync();
              });
        }

 

Vous trouverez en téléchargement sur ce billet de blog:

  • la classe GeneralThreadAffineContext à utiliser dans vos tests. Disponible –>ici<-.
  • un exemple complet contenant tout le code source mentionné dans ce billet. Disponible –>ici<-.

 

Alors n’attendez plus !

 

- Jean-François Lavidalle -