This post has already been read 103 times!

SSISTester

Quand j'ai commencé à réfléchir à une infrastructure de test pour les packages SSIS, j'ai trouvé trois aspects importants. Tout d'abord, je voulais avoir un UX semblable à l'écriture de tests en utilisant l'infrastructure de test de Visual Studio , donc la méthode typique mettant en cause le programme d'installation, de vérification et de nettoyage (aka le démontage) étapes devaient être appliqués. Deuxièmement, je voulais utiliser outils existantes et éprouvées pour écrire, d'exécuter et de gérer des tests. Une fois de plus, Visual Studio est le choix évident. Et Troisièmement, je voulais être en mesure de tests de code en c#. Dans cet esprit que j'ai écrit SSISTester, une bibliothèque .NET qui se trouve sur le dessus le runtime SSIS et expose une API qui vous permet d'écrire et d'exécuter des tests pour les packages SSIS. Les principaux composants logiques de la bibliothèque sont dépeints dans Figure1.

Figure 1 composants logiques de la bibliothèque de SSISTester

Le dépôt de paquets est utilisé pour stocker les premières représentations XML des paquets de la cible. Chaque fois qu'un test est exécuté, une nouvelle instance de la classe Microsoft.SqlServer.Dts.Runtime.Package est désérialisée à partir XML avec tous les champs et les propriétés leurs valeurs par défaut. Ceci est important parce que vous ne voulez pas différents tests qui ciblent le même package pour réutilisation accidentellement toute valeur définie par tests précédents.

Les instances de classes de test sont stockés dans le référentiel de Test. Ces classes contiennent des méthodes qui implémentent vos cas de test. Lorsqu'un test est exécuté, ces méthodes sont appelées par le moteur d'essai. Les règles spécifiques qui doivent être suivies lors de la création des classes de test seront décrite en détail plus tard.

Métadonnées contient les attributs nécessaires pour décorer une classe de test, donc il peut être reconnu comme une application de test. Le moteur de Test recherche ces attributs lors du chargement des tests dans le référentiel de Test.

Le contexte de Test représente un ensemble de classes qui donnent accès à l'information de DUREE au cours des différentes phases de l'exécution de tests. Par exemple, vous pouvez utiliser ces classes pour accéder aux différents aspects d'un paquet à l'épreuve, comme les variables, propriétés, contraintes précédentes, les gestionnaires de connexions, en cours d'exécution de tâche, erreurs de paquet et ainsi de suite.

Le moteur de Test désigne les classes de base et les interfaces de l'API SSISTester qui utilisent directement le runtime managé de SSIS. Ils sont utilisés pour charger des packages et classes d'essai dans leurs référentiels respectifs, aussi bien quant à l'exécution de tests et de créer des résultats des tests.

Mini ETL

Pour créer des packages et les classes de test, je vais utiliser Visual Studio 2012 et SQL Server 2012 et j'utiliserai trois paquets pour illustrer un scénario ETL simple dans quel client données, envoyées sous forme de fichier texte sont transformées et stockées dans une base de données. Les paquets sont CopyCustomers.dtsx, LoadCustomers.dtsx et Main.dtsx. CopyCustomers.dtsx copie le fichier Customers.txt d'un endroit à l'autre et sur la façon dont il convertit tous les noms des clients de texte en majuscules. Customers.txt est un simple fichier CSV qui contient les ID et les noms de clients, comme suit :

id,name
1,company1
5,company2
11,company3

LoadCustomers.dtsx charge les noms de convertis la base de données démo. Avant il charge les données dans une table cible appelée Customers­mise en scène, il tronque toutes les données précédemment stockées. À la fin du processus, il stocke le nombre de clients dans une variable. Voici le script pour créer la base de données de démonstration et de la table CustomersStaging :

CREATE
DATABASE [Demo]
GO
USE [Demo]
GO
CREATE TABLE [dbo].[CustomersStaging](
  [Id] [int] NULL,
  [Name] [nvarchar](255) NULL
) ON [PRIMARY]
GO

Le Main.dtsx contient deux tâches d'exécution de Package qui exécutent les éléments CopyCustomers.dtsx et charge­Customers.dtsx, respectivement. Les gestionnaires de connexions à la fois CopyCustomers.dtsx et LoadCustomers.dtsx sont configurés à l'aide des expressions et des variables de package. Les mêmes variables de package sont extraites de la configuration de package parent lorsque exécuté dans un autre package.

