2016-11-21 1 views
0

Ich habe mein bestes getan, um der Weisheit in http://www.sommarskog.se/share_data.html und der tSQLt-Dokumentation zu folgen; versuchen, meine gespeicherten Prozeduren leicht und relativ unkomplex zu halten, so dass sie leicht testbar sind. So finde ich mich selbst eine temporäre Tabelle in einer primären gespeicherten Prozedur erstellen und dann auf dieser temporären Tabelle in "sekundären" gespeicherten Prozeduren arbeiten, die von der primären aufgerufen werden. Das funktioniert ziemlich gut, aber es erweist sich als etwas schwierig zu testen.Testen einer gespeicherten Prozedur, die auf der temporären Tabelle eines Aufrufers ausgeführt wird

Wenn Sie eine "sekundäre" gespeicherte Prozedur isoliert testen, muss die temporäre Tabelle bereits vorhanden sein. Es sieht so aus, als würde die Erstellung der temporären Tabelle in einer [Set Up]-Prozedur nicht für die Komponententests beibehalten werden, sondern für eine vollständige Tabelle.

Also, um zu vermeiden, dass die CREATE TABLE #temp in jeder Unit-Test zu wiederholen (mit seiner vollen Spaltendefinition), ich bin eine Variation der folgenden Aktionen ausführen:

EXEC tSQLt.NewTestClass 'SEtest'; 
GO 

CREATE PROCEDURE [SEtest].[SetUp] 
AS 
BEGIN 
    CREATE TABLE SEtest.temptemplate (col1 int); 
END; 
GO 

CREATE PROCEDURE [SEtest].[test example] 
AS 
BEGIN 
    -- Assemble 
    SELECT TOP (0) * INTO #temp FROM SEtest.temptemplate; 
    INSERT INTO #temp (col1) 
    VALUES (1),(2),(5),(7); 

    -- Act 
    EXEC dbo.REMOVE_EVEN_NUMBERS; 

    -- Assert 
    SELECT TOP (0) * INTO #expected FROM #temp; 
    INSERT INTO #expected (col1) 
    VALUES (1),(5),(7); 

    EXEC tSQLt.AssertEqualsTable '#expected', '#temp'; 
END; 
GO 

es irgendwelche bessere Möglichkeiten tSQLt mit Teilung in Einklang zu bringen Daten zwischen gespeicherten Prozeduren über temporäre Tabellen?

+0

"Ich bin dabei, eine temporäre Tabelle in einer primären gespeicherten Prozedur zu erstellen und dann auf dieser temporären Tabelle in" sekundären "gespeicherten Prozeduren zu arbeiten, die von der primären aufgerufen werden" - Ich vermeide dieses Muster wo immer möglich. Sobald die Implementierung aus einer gespeicherten Prozedur "leckt", wird es schwieriger zu warten und zu testen. Eine Inline-Tabellenwert-Funktion kann oft eine Lösung sein –

+0

Mitch, ich muss widersprechen. In diesem Kontext ist die Definition der Tabelle #temp Teil des Vertrags zwischen dem Sproc und dem Aufrufer.Daher ist es nicht schwierig, das Verfahren zu warten, wenn Sie die richtigen Tests durchführen. Allerdings stimme ich zu, dass es ein wenig hässlich ist (aber manchmal ist T-SQL hässlich). –

+0

Das Einzige, was mir dabei helfen könnte, wäre eine prozessbasierte, permanente Tabelle. Solange es mir nichts ausmacht, dass die Performance nicht in tempdb liegt und ich ein zusätzliches Objekt in der Datenbank habe, kann ich es wahrscheinlich wie üblich in Tests testen. – NReilingh

Antwort

2

Es gibt wirklich keinen besseren Weg.

Die Verwendung einer #temp-Tabelle als Tabellenwert-Parameterreferenz ist in T-SQL inhärent hässlich und führt auch in den Tests zu Hässlichkeit. Ihre Tests scheinen jedoch gut durchdacht zu sein und sollten das liefern, wonach Sie suchen.

Die einzige Verbesserung zu Ihrem Muster Ich würde vorschlagen, die SEtest.temptemplate Tabelle im Testschema permanent zu erstellen, anstatt es bei jedem Test neu zu erstellen.

Verwenden SELECT ... INTO, um testspezifische Tabellen zu erstellen, ist ein Muster, das ich überall in meinen Tests verwende. Und da Sie keine temporären Tabellen in Unterprozeduren erstellen können, ist dies die einzige saubere Option, die wir haben.

In beiden Fällen verwenden Sie keine CREATE TABLE-Anweisung in Ihren Tests, um die #temp-Tabelle zu erstellen, da dies zu einem Wartungs-Albtraum würde, sollte sich das Tabellenschema jemals ändern.


Update:

Es gibt eine Alternative, die Sie vielleicht zu prüfen. Da Ihre #temp-Tabelle im Grunde genommen ein Tabellenwertparameter ist, wäre es keine schlechte Idee, einen Tabellentyp zu verwenden. Jetzt ist, dass noch ungeschickt, aber es erhöht die Wartbarkeit an allen Ecken und Ende:

DECLARE @template AS dbo.tabletype; 
SELECT * INTO #temptable FROM @template; 

, die für eine wenig klare Lesbarkeit macht, vor allem, wenn der Name des Tabellentypen ist ausdrucksvoll (und es ist in demselben Schema wie die Verfahren in Frage).

Mit diesem können Sie das gleiche Muster in jedem aufrufenden Verfahren, nicht nur auf Tests verwenden. Das macht den eigentlichen Code ein wenig offensichtlicher/lesbarer und reduziert die Wartungsarbeiten, wenn sich die Tabellendefinition jemals ändern sollte.

+0

Aktualisiert, um eine zusätzliche Idee hinzuzufügen, die den Code ein wenig offensichtlicher macht. –

Verwandte Themen