-->

mercredi 16 mai 2012

Structure d'un projet de tests automatisés dans un contexte Agile Scrum avec Visual Studio 2010


Description de la problématique

Dans le cadre de l'automatisation des tests fonctionnels d'un projet dans un contexte Scrum, nous avons besoin de définir une méthodologie qui sera appliquée à nos différents projets de test. Cette structure doit pouvoir être mise en place simplement et rapidement.
Avec la structure suivante, il suffit de modifier les variables de contexte et quelques autres variables afin d'avoir un projet de test utilisable directement pour d'autres projets.

L'approche que nous avons mise en place pour nos projets est la suivante:
Un "Acceptance Test" est couvert par 1 test automatisé
Une fonctionnalité (PBI) est testée par 1 à n "Acceptance Test" (-> 1 à n tests automatisés par classe/fonctionnalité)
Un ensemble fonctionnel est couvert par 1 à n fonctionnalité (-> 1 à n classes par répertoire/ensemble)


Voici la structure de base que j'utilise actuellement pour mes projets de tests automatisés


  • Un répertoire common qui contient différentes classes pour l'exécution de mon projet.
  • Un répertoire UIMap qui va contenir tous mes UI Test Map du projet en cours.
  • Un fichier App.config pour les accès à mon application
  • Différents répertoires correspondant aux ensembles fonctionnels à tester

Nous allons maintenant voir en détails ce que contient chaque parties de ma structure.

App.config

Ce fichier contient l'url du Lab sur lequel doivent s'exécuter les tests automatisés, le nom de l'application, ainsi que l'url d'authentification (en recette, nous avons un module permettant d'usurper les différents profils)

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <!-- Url du Lab pour l'exécution des Coded Ui Test -->
    <add key="ApplicationAplicationBaseUrl" value="https://url.Lab.fr/"/>
    <!-- Répertoire virtuel de l'application -->
    <add key="AplicationVirtualDirectory" value="Application/"/>
    <!-- Url d'authetification -->
    <add key="InternalUsersAuthentificationUrl" value="https://authentification/log.aspx?Source="/>
  </appSettings>
</configuration>

Répertoire UIMap

Ce répertoire contient tous les UI Test Map nécessaires pour tester mon application.
Pour plus de clarté et de compréhension, un UI Test Map correspond à un ensemble fonctionnel (ici Navigation -> EnsembleNavigation)
NB: attention à ne pas nommer les répertoires "ensemble fonctionnel" et les UI Test Map avec le même nom car cela provoquerait une erreur de compilation.

Les fichiers sont créés directement dans le répertoire en faisant clic droit sur le répertoire -> Add ->New item -> Coded UI Test Map


Répertoire des ensembles fonctionnels

Le détail concernant l'écriture des tests fera l'objet d' un prochain article.
Chaque répertoire "ensemble fonctionnel" devra contenir une classe par fonctionnalité.

NB: Dans le répertoire EnsembleNavigation, il est possible d'ajouter une classe "CommonEnsemble" qui permettra de créer des fonctionnalités utilisables dans tout l'ensemble fonctionnel.

Exemple:
Ensemble:
  • Gestion des utilisateurs
Fonctionnalité:
  • Ajouter un utilisateur
  • Modifier un utilisateur
  • Supprimer un utilisateur
Acceptance test (liés à l'ajout d'un utilisateur):
  • Je suis administrateur et j'ai la possibilité de créer un utilisateur
  • Je suis modérateur et je n'ai pas accès à la page d'ajout d'un utilisateur
  • Affichage d'un message d'erreur si le champ "Nom" contient des caractères non alphanumériques
  • etc…

Répertoire Common

Voici le contenu de mon répertoire Common qui est sensiblement le même pour chaque projet


Fichier CodedUiTestbase:
C'est la classe de base de toutes les classes contenant des codedUiTest.

Cette classe sera appelée par chaque test automatisé lors de son exécution, elle contient:
  • Les constructeurs TestContext, ConfigurationContext, CodedUiTestCommons et TestRunner
  • Les fonctions d'initialisation et de nettoyage du test (lorsque le playback échoue, on appelle la fonction MyTestCleanup)


Détail du constructeur CodedUiTestCommons (TestRunner est construit de la même manière en remplaçant uniquement la clé):

public CodedUiTestCommons CodedUiTestCommons
{
     get { return _testContextInstance.Properties[CodedCommonKey] as CodedUiTestCommons; }
     set
     {
          if (_testContextInstance.Properties[CodedCommonKey] == null)
              _testContextInstance.Properties.Add(CodedCommonKey, value);
          else
              _testContextInstance.Properties[CodedCommonKey] = value;
     }
}

Détail de MyTestInitialize et MyTestCleanup:

[TestInitialize]
public virtual void MyTestInitialize()
{
     TestRunner = new TestRunner();
     CodedUiTestCommons = new CodedUiTestCommons(TestRunner);
     {
         TestContext = _testContextInstance;
     }
 
     Playback.PlaybackError += Playback_PlaybackError;
     if (!Playback.IsInitialized)
         Playback.Initialize();
}
 
static void Playback_PlaybackError(object sender, PlaybackErrorEventArgs e)
{
     Playback.Cleanup();
}
 
[TestCleanup]
public virtual void MyTestCleanup()
{
      // Quitte l'Application et ferme le navigateur.
      CodedUiTestCommons.Logout();
      Playback.PlaybackError -= Playback_PlaybackError;
      Playback.Cleanup();
}

Fichier CodedUiTestCommon:
Cette classe permet de définir les fonctions qui seront transverses à toute l'application.
Dans cet exemple, nous avons uniquement la fermeture du navigateur et la connexion de l'utilisateur (avec lancement du navigateur)

using System;
using Microsoft.VisualStudio.TestTools.UITesting;
 
namespace TestProject1.Common
{
    public class CodedUiTestCommons
    {
        private readonly TestRunner _testRunner;
        public CodedUiTestCommons(TestRunner testRunner)
        {
            _testRunner = testRunner;
        }
 
        public void Logout()
        {
            _testRunner.Navigation.Close_Browser_IE();
        }
 
        public void Logon(string login)
        {
            if (String.IsNullOrWhiteSpace(login)) throw new NullReferenceException();
 
            // On définit l'URL de la RunnerPage d'authentifiction
            var server = new ConfigurationContext();
            _testRunner.Navigation.Authenticate_And_Display_HomepageParams.UIPageviergeWindowsIntWindowUrl = server.InternalUsersAuthentificationUrl + server.ApplicationUrl;
            // On modifie le login pour l'utilisation de ma fonction authenticate
            _testRunner.Navigation.Authenticate_And_Display_HomepageParams.UITbLoginEditText = login;
 
            // Lancement du navigateur IE
            BrowserWindow.Launch();
            // L'utilisateur se connecte
           _testRunner.Navigation.Authenticate_And_Display_Homepage();
        }
    }
}

Fichier ConfigurationContext:
Cette classe permet de définir les variables de contexte de l'application à partir du fichier App.config pour les utiliser dans les tests.

namespace TestProject1.Common
{
    public class ConfigurationContext
    {
        #region Public Properties
 
        public string ApplicationUrl { get; set; }
        public string AuthentificationExterne { get; set; }
        public string InternalUsersAuthentificationUrl { get; set; }
 
        #endregion
 
        public ConfigurationContext()
        {
            var applicationBaseUrl = System.Configuration.ConfigurationManager.AppSettings["AplicationBaseUrl"];
            var applicationInternalVirtualDirectory = System.Configuration.ConfigurationManager.AppSettings["AplicationVirtualDirectory"];
 
            ApplicationUrl = applicationBaseUrl + applicationInternalVirtualDirectory;
 
            InternalUsersAuthentificationUrl = System.Configuration.ConfigurationManager.AppSettings["InternalUsersAuthentificationUrl"];
        }
    }
}


Fichier Profil:
Cette classe sert à stocker tous les différents profils et leurs spécificités ayant accès à l'application avec la possibilité de leur affecter des variables spécifiques supplémentaires

namespace TestProject1.Common
{
    /// <summary>
    /// Permet de définir les logins des profils utilisés dans les tests
    /// </summary>
    public class Profil
    {
        public struct Sylvie
        {
            public const string Login = "login";
            public const string Nom = "NOM";
            public const string Prenom = "Prenom";
            public const string Profil = "Profil";
        }
    }
}


Fichier TestRunner:
Cette classe permet d'encapsuler l'accès aux fonctions des différentes classes UIMap et permet de partager le contexte de fenêtre entre les différentes instances.

NB: Lorsque l'on créé un nouveau fichier Ui test map, il faut penser à venir l'ajouter dans ce fichier pour qu'il soit bien pris en compte.


Conclusion

Voici donc un exemple de structure qui a été mise en place et qui me permet de n'avoir plus qu'à gérer l'écriture des tests liés aux Acceptance Test.

Aucun commentaire:

Enregistrer un commentaire