Création de tests unitaires

Pour commencer, créez un projet de console et ajoutez des références d'assembly à SSIS.Test.dll et SSIS.Test.Report.dll. Je vais tout d'abord créer un test unitaire pour le paquet de CopyCustomers.dtsx. La figure 2 montre le flux de contrôle (à gauche) et le flux de données (à droite) pour CopyCustomers.dtsx.


Figure 2 contrôle débit (à gauche) et des flux de données (à droite) du Package CopyCustomers.dtsx

Chaque test unitaire est implémenté dans une classe simple qui dérive de la classe BaseUnitTest et doit être décorée avec l'attribut UnitTest :

[UnitTest("CUSTOMERS", "CopyCustomers.dtsx")]
public class CopyCustomersTest : BaseUnitTest{
  protected override void Setup(SetupContext context){}
  protected override void Verify(VerificationContext context){}
  protected override void Teardown(TeardownContext context){}
}

Les marques d'attribut UnitTest une classe en tant qu'unité d'essai mise en oeuvre donc il peut être trouvé par le moteur d'essai. Le premier paramètre correspond au référentiel paquet où un paquet de cible sera chargé pendant l'exécution du test, les visiteurs dans cet exemple. Le deuxième paramètre peut être le nom d'un paquet de cible, le chemin d'accès à une tâche dans le flux de contrôle, le chemin d'accès à un gestionnaire d'événements ou le chemin d'accès à une contrainte précédente. Dans cet exemple, c'est le nom du package CopyCustomers.dtsx parce que je veux tester l'ensemble du paquet. Fondamentalement, l'attribut UnitTest indique au moteur de Test pour rechercher le paquet de CopyCustomers.dtsx dans le référentiel de clients et l'exécuter lors de l'essai de CopyCustomersTest.

BaseUnitTest que toutes les implémentations de test d'unité doivent dériver de la classe de base contient trois méthodes qui doivent être mises en œuvre : Configurer, vérifier et le démontage.

Ces trois méthodes sont exécutées au cours des phases d'essais différents. La méthode d'installation s'exécute avant un paquet de la cible est exécuté par le moteur de Test. Le programme d'installation prépare le paquet et toutes les entrées et les sorties que le paquet dépend donc peut être validé et exécuté avec succès. Dans l'exemple suivant, j'ai mis des chemins pour les variables de package qui sont utilisés comme des chaînes de connexion dans les gestionnaires de connexions :

protected override void Setup(SetupContext context){
  if(File.Exists(@"C:\TestFiles\Archive\Customers.txt"))
    File.Delete(@"C:\TestFiles\Archive\Customers.txt");
  if(File.Exists(@"C:\TestFiles\Converted\Customers.txt"))
    File.Delete(@"C:\TestFiles\Converted\Customers.txt");
  DtsVariable sourceFile = context.Package.GetVariable("SourcePath");
  sourceFile.SetValue(@"\\nc1\Customers\Customers.txt");
  DtsVariable destinationFile = 
    context.Package.GetVariable("DestinationPath");
  destinationFile.SetValue(@"C:\TestFiles\Archive\Customers.txt");
  DtsVariable convertedFile = 
    context.Package.GetVariable("ConvertDestinationPath");
  convertedFile.SetValue(@"C:\TestFiles\Converted\Customers.txt");
}

Après que la méthode d'installation a été exécuté avec succès, le moteur de Test exécute le package de cible. Lorsque le package est exécuté, le moteur de Test appelle la méthode Verify et je peux vérifier si mes affirmations sont vraies :

protected override void Verify(VerificationContext context){
  Assert.AreEqual(true, 
    context.Package.IsExecutionSuccess);
  Assert.AreEqual(true, 
    File.Exists(@"C:\TestFiles\Archive\Customers.txt"));
  Assert.AreEqual(true, 
    File.Exists(@"C:\TestFiles\Converted\Customers.txt"));
  string[] lines = 
    File.ReadAllLines(@"C:\TestFiles\Converted\Customers.txt");
  Assert.AreEqual("COMPANY2", lines[2].Split(',')[1]);
}

La première instruction assert vérifie si le package est exécuté avec succès. L'autre détermine si la tâche de système de fichier FST copie Source fichier copié le fichier \\nc1\Customers\Customers.txt dans le dossier C:\TestFiles\Archive\. Les deux derniers affirme vérifie si les données de noms des clients de convertir DFT flow dénominations sociales tâche correctement converti en majuscules. Plus tôt, j'ai décrit brièvement le contexte de test. Ici vous pouvez voir comment j'ai utilisé le paramètre de contexte pour accéder à un objet de paquet dans les méthodes d'installation et de vérifier.

À la fin du test, j'utilise la méthode de démontage pour supprimer les fichiers qui ont été copiés ou créés par le package :

protected override void Teardown(TeardownContext context){
  File.Delete(@"C:\TestFiles\Archive\Customers.txt");
  File.Delete(@"C:\TestFiles\Converted\Customers.txt");
}

Tests de tâches de flux de contrôle

Les tests peuvent cibler des tâches spécifiques dans le flux de contrôle aussi bien. Par exemple, pour tester le flux de données de clients de charge DFT dans le package LoadCustomers.dtsx, j'ai utilisé un paramètre supplémentaire de l'attribut UnitTest, appelé ExecutableName, pour indiquer au moteur de Test que je veux tester cette tâche :

[UnitTest("CUSTOMERS", "LoadCustomers.dtsx",ExecutableName =
  @"

LoadCustomers]

!SEQC Load]

DFT Load customers]

ExecutableName reprsente le chemin d'accs qui combine les noms des conteneurs imbriqus tout commence par un nom de paquet.

Flux de donnes et de contrle pour LoadCustomers.dtsx sont affichs dans Figure3.


Figure 3 contrle dbit ( gauche) et des flux de donnes ( droite) du Package LoadCustomers.dtsx

Lorsqu'un test vise une tche spcifique, seule cette tche est excute par le moteur d'essai. Si la bonne excution de la tche de la cible dpend de l'excution des tches prcdentes, les rsultats de l'excution de ces tches doivent tre gnr manuellement. Le flux de donnes de clients de charge DFT s'attend que la table cible soit tronqu par la tche SQL Truncate CustomersStaging. En outre, le flux de donnes attend le fichier Customers.txt transform un endroit prcis. Car ce fichier est cr par le paquet CopyCustomers.dtsx, j'ai besoin de le copier manuellement. Voici la mthode d'installation qui fait tout cela :

protected override void Setup(SetupContext context){
 string dbConStr = @"Data Source=.;Integrated Security=SSPI;Initial Catalog=Demo";
 string ssisConStr = @"Provider=SQLNCLI11;" + dbConStr;
 File.Copy(@"\\nc1\Customers\Customers.txt", 
    @"C:\TestFiles\Converted\Customers.txt");
 context.DataAccess.OpenConnection(dbConStr);
 context.DataAccess.ExecuteNonQuery("truncate table [dbo].[CustomersStaging]");
 context.DataAccess.CloseConnection();
 DtsConnection conn = context.Package.GetConnection("CustomerDB");
 conn.SetConnectionString(ssisConnStr);
 conn = context.Package.GetConnection("CustomersSrc");
 conn.SetConnectionString(@"C:\TestFiles\Converted\Customers.txt");
}

l'aide de File.Copy, je copie le Customers.txt l'emplacement attendu par le flux de donnes. Ensuite, j'utilise la proprit DataAccess de la SetupContext pour excuter une instruction truncate sur la table cible. Cette proprit expose un wrapper ADO.NET lger qui vous permet d'excuter des commandes SQL sans avoir utiliser des classes SqlConnection et SqlCommand chaque fois que vous souhaitez accder la base de donnes. la fin, j'utilise la proprit de paquet pour dfinir les chanes de connexion pour les gestionnaires de connexions sous-jacent.

Tests de contraintes prcdentes

Il est galement possible d'crire des tests qui ciblent les contraintes prcdentes. Par exemple, la CountConstraint qui prcde la tche de script SCR CheckCount dans le package LoadCustomers.dtsx a une expression qui vrifie si la variable CustomerCount est suprieure zro. Si cette expression a la valeur true et que la tche SEQC de charge s'excute correctement, puis la tche de script est excute. Figure 4 illustre l'unit complte de test.

La figure 4 le Test unitaire complet

[UnitTest("CUSTOMERS", "LoadCustomers.dtsx",
    PrecedenceConstraintsTestOnly = true))]
public class LoadCustomersConstraintsTest : BaseUnitTest{
 private DtsPrecedenceConstraint _countConstraint;
 protected override void Setup(SetupContext context){
 DtsVariable variable = context.Package.GetVariable("CustomerCount");
 variable.SetValue(0);
 _countConstraint =
 context.Package.GetPrecedingConstraintForPath(
 @"" />

!LoadCustomers]

SCR CheckCount].[CountConstraint]

Pour prparer la contrainte de prcdence tester, j'ai besoin de faire deux choses. Tout d'abord, je dois dfinir la variable CustomerCount une valeur, parce qu'il veut dire l'expression de la contrainte de prcdence. Dans ce cas, je choisis de 0. Ensuite, j'ai mis le rsultat de l'excution de la tche prcdente russite, chec ou l'achvement. Je fais cela en utilisant la mthode SetExecutionResult pour simuler le rsultat de la tche prcdente. Cela signifie que CountConstraint devrait ont la valeur false, et c'est ce que j'attends dans la mthode Verify. Vous pouvez avoir qu'une seule catgorie o vous implmenter les tests unitaires pour toutes les contraintes prcdentes dans un paquet. Il n'y a donc aucun chemin de cible la contrainte particulire dans l'attribut UnitTest, seulement un indicateur Boolean qui indique au moteur qu'il s'agit d'une classe de test unitaire pour les contraintes de prcdence. La raison en est qu'avec les contraintes de prcdence, il n'y a pas besoin d'excuter le package ou la tche avant la mthode Verify est appele.

L'excution de Tests unitaires

Avant je peux excuter mes tests, j'ai besoin de charger des paquets de cible et tests dans leurs dpts. Pour ce faire, j'ai besoin d'une rfrence au moteur de Test. Ouvrez le fichier Program.cs et remplacez la mthode Main vide avec celui-ci :

static void Main{
 IUnitTestEngine engine = 
    EngineFactory.GetClassInstance();
 engine.LoadPackages("CUSTOMERS", @"C:\TargetPackages\");
 engine.LoadUnitTests();
 engine.ExecuteUnitTestsWithGui();
}

La premire ligne cre une rfrence au moteur de Test. Pour charger tous les packages dans le dossier C:\TargetPackages\ dans le rfrentiel de clients, j'utilise la mthode LoadPackages. La mthode de LoadUnitTests charge toutes les classes dans l'assembly appelant qui sont dcores avec l'attribut UnitTest dans le rfrentiel de test spcifi. Enfin, j'appelle ExecuteUnitTestsWithGui pour dmarrer l'excution de tests et d'ouvrir la surveillance GUI, illustre la Figure5.


Figure 5 la GUI de surveillance pendant l'excution de Tests

Le GUI dans Figure5 est pratique si vous voulez tester localement sur votre machine et que vous ne voulez pas commencer Visual Studio. Si vous souhaitez tester les paquets sur un serveur, vous pouvez faire des petites modifications au programme et planifier son excution de tests directement sur un serveur de builds, par exemple :

static void Main{
 IUnitTestEngine engine = 
    EngineFactory.GetClassInstance();
 engine.LoadPackages("CUSTOMERS", @"C:\TargetPackages\");
 engine.LoadUnitTests();
 engine.ExecuteUnitTests();
 engine.UnitTestResults.SaveAsHtml(@"C:\TestResults\");
}

L'interface de IUnitTestEngine a la proprit de UnitTestResults qui vous permet d'accder aux rsultats des tests et de les enregistrer sous forme d'un rapport HTML. J'ai remplac ExecuteUnitTestsWithGui par ExecuteUnitTests, qui ne montre pas la surveillance GUI. Vous pourriez galement excuter des tests l'intrieur de la Visual Studio ou utiliser ReSharper, donc vous n'avez pas besoin dmarrer le programme console. Pour ce faire, j'ai cr la nouvelle classe, appele SSISUnitTestAdapter, montr dans Figure 6.

Figure 6 la classe de SSISUnitTestAdapter

[TestClass]
public class SSISUnitTestAdapter{
 IUnitTestEngine Engine {get;set;}
 [AssemblyInitialize]
 public static void Prepare(TestContext context){
 Engine = EngineFactory.GetClassInstance();
 Engine.LoadPackages("CUSTOMERS", @"C:\TargetPackages\");
 Assembly testAssembly =
 Assembly.GetAssembly(typeof(CopyCustomersTest));
 Engine.LoadRepositoryUnitTests(testAssembly, "CUSTOMERS");
 }
 [TestMethod]
 public void CopyCustomersTest(){
 Engine.ExecuteUnitTest(typeof(CopyCustomersTest));
 }
 [TestMethod]
 public void LoadCustomersTest(){
 Engine.ExecuteUnitTest(typeof(LoadCustomersTest));
 }
 [TestMethod]
 public void LoadCustomersConstraintsTest(){
 Engine.ExecuteUnitTest(typeof(LoadCustomersConstraintsTest));
 }
}

Si vous avez travaill avec l'unit de Microsoft framework avant de tests, vous reconnatrez les attributs TestClass, AssemblyInitialize et divers. Les trois mthodes d'essai, CopyCustomersTest, LoadCustomersTest et LoadCustomersConstraintsTest, enveloppement l'appel de la mthode ExecuteUnitTest, qui son tour excute les mthodes d'installation, de vrifier et de destruction de la classe qui est pass comme paramtre. La mthode Prepare cre l'objet de Test moteur et charge paquets et unit des tests dans leurs dpts respectifs. J'ai utilis des mthodes lgrement diffrentes, appels LoadRepositoryUnitTests pour charger les tests lis au rfrentiel clients seulement. Ceci est utile si vous ne voulez pas charger tous les tests. Vous pouvez excuter tous les tests en cliquant sur Tests | Excuter | Tous les Tests en Visual Studio.

Cration de Tests d'intgration

L'ide de base de tests unitaires est d'isoler tous les effets possibles Autres paquets ou tches peuvent avoir sur celui mis l'essai. Parfois, il peut tre difficile de crer une configuration de test ralistes et les conditions initiales ncessaires un test unitaire assurer le colis ou la tche teste se comporte comme une partie d'un processus ETL complet. Parce que vous implmentez gnralement les processus ETL avec un certain nombre de paquets, vous devez effectuer des tests d'intgration pour s'assurer que chaque paquet fonctionne bien lorsqu'il est excut dans le cadre de ce processus. L'ide est de dfinir des points de sondage dans votre processus ETL o vous souhaitez effectuer des tests, sans avoir arrter tout le processus. Que le processus progresse et atteint le point de dtection, vos tests sont excuts, et vous pouvez vrifier un processus d'ETL work-in-progress en direct ; d'o le nom, le test en direct.

Un test en direct est en fait une condition-post ? dfini pour un gestionnaire de paquet, tche ou vnement ? qui doit tre satisfaite aprs le paquet, gestionnaire de tche ou d'un vnement a excut. Cette post-condition correspond l'tape de vrification d'un test unitaire. Tests de Live sont distinguent par les tests unitaires parce qu'il n'est pas possible de prparer le test avant l'excution du package ou pour excuter une tape de nettoyage par la suite. C'est parce que contrairement un test unitaire, un test en direct n'excute pas le paquet ; C'est l'inverse : Un package s'excute un test en ce qui concerne le point pouss pour lequel est dfinie une post-condition.

La figure 7 illustre cette diffrence. Notez la position du colis dans les deux chiffres. Lorsque des tests unitaires en cours d'excution, le moteur de Test excute explicitement un test unitaire en appelant les mthodes de son installation, vrification et destruction. Un package est excut dans le cadre de cette squence d'installation-vrifier-dmontage.


Figure 7 diagrammes de squence pour l'unit d'essai ( gauche) et vivent ( droite) l'excution de tests

En revanche, lorsque vous excutez des tests direct, le moteur de Test excute un package explicitement, qui son tour dclenche l'excution de mthodes d'action qui implmentent les post-conditions pour un package et ses tches.

Afin de crer un test en direct pour le paquet de CopyCustomers.dtsx, j'ai cr la nouvelle classe, appele CopyCustomers, montr dans Figure 8.

Figure 8 la classe de CopyCustomers

[ActionClass("CUSTOMERS", "CopyCustomers.dtsx")]
public class CopyCustomers : BaseLiveTest{
 [ActionMethod(@"" />

!CopyCustomers]")]   public void TestWholePackage(ActionContext context){     Assert.AreEqual(true, context.Package.IsExecutionSuccess);   }   [ActionMethod(@"

CopyCustomers]

!FST Copy Source File]")]   public void TestCopySourceFile(ActionContext context){     Assert.AreEqual(true, context.ActiveExecutable.IsExecutionSuccess);     Assert.AreEqual(true, File.Exists(@"C:\TestFiles\Archive\Customers.txt"));   }   [ActionMethod(@"

CopyCustomers]

!DFT Convert customer names]")]   public void TestConvertCustomersNames(ActionContext context){     Assert.AreEqual(true, context.ActiveExecutable.IsExecutionSuccess);     string[] lines = File.ReadAllLines(@"C:\TestFiles\Converted\Customers.txt");     Assert.AreEqual("COMPANY2", lines[2].Split(‘,’)[1]);   } }

Chaque classe de test en direct doit dériver de la classe BaseLiveTest, une différence majeure par rapport à un test unitaire. La classe BaseLiveTest est utilisée en interne par le moteur de Test pour exécuter des tests direct et possède pas de méthodes qui doivent être remplacées. L'attribut ActionClass marque cette classe comme un test en direct. Les paramètres sont les mêmes que lorsque vous utilisez l'attribut UnitTest — paquet de référentiel et de la cible. Notez que contrairement aux tests unitaires où chaque test est implémentée dans une classe unique, distincte, qu'une seule classe est nécessaire pour mettre en œuvre tous les post-conditions pour un package. Les classes de test en direct peuvent avoir un nombre arbitraire de post-conditions qui devrait être évaluée. Ces post-conditions correspondent à la méthode Verify dans un test unitaire et sont implémentées comme des méthodes décorées avec l'attribut ActionMethod. Dans l'exemple de Figure 8, j'ai une post-condition pour chaque tâche dans le package et l'autre pour l'emballage proprement dit. ActionMethod accepte un chemin vers la tâche de la cible, qui est le même que le ExecutableName dans l'attribut UnitTest. Cela indique au moteur de Test pour exécuter cette méthode lorsque la tâche de la cible est exécutée. Contrairement à la méthode Verify, qui est toujours exécutée, ces post-conditions ne peuvent pas être appelées lorsque, par exemple, la tâche cible n'exécute pas correctement, ou la contrainte précédente a la valeur false. Le paramètre ActionContext fournit la même fonctionnalité que la VerificationContext.

L'exécution des Tests Live

Les étapes nécessaires pour exécuter des tests direct sont légèrement différentes que lors de l'exécution de tests unitaires. Pour exécuter des tests direct, remplacez la méthode Main dans le fichier Program.cs par le code dans Figure 9.

Figure 9 la méthode principale pour l'exécution des Tests Live

static void Main{
  string dbConStr = @"Data Source=.;Integrated Security=SSPI;Initial Catalog=Demo";
  string ssisConStr = @"Provider=SQLNCLI11;" + dbConStr;
  ILiveTestEngine engine = 
    EngineFactory.GetClassInstance<ILiveTestEngine>();
  engine.LoadPackages("CUSTOMERS", @"C:\TargetPackages\");
  engine.LoadActions();
  ExecutionParameters params = new ExecutionParameters();
  params.AddVariable(@"

Main].[ConnectionString]

!Main].[CopyCustomersPath]", @"C:\TargetPackages\CopyCustomers.dtsx");   params.AddVariable(@"

Main].[LoadCustomersPath]

!Main].[ConvertDestinationPath]",     @"C:\TestFiles\Converted\Customers.txt");   params.AddVariable(@"

Main].[DestinationPath]

!Main].[SourcePath]", @"\\nc1\Customers\Customers.txt");   engine.SetExecutionParameters(parameters);   engine.ExecuteLiveTestsWithGui("CUSTOMERS", "Main.dtsx"); }

J'ai besoin d'une instance de ILiveTestEngine, que je crée à l'aide de EngineFactory. Chargement des packages, c'est le même que lors de l'utilisation de IUnitTestEngine. La méthode de LoadActions charge de toutes les actions définies dans l'assembly appelant et est pratiquement l'équivalent de charge­UnitTests. À ce stade, cependant, la similitude avec l'unité teste s'arrête. Au lieu d'exécuter des tests unitaires, je dis le moteur de Test pour exécuter le package de Main.dtsx en appelant le ExecuteLiveTestsWithGui.

Lorsque le package Main.dtsx démarre, il fonctionne le CopyCustomers.dtsx par l'exécution de la tâche CopyCustomers de l'EPT. Chacun terminé avec succès tâche dans les déclencheurs de CopyCustomers.dtsx une des méthodes d'action correspondante dans la classe CopyCustomersLiveTests. Il est important de noter que ce test a implicitement vérifie les paramètres de configuration du package CopyCustomers.dtsx.

Variables configurées héritent leurs valeurs le paquet Main.dtsx. Veuillez noter que ces variables sont utilisées comme des chaînes de connexion dans les gestionnaires de connexions de fichiers plats du package CopyCustomers.dtsx. Cela signifie essentiellement que des succès de l'exécution des tâches dans le paquet de CopyCustomers.dtsx dépend de savoir si le transfert de valeur entre ces deux paquets fonctionne correctement. Il s'agit d'un exemple simple de comment les interactions et les dépendances entre paquets sont testés, mais vous pouvez imaginer des scénarios plus complexes, où des tests unitaires isolé ne serait pas suffisant pour couvrir le cas de test.

Test moteur Internals

La classe de base implémentant les principales fonctions de la bibliothèque SSISTester est TestEngine. C'est une classe interne qui est exposée via les interfaces IUnitTestEngine et ILiveTestEngine. Les deux méthodes qui révèlent la plupart de la logique interne sont LoadUnitTests (montré dans Figure 10) et ExecuteUnitTests.

Figure 10 la méthode de LoadUnitTests

public void LoadUnitTests(){
  Assembly assembly = Assembly.GetCallingAssembly();
  IEnumerable<Type> types = assembly.GetTypes().Where(t => t.GetCustomAttributes(false).OfType<UnitTestAttribute>().Any() && 
    t.BaseType != null && t.BaseType.Name.Equals("BaseUnitTest"));
  foreach (Type t in types)
  {
    var attribute =
      t.GetCustomAttributes(false).OfType<UnitTestAttribute>().Single();
    DtsPackage package =
      _packages[attribute.Repository].GetForName(attribute.PackageName);
    string executable = attribute.ExecutableName;
    bool precedenceTestOnly = attribute.PrecedenceConstraintsTestOnly;
    var test = (BaseUnitTest)Activator.CreateInstance(t);
    test.TestClass = t;
    test.SetTestTargets(package, executable, precedenceTestOnly);
    test.Started += BaseUnitTestStarted;
    test.Finished += BaseUnitTestFinished;
    _unitTests.Add(test);
  }
}

LoadUnitTests itère fondamentalement toutes les classes décorées avec l'attribut UnitTest et crée une instance de chacun. Ces instances sont alors castées en BaseUnitTest et sont assignés le package cible précédemment chargé depuis le dépôt de paquets. À la fin, toutes les instances sont enregistrés dans la liste de _unitTests. La méthode ExecuteUnitTests itère toutes les instances de BaseUnitTest et appelle ExecuteTests sur chacune :

public void ExecuteUnitTests(){
  foreach (BaseUnitTest t in _unitTests){
    t.ExecuteTest();
  }
}

L'exécution de tests unitaires est implémentée dans la méthode ExecuteTest (montré dans Figure 11) dans la classe BaseUnitTest.

Figure 11 la ExecuteTest, méthode

public void ExecutTest(){
  Result = new UnitTestResult(Package, Executable) { TestOutcome =
    TestOutcome.InProgress, StartedAt = DateTime.Now };
  ExecuteSetup(CreateSetupContext());
  if (!Result.IsSetupSuccess)
    ExecuteTeardown(CreateTeardownContext());
  else{
    if(!PrecedenceOnly)
      Executable.Execute();
    ExecuteVerify(CreateVerifyContext());
    ExecuteTeardown(CreateTeardownContext());
    Result.FinishedAt = DateTime.Now;
  }
}

L'aspect le plus important de cette méthode est qu'elle exécute les méthodes d'installation, de vérifier et de destruction, mais aussi l'ensemble de la cible.

Leave a Reply

Post Navigation