Unit Test - Part 1 (SSDT)
היי חברים,
לאחרונה התבקשתי לבחון "כיצד ניתן לכתוב קוד ללא שגיאות".
רגע, לפני שאתם מתעצבנים, נכון, כולנו עושים שגיאות, המטרה היא לראות כיצד אנו כמפתחים יכולים לכתוב קוד שנבדק ברמה מספיק טובה על ידינו לפני שנוכל לשלוח אותו במסלול ה Continuous integration לטובת מעבר לסביבת הבדיקות.
ניתן משמעות חדשה ל- "קוד ללא שגיאות" – כתיבת קוד שעונה על הצרכים ומחזיר תוצאות נכונות לאחר זמן מינימאלי.
או ביצוע שינויים בקוד בצורה שלא תשפיע או תגרום לשגיאות מטעם האפליקציה.
מטרתי לכתוב סדרת מאמרים, בכל מאמר אכתוב על כלי Unit Test שונים שמצויים ברשת שנחשפתי אליהם במהלך עבודתי ויכולים לתרום לנו למהלך עבודה תקין יותר ועם פחות שגיאות.
את כל הבדיקות יבוצעו מול מסד נתונים AdventureWorks כאשר הוספתי לו ניפוח שניתן להוריד מכאן
במסד הנתונים יצרתי פרוצדורת חיפוש –
CREATE PROCEDURE [dbo].[usp_FindBigTransactionBig]
@ProductID INT,
@ProductName NVARCHAR(80),
@ProductNumber NVARCHAR(56),
@ProductColor NVARCHAR(15),
@SellDate DATETIME,
@TransactionDateStart DATETIME,
@TransactionDateEnd DATETIME
AS
BEGIN
SET NOCOUNT ON;
DECLARE @SELECT NVARCHAR(MAX) = N'SELECT BP.ProductID ,
BP.Name ,
BP.ProductNumber ,
BP.MakeFlag ,
BP.FinishedGoodsFlag ,
BP.Color ,
BP.SafetyStockLevel ,
BP.ReorderPoint ,
BP.StandardCost ,
BP.ListPrice ,
BP.Size ,
BP.SizeUnitMeasureCode ,
BP.WeightUnitMeasureCode ,
BP.Weight ,
BP.DaysToManufacture ,
BP.ProductLine ,
BP.Class ,
BP.Style ,
BP.ProductSubcategoryID ,
BP.ProductModelID ,
BP.SellStartDate ,
BP.SellEndDate ,
BP.DiscontinuedDate ,
BTH.TransactionID ,
BTH.ProductID ,
BTH.TransactionDate ,
BTH.Quantity ,
BTH.ActualCost
';
DECLARE @FROM NVARCHAR(MAX) = N'FROM [dbo].[bigProduct] BP
INNER JOIN [dbo].[bigTransactionHistory] BTH ON BP.[ProductID] = BTH.[ProductID]
';
DECLARE @WHERE NVARCHAR(MAX) = N'
WHERE (1=1)
';
IF @ProductID IS NOT NULL SET @WHERE += '
AND BP.ProductID = @ProductID
';
IF @ProductName IS NOT NULL SET @WHERE += '
AND BP.Name LIKE ''%'' + @ProductName + ''%''
';
IF @ProductColor IS NOT NULL SET @WHERE += '
AND BP.Color = @ProductColor
';
IF @ProductNumber IS NOT NULL SET @WHERE += '
AND BP.ProductNumber LIKE ''%'' + @ProductNumber + ''%''
';
IF @SellDate IS NOT NULL SET @WHERE += '
AND @SellDate BETWEEN BP.SellStartDate AND BP.SellEndDate
';
IF @TransactionDateStart IS NOT NULL AND @TransactionDateEnd IS NOT NULL SET @WHERE += '
AND BTH.TransactionDate BETWEEN @TransactionDateStart AND @TransactionDateEnd
';
IF @TransactionDateStart IS NOT NULL AND @TransactionDateEnd IS NULL SET @WHERE += '
AND @TransactionDateStart =< BTH.TransactionDate
';
IF @TransactionDateStart IS NULL AND @TransactionDateEnd IS NOT NULL SET @WHERE += '
AND @TransactionDateEnd => BTH.TransactionDate
';
SET @SELECT += @FROM + @WHERE;
EXEC SP_EXECUTESQL @SELECT ,N'@ProductID INT,
@ProductName NVARCHAR(80),
@ProductNumber NVARCHAR(56),
@ProductColor NVARCHAR(15),
@SellDate DATETIME,
@TransactionDateStart DATETIME,
@TransactionDateEnd DATETIME',@ProductID = @ProductID,@ProductName = @ProductName,@ProductNumber = @ProductNumber,@ProductColor = @ProductColor,
@SellDate = @SellDate,@TransactionDateStart = @TransactionDateStart,@TransactionDateEnd = @TransactionDateEnd;
END
הכלי הראשון שיש ברשותנו הוא Visual Studio + SSDT.
א. נפתח פרויקט חדש מסוג Unit Test
ב. נוסיף קובץ חדש מסוג SQL Server Unit Test –
ג. מיד לאחר הוספת הקובץ נתבקש להכניס את הConnection sting
במסך הזה ניתן לראות שקיימים לנו 2 חיבורים אפשריים למסד הנתונים.
החיבור הראשון נועד לטובת המשתמש שיריץ את הבדיקה.
החיבור הנוסף נועד לטובת אימות הבדיקה שנכתבה(לא חייב) – ניתן לתת חיבור חזק כמו Sa
אך לרוב אני לא מעוניין לבדוק הרשאות ואני אשתמש רק עם החיבור הראשון כאשר המשתמש מסוג SA.
ניתן לפתח 8 סוגי בדיקות
Data Checksum – תיפול כאשר חישוב checksum של כל הסט בתוצאה לא תואם לערך שהכנסנו.
Empty ResultSet – תיפול כאשר חזר סט נתונים ולא סט ריק.
Execution Time – תיפול כאשר לא תזרה תוצאה לאחר זמן שקבענו – ברירת מחדל 30 שניות.
Expected Schema – תיפול כאשר מבנה (סכמה) התוצאות לא תואם למבנה שקבענו.
Inconclusive – מופיע כברירת מחדל בעת הוספת בדיקה חדשה – יש למחוק כאשר אנו מוסיפים תנאי.
Not Empty ResultSet – תיפול כאשר חוזר סט ריק.
Row Count – תיפול כאשר כמות השורות שחזרה לא תואמת למספר שקבענו.
Scalar Value – תיפול כאשר הערך שחזר לא תואם לערך שקבענו.
Execution Time
DECLARE @ProductID int =1001
הגדרתי חיפוש ע"פ מספר פריט כאשר הבדיקה תיפול כאשר עברו 30 שנויות.
דרך אחת להריץ את הבדיקות היא ע"י התפריט כך –
לאחר ההרצה ניתן לראות את התוצאות בחלונית – Test Explorer
כעת נוסיף בדיקה נוספת ע"מ להראות שכאשר עוברים את הסף הבדיקה נכשלת.
שיניתי את הפרמטרים כך –
DECLARE @ProductID int
DECLARE @ProductName nvarchar(80) = 'f'
Empty ResultSet
נוסיף עוד 2 בדיקות
פרמטרים לראשונה - EmptyResultSetNotFail -
DECLARE @ProductID int =1
כאשר לא אמורים לחזור ערכים והבדיקה אמורה לעבור בהצלחה
פרמטרים לשניה – EmptyResultSet -
DECLARE @ProductID int =1001
כאשר אמורה לחזור שורה אחת ובעצם להפיל את הבדיקה.
כך ניתן לבנות יחסית בקלות ומהירות בדיקות לפרוצדורות או תהליכים אצלנו במסד הנתונים.
לסיכום:
ניתן לראות שיש לנו כלי יחסית קל לקנפוג והכנת בדיקות יחסית פשוטות.
בעיה שנתקלתי במהלך תקופה שעבדתי עם פרויקט Unit Test הוא הקושי בתחזוקה כמות גדולה של בדיקות- מעל 300 Unit Test, היינו חייבים להשקיע שעות יקרות רק כדי לישר קו עם חלק משינויי הסכמה היומיים.
עוד קושי נוסף שנתקלתי בו, כאשר אנו מריצים פרוצדורה עם פרמטרים, לדוגמא פרוצדורה עם 18 פרמטרים הסיכוי לבדוק את כל הסוגים האפשריים ולמצוא את נקודות הכשל היא כמעט בלתי אפשרית עם הכלי הזה.
אולם לבדיקות קלות יחסית הוא מתמודד מצוין, ובכל זאת עדיף שיש משהו כזה מאשר כלום.
אשמח לשמוע עם איזה כלים אתם משתמשים?
האם אתם משתמשים עם הכלי בצורה אחרת?
Comments