יחידות בדיקה עם fpcUnit

הקדמה

ישנם מספר ספריות לבדיקה עבור שפת פסקל. הספרייה הכי וותיקה שאני מכיר נקראת DUnit, והיא שוחררה לראשונה ב1999, כמימוש jUnit עבור דלפי. ד"א jUnit למיטב ידיעתי היא מימוש ג'אווה של SUnit עבור שפת Smalltalk.
fpcUnit הוא סוג של מימוש מחודש עבור FPC ולזרוס. fpcUnit מגיע בשני טעמים:

  1. הצגה גרפית של בדיקות
  2. הצגה טקסטואלית (כולל ייצוא למספר פורמטרים) של בדיקות

הוא תומך במרבית התחביר של דלפי, אבל מציג גם תחביר חדש לגמרי. לפרוייקט עצמו יש פורק שמוסיף לו עוד תכונות, כדוגמת יכולת לאתחל מידע בהתחלת ריצת המערכת, ושחרור בסיומה לפני היציאה. כך למשל במסדי נתונים, ופעולות מאוד יקרות, ניתן ליעל את זמן הריצה והתגובתיות.

צורת עבודה

הרעיון:

הרעיון הכללי הוא ליצור "תוכנה" אחת שמריצה הרבה unit tests, שבפסקל, זה באמת יחידות :). היחידות נרשמות בחלק ה initialization של היחידה, באמצעות RegisterTest. אשר לוקח את המחלקה של הבדיקות ורץ על הפרוצדורות השונות לבדיקה.
המחלקה יורשת מ TTestCase, וכל פרוצדורות הבדיקה (הרי אנחנו רוצים לפרק את הבדיקות לחלקים הגיוניים), חייבת להיות בחלק ה published, בשביל שתוכל לרוץ.
ישנה מתודה אחת שבמידה וצריך לאתחל מידע, צריך להגדיר אותה (בחלק ה protected) בשם SetUp. במידה והגדרנו את SetUp מומלץ גם להגדיר מתודה בשם TearDown שעושה בדיוק הפוך.

אני ממליץ לבקש מלזרוס ליצור לנו את השלד עבור הבדיקות, אך לא חייבים אותו לשם כך, אבל מכאן והלאה, אני מניח שעשיתם זאת.

קוד

אצור יחידה רגילה, ואצור שם פונקציה בשם life_universe_and_everything שצריכה להחזיר את המספר 42, אבל עדיין לא אתן לה להחזיר כלום.

interface
...
function life_universe_and_everyting : byte;
...
implementation
...
function life_universe_and_everyting: byte;
begin

end;
...
end.

עכשיו בunit test אצור מתודה בשם TestLifeUniverseAndEverything.
אנחנו צריכים להתחיל לחשוב מה בעצם אנחנו רוצים להתחיל לבדוק כאן. המטרה היא שקוד הבדיקה יכשל, היות ואנחנו עובדים במתודולוגיה של test driven development.

...
  TBlogExampleTestUnit= class(TTestCase)
  published
    procedure TestLifeUniverseAndEverything;
  end;
...

דבר ראשון, אני רוצה לבדוק כי היא באמת מחזירה 42, הרי זו המשמעות של החיים, היקום והכל, לא ?

...
implementation
uses unitBlog;

resourcestring
errInvalidValue = 'The value %d is invalid, expected %d';

{ TBlogExampleTestUnit }

procedure TBlogExampleTestUnit.TestLifeUniverseAndEverything;
var Value, expected : Byte;
begin
  Value := life_universe_and_everyting;
  expected := 42;
  AssertEquals(Format(errInvalidValue, [Value, expected]), expected, Value);
end;
...

fpctest-failed

כמו שניתן לראות בתמונה, הבדיקה נכשלה.
אבל לא רק זה, אלא גם הצגתי טקסט מה לא בסדר.

עכשיו צריך לתקן את הבעיה. אחזור ליחידה שבה נמצאת הפונקציה, ואתן לה ערך:

function life_universe_and_everyting: byte;
begin
 Result := 42;
end;

הרצה נוספת של הבדיקה עכשיו, תגרום לה לעבור.
fpctest-passed
וככה ניתן לבדוק דברים נוספים הקשורים לפונקציה life_universe_and_everything.

במידה ונרצה לבדוק למשל שאנחנו מעלים חריגה כמו שצריך, זה דורש מעט קוד. ביחידה של הפונקציה, אצור גם פרוצדורה בשם raise_exception.
בהתחלה אגרום לבדיקה שלהם להכשל על ידי חוסר יצירת קוד:

procedure raise_exception;
begin

end;

ובדיקה:

procedure TBlogExampleTestUnit.TestRaiseException;
begin
  try
    raise_exception;
    Fail(errNoException);
  except
  on e: Exception do
    begin
      CheckEquals('EInOutError', e.ClassName);
    end;
  end;
end;

fpctest-failed2

עכשיו נגרום לבדיקה שלנו לעבור, על ידי יצירת קוד נכון:

procedure raise_exception;
begin
  raise EInOutError.create('Do not access any I/O');
end;

fpctest-passed2

סיכום

מערכת הבדיקות מאפשרת לנו לפתח קוד בצורה פשוטה יותר, וללכת צעד אחרי צעד במימוש שלנו, ולסייע לנו לבדוק בעיות.
בגרסת הטרמינל, הפלט בברירת המחדל הוא xml, וניתן גם להגיד לו לבצע פלט ל LaTeX או plain text. ובכך גם לשמור את הפלט ולנתח אותו בצורה אוטומטית (למשל עבור בנייה לילית).

את קוד המקור, ניתן להוריד מכאן.

כתיבת תגובה

הזינו את פרטיכם בטופס, או לחצו על אחד מהאייקונים כדי להשתמש בחשבון קיים:

הלוגו של WordPress.com

אתה מגיב באמצעות חשבון WordPress.com שלך. לצאת מהמערכת / לשנות )

תמונת Twitter

אתה מגיב באמצעות חשבון Twitter שלך. לצאת מהמערכת / לשנות )

תמונת Facebook

אתה מגיב באמצעות חשבון Facebook שלך. לצאת מהמערכת / לשנות )

תמונת גוגל פלוס

אתה מגיב באמצעות חשבון Google+ שלך. לצאת מהמערכת / לשנות )

מתחבר ל-%s