Eenvoudig unittesten voor Sql Server Integration Services

Sql Server Integration Services (SSIS) is het antwoord van Microsoft op de
vraag naar ETL. ETL staat voor Extract, Transform en Load. Eigenlijk wordt er
gewoon met data geschoven, van bron(-nen) naar doel(-en).

Mocht binnen een project veel met data import gewerkt worden dan kan SSIS vrijwel zeker een hele hoop problemen oplossen. SSIS geeft de mogelijkheid om bronnen en doelen te definiëren waarna een workflow ontworpen wordt om de data te extraheren, te valideren, te transformeren en weer weg te schrijven.

Input Output

Collega’s welke met BizTalk werken komt dit bekent voor maar daar is tevens
een workflow engine aanwezig, compleet met storage. Echter voor SSIS is de
workflow slechts een middel om data te transformeren. Door de grafische
representatie en eenvoudige maar krachtige scripting is SSIS ook een stuk
basisgereedschap voor administrators.

Er is een leerkurve om met SSIS aan de gang te gaan maar hier en hier staat voldoende om er eens mee te beginnen.

Een stuk SSIS logica (package) kan zowel direct in Sql Server bewaard worden,
maar ook op schijf opgeslagen worden.  Zo’n package krijgt de extensie DTSX.
Hoewel opslag op schijf de package kwetsbaar maakt voor systeem-afhankelijke
paden, heeft het wel degelijk voordelen. De package wordt zo makkelijk
transportabel in een OTAP omgeving met verschillende SQL servers en dit maakt de package ook beschikbaar voor unittesten.

Want soms lijkt iets heel lastig maar is het in wezen juist er simpel. Binnen
ons team zijn wij met de bouw van Business Intelligence Software (BIS) begonnen waarbij SSIS de basis is voor de import van data en bestanden uit csv bestanden, mappen en webservices. En hierbij kwam al snel de vraag hoe we konden bewijzen dat onze import met verschillende scenario’s kon omgaan.

Uiteindelijk bleek de oplossing heel eenvoudig te zijn. Voor SSIS is ook een
.Net API beschikbaar. Het is hiermee zelfs mogelijk om SSIS packages volledig
uit te coderen maar daar waren wij niet in geïnteresseerd. Wel is het mogelijk
om zo via code een package te laden, de variabelen te vullen en uit te voeren.
Vervolgens is te controleren of de package correct uitgevoerd is. Uiteindelijk
kan gecontroleerd worden of de package correct gereageerd heeft op de
gecontroleerde input.

Hoewel dit meer een integratie test is omdat het mocken van services
en databases hierbij wat lastig is, scheelt deze aanpak veel tijd voor het
ontwikkelteam. Anders moet tijdens het coderen steeds handmatig een scenario
afgewerkt worden en bij iedere wijziging mogen die weer opnieuw gecontroleerd
worden.

Maak dus naast het SSIS project een unittest project aan en voeg
onderstaande references toe.

SSIS API Assemblies

Maak vervolgens een unittest aan welke de package in het geheugen laadt.

In onderstaande voorbeeld wordt eerst een csv uitgelezen. Vervolgens wordt
een sommatie weggeschreven in een ander bestand. Bus beide bestandsnamen worden opgegeven bij de package.

using System;using System.Text;using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.SqlServer.Dts.Runtime;
using Microsoft.SqlServer.Dts.Pipeline;
using SSISRumtime = Microsoft.SqlServer.Dts.Runtime.Wrapper;
using System.IO;
namespace TestProject
{
  [TestClass]
  public class UnitTest1
  {

  [TestMethod]
  public void TestMethod1()
  {
    Application application = new Application();
    Package package = null;
    try
    {
      string inputFile =
        @"C:\TMP\Integration Services
        Project\TestProject\InputFiles\Test1.txt";
      string outputFile =
        @"C:\TMP\Integration Services
        Project\TestProject\OutputFiles\Test1.txt";
      package = application.LoadPackage(
        @"C:\TMP\Integration Services Project\Integration Services
        Project\bin\Package.dtsx", null);
      package.Connections["ImportTest"].ConnectionString =
        inputFile;
      package.Connections["ImportResult"].ConnectionString =
        outputFile;
      Microsoft.SqlServer.Dts.Runtime.DTSExecResult results =
        package.Execute();

      Assert.AreEqual(Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
        results, "Execution of package failed");
      Assert.IsTrue(File.Exists(outputFile));
      string outputTextExpected =
        "<html><body>1000</body></html>";
      string outputTextActual = "";
      using (StreamReader streamReader =
                           File.OpenText(outputFile))
      {
        outputTextActual = streamReader.ReadToEnd();
      }
      Assert.AreEqual(outputTextExpected, outputTextActual);
    }
    finally
    {
      package.Dispose();
      package = null;
    }
  }
}
}

Omdat we weten wat we als invoer meegeven, weten we ook wat we mogen
verwachten.

We roepen dus Execute op de package aan en controleren of de succesvol is
uitgevoerd. Maar we moeten wel het resultaat ook controleren. Daarom wordt
uiteindelijk het doelbestand uitgelezen en op inhoud vergeleken.

SSIS Unittest passed

Uiteindelijk levert deze test een groen vinkje op. Yes! (en vieren met een
kopje koffie, want: “Vier je successen”).

Dit geeft een aardige start.

Mocht dit  uiteindelijk als unittest mechanisme te licht bevonden worden, dan
zijn er ook zwaardere middelen aanwezig.

Advertenties