JavaRush /בלוג Java /Random-HE /מה זה TDD ובדיקת יחידות [תרגום]
Dr-John Zoidberg
רָמָה
Марс

מה זה TDD ובדיקת יחידות [תרגום]

פורסם בקבוצה
מאמר זה הוא עיבוד של פרק מתוך הספר The Complete Software Career Guide. מחברו, ג'ון סונמז, כותב אותו ומפרסם כמה פרקים באתר האינטרנט שלו.
מה זה TDD ובדיקת יחידות [תרגום] - 1

מילון מונחים קצר למתחילים

בדיקת יחידות או בדיקת יחידות היא תהליך בתכנות המאפשר לך לבדוק מודולים בודדים של קוד המקור של תוכנית לתקינות. הרעיון הוא לכתוב מבחנים לכל פונקציה או שיטה לא טריוויאלית. בדיקת רגרסיה היא שם כללי לכל סוגי בדיקות התוכנה שמטרתן לזהות שגיאות באזורים שכבר נבדקו בקוד המקור. שגיאות כאלה - כאשר לאחר ביצוע שינויים בתוכנית, משהו שאמור להמשיך לעבוד מפסיק לעבוד - נקראות שגיאות רגרסיה. תוצאה אדומה, נכשל - כישלון בבדיקה. ההבדל בין התוצאה הצפויה לתוצאה בפועל. תוצאה ירוקה, עובר - תוצאת בדיקה חיובית. התוצאה בפועל אינה שונה ממה שהתקבלה. ***
מה זה TDD ובדיקת יחידות [תרגום] - 2
יש לי מערכת יחסים מאוד מעורבת עם פיתוח מבחן (TDD) ובדיקות יחידות, עובר מאהבה לשנאה וחוזר חלילה. הייתי מעריץ מושבע ובו בזמן ספקן חשדן לגבי השימוש ב"שיטות מומלצות" זה ואחרות. הסיבה לגישה שלי מבוססת על העובדה שנוצרה בעיה רצינית בתהליכי פיתוח תוכנה: מפתחים, ולפעמים מנהלים, משתמשים בכלים ומתודולוגיות מסוימות רק בגלל שהם שייכים ל"שיטות עבודה מומלצות". הסיבה האמיתית לשימוש בהם נותרה לא ברורה. יום אחד התחלתי לעבוד על פרויקט מסוים, ותוך כדי כך הודיעו לי שנשנה קוד המכוסה במספר עצום של בדיקות יחידה. בלי בדיחה, היו בערך 3000 כאלה. זה בדרך כלל סימן טוב, איתות שהמפתחים משתמשים במתודולוגיות מתקדמות. הקוד בגישה זו הוא לרוב בנוי, והוא מבוסס על ארכיטקטורה מחושבת היטב. במילה אחת, נוכחותם של מבחנים שימחה אותי, ולו רק בגלל שמשמעותה הייתה להקל על עבודתי כמנטור של מתכנתים. מכיוון שכבר היו לנו בדיקות יחידה, כל מה שהייתי צריך לעשות זה לחבר את צוות הפיתוח כדי לתמוך בהם ולהתחיל לכתוב קוד משלנו. פתחתי את ה-IDE (סביבת פיתוח משולבת) וטענתי את הפרויקט.
מה זה TDD ובדיקת יחידות [תרגום] - 3
זה היה פרויקט גדול! מצאתי תיקייה שכותרתה "בדיקות יחידה". "נהדר," חשבתי. - בואו נשיק אותו ונראה מה קורה. זה לקח רק כמה דקות, ולהפתעתי, כל הבדיקות עברו, הכל היה ירוק ( "ירוק" היא תוצאה חיובית של הבדיקה. מסמן שהקוד עובד כמצופה. אדום מציין "כשל" או כישלון, ואז יש מקרה שהקוד לא עובד כהלכה - הערת המתרגם ). כולם עברו את המבחן. באותו רגע התעורר בי הספקן. איך זה, שלושת אלפים בדיקות יחידות, ולקחו את כולם בבת אחת - ונתנו תוצאה חיובית? במהלך התרגול הארוך שלי, לא יכולתי לזכור תקופה שבה התחלתי לעבוד על פרויקט ללא מבחן יחידה שלילי אחד בקוד. מה לעשות? בדוק ידנית! ChY בחר מבחן אקראי אחד, לא הכי חושפני, אבל היה ברור מיד מה הוא בודק. אבל תוך כדי עבודה על זה, שמתי לב למשהו אבסורדי: הבדיקה לא כללה השוואות עם התוצאה הצפויה (טוען)! כלומר, במציאות שום דבר לא נבדק בכלל ! היו שלבים מסוימים בבדיקה, הם בוצעו, אבל בתום הבדיקה, שבו הוא צריך להשוות את התוצאות בפועל והצפוי, לא הייתה בדיקה. ה"מבחן" לא בדק דבר. פתחתי עוד מבחן. אפילו טוב יותר: אופרטור ההשוואה עם התוצאה זכה להערה. בצורה מבריקה! זוהי דרך מצוינת לעבור מבחן, פשוט ציין את הקוד שגורם לו להיכשל. בדקתי עוד בדיקה, ואז עוד... אף אחד מהם לא בדק כלום. שלושת אלפים מבחנים, וכולם חסרי תועלת לחלוטין. יש הבדל עצום בין כתיבת מבחני יחידות לבין הבנת בדיקת יחידות ופיתוח מונחה מבחן (TDD).

מהי בדיקת יחידה?

מה זה TDD ובדיקת יחידות [תרגום] - 4
הרעיון הבסיסי של בדיקת יחידות הוא לכתוב מבחנים הבודקים את "יחידת הקוד" הקטנה ביותר. מבחני יחידות נכתבים בדרך כלל באותה שפת תכנות כמו קוד המקור של האפליקציה. הם נוצרים ישירות כדי לבדוק את הקוד הזה. כלומר, בדיקות יחידה הן קוד שבודק את נכונות קוד אחר. אני משתמש במילה "מבחן" באופן חופשי למדי בהקשר, כי מבחני יחידה במובן מסוים אינם מבחנים. הם לא חווים כלום. מה שאני מתכוון הוא שכאשר אתה מפעיל בדיקת יחידה אתה בדרך כלל לא מגלה שקוד מסוים לא עובד. אתה מגלה את זה בזמן כתיבת המבחן, כי אתה תשנה את הקוד עד שהמבחן יהפוך לירוק. כן, הקוד עשוי להשתנות מאוחר יותר ואז הבדיקה שלך עשויה להיכשל. אז במובן הזה, מבחן יחידה הוא מבחן רגרסיה. בדיקת יחידה היא לא כמו בדיקה רגילה שבה יש לך כמה שלבים שאתה הולך לבצע ואתה רואה אם ​​התוכנה עובדת כמו שצריך או לא. בתהליך כתיבת מבחן יחידה מגלים האם הקוד עושה את מה שהוא אמור לעשות או לא, ותשנה את הקוד עד שהמבחן יעבור.
מה זה TDD ובדיקת יחידות [תרגום] - 5
למה לא לכתוב מבחן יחידה ולבדוק אם הוא עובר? אם אתה חושב על זה כך, אז בדיקות יחידה הופכות לסוג של דרישות מוחלטות עבור מודולי קוד מסוימים ברמה נמוכה מאוד. אתה יכול לחשוב על מבחן יחידה כמפרט מוחלט . בדיקת יחידה קובעת שבתנאים אלה, עם קבוצת הקלט הספציפית הזו, יש פלט שאתה צריך לקבל מיחידת הקוד הזו. בדיקת יחידה אמיתית מזהה את יחידת הקוד הקוהרנטית הקטנה ביותר, שברוב שפות התכנות - לפחות אלה מונחה עצמים - היא מחלקה.

מה נקרא לפעמים בדיקת יחידה?

מה זה TDD ובדיקת יחידות [תרגום] - 6
לעתים קרובות מבלבלים בין בדיקת יחידות לבין בדיקות אינטגרציה. כמה "מבחני יחידה" בודקים יותר ממחלקה אחת או בודקים יחידות קוד גדולות. הרבה מפתחים טוענים שהם כותבים מבחני יחידה כשלמעשה הם כותבים מבחני whitebox ברמה נמוכה. אל תתווכח עם החבר'ה האלה. רק דעו שהם למעשה כותבים מבחני אינטגרציה, ומבחני יחידות אמיתיים בודקים את יחידת הקוד הקטנה ביותר במנותק מחלקים אחרים. דבר נוסף שנקרא לרוב בדיקת יחידה הוא בדיקות יחידה ללא בדיקה מול ערך צפוי. במילים אחרות, בדיקות יחידה שלמעשה לא בודקות כלום. כל בדיקה, מאוחדת או לא, חייבת לכלול סוג של אימות - אנחנו קוראים לזה בדיקת התוצאה בפועל מול התוצאה הצפויה. הפיוס הזה הוא שקובע אם המבחן עובר או נכשל. מבחן שתמיד עובר הוא חסר תועלת. מבחן שתמיד נכשל הוא חסר תועלת.

הערך של בדיקת יחידות

למה אני חובב בדיקות יחידות? מדוע מזיק לקרוא לבדיקה כללית, הכוללת בדיקה לא של הבלוק הקטן ביותר המבודד מקוד אחר, אלא פיסת קוד גדולה יותר, "בדיקת יחידות"? מה הבעיה אם חלק מהבדיקות שלי לא משווים את התוצאות שהתקבלו והצפויות? לפחות הם מבצעים את הקוד. אני אנסה להסביר.
מה זה TDD ובדיקת יחידות [תרגום] - 7
ישנן שתי סיבות עיקריות לביצוע בדיקות יחידה. הראשון הוא לשפר את עיצוב הקוד. זוכרים איך אמרתי שבדיקת יחידות היא לא באמת בדיקה? כאשר אתה כותב מבחני יחידה נאותים, אתה מכריח את עצמך לבודד את יחידת הקוד הקטנה ביותר. ניסיונות אלו יובילו אותך לגלות בעיות במבנה הקוד עצמו. ייתכן שיהיה לך קשה מאוד לבודד את מחלקת הבדיקה ולא לכלול את התלות שלה, וזה עלול לגרום לך להבין שהקוד שלך צמוד מדי. אתה עשוי לגלות שפונקציונליות הליבה שאתה מנסה לבדוק משתרעת על פני מספר מודולים, מה שגורם לך להאמין שהקוד שלך אינו קוהרנטי מספיק. כשאתה יושב לכתוב מבחן יחידה, אתה עלול לגלות פתאום (ותאמין לי, זה קורה!) שאין לך מושג מה הקוד אמור לעשות. בהתאם, לא תוכל לכתוב עבורו מבחן יחידה. וכמובן, אתה עלול למצוא באג אמיתי ביישום הקוד, שכן בדיקת היחידה מאלצת אותך לחשוב מחוץ לקופסה ולבדוק סטים שונים של קלט שאולי לא שקלת.
מה זה TDD ובדיקת יחידות [תרגום] - 8
אם אתה מקפיד על הכלל של "בדוק את יחידת הקוד הקטנה ביותר במנותק מהאחרות" בעת יצירת בדיקות יחידות, אתה חייב למצוא כל מיני בעיות עם הקוד הזה והעיצוב של המודולים האלה. במחזור החיים של פיתוח תוכנה, בדיקת יחידות היא יותר פעילות הערכה מאשר פעילות בדיקה. המטרה העיקרית השנייה של בדיקת יחידות היא ליצור מערך אוטומטי של מבחני רגרסיה שיכולים לשמש כמפרט ברמה נמוכה של התנהגות תוכנה. מה זה אומר? כשאתה לישה את הבצק, אתה לא שובר אותו. מנקודת מבט זו, מבחני יחידה הם מבחנים, ליתר דיוק מבחני רגרסיה. עם זאת, המטרה של בדיקת יחידות היא לא פשוט לבנות מבחני רגרסיה. בפועל, בדיקות יחידה לעיתים רחוקות תופסות רגרסיות, מכיוון ששינוי ביחידת הקוד שאתה בודק מכיל כמעט תמיד שינויים בבדיקת היחידה עצמה. בדיקת רגרסיה יעילה הרבה יותר ברמה גבוהה יותר, כאשר הקוד נבדק כ"קופסה שחורה", מכיוון שברמה זו ניתן לשנות את המבנה הפנימי של הקוד, בעוד שההתנהגות החיצונית צפויה להישאר זהה. מבחני יחידה בתורם בודקים את המבנה הפנימי כך שכאשר מבנה זה משתנה, מבחני היחידה לא נכשלים. הם הופכים לבלתי שמישים ועכשיו צריך לשנות אותם, לזרוק אותם או לשכתב אותם. כעת אתה יודע יותר על המטרה האמיתית של בדיקת יחידות מאשר מפתחי תוכנה ותיקים רבים.

מהו פיתוח מבחן (TDD)?

מה זה TDD ובדיקת יחידות [תרגום] - 9
בתהליך פיתוח התוכנה, מפרט טוב שווה זהב. גישת ה-TDD היא שלפני שאתה כותב קוד כלשהו, ​​אתה תחילה כותב מבחן שישמש כמפרט, כלומר, מגדיר מה הקוד צריך לעשות. זוהי תפיסת פיתוח תוכנה חזקה ביותר, אך לעתים קרובות נעשה בה שימוש לרעה. בדרך כלל, פיתוח מונחה מבחן פירושו שימוש בבדיקות יחידה כדי להנחות את יצירת קוד האפליקציה. אבל למעשה, גישה זו יכולה להיות מיושמת בכל רמה. עם זאת, במאמר זה נניח שאנו משתמשים בבדיקת יחידות עבור היישום שלנו. גישת ה-TDD הופכת הכל על ראשו, ובמקום לכתוב קודם קוד ואז לכתוב בדיקות יחידות כדי לבדוק את הקוד הזה, אתה כותב תחילה מבחן יחידה ואז כותב קוד כדי להפוך את המבחן לירוק. בדרך זו, בדיקת יחידות "דוחפת" את פיתוח הקוד. תהליך זה חוזר על עצמו שוב ושוב. אתה כותב מבחן נוסף שמגדיר יותר פונקציונליות של מה שהקוד צריך לעשות. לאחר מכן אתה כותב ומשנה את הקוד כדי להבטיח שהבדיקה תסתיים בהצלחה. ברגע שיש לך תוצאה ירוקה, אתה מתחיל לשחזר את הקוד, כלומר לשחזר או לנקות אותו כדי להפוך אותו לתמציתי יותר. שרשרת תהליכים זו נקראת לעתים קרובות "Red-Green-Refactoring" מכיוון שקודם מבחן היחידה נכשל (אדום), לאחר מכן הקוד נכתב כדי להתאים אותו לבדיקה, מוודא שהוא מצליח (ירוק), ולבסוף הקוד עובר אופטימיזציה ( ארגון מחדש). .

מה המטרה של TDD?

מה זה TDD ובדיקת יחידות [תרגום] - 10
פיתוח מונחה בדיקה (TDD), כמו בדיקת יחידות, יכול לשמש בצורה שגויה. קל מאוד לקרוא למה שאתה עושה "TDD" ואפילו לעקוב אחר התרגול מבלי להבין למה אתה עושה את זה ככה. הערך הגדול ביותר של TDD הוא שבדיקות מבוצעות כדי לייצר מפרטי איכות. TDD הוא בעצם התרגול של כתיבת מפרטים מדויקים שניתן לבדוק אוטומטית לפני כתיבת קידוד. בדיקות הן המפרט הטוב ביותר כי הם לא משקרים. הם לא יגידו לך אחרי שבועיים של ייסורים עם הקוד "לא לזה התכוונתי בכלל". מבחנים, כאשר הם כתובים בצורה נכונה, עוברים או נכשלים. בדיקות מצביעות בבירור מה צריך לקרות בנסיבות מסוימות. לפיכך, המטרה של TDD היא לתת לנו הבנה מלאה של מה שעלינו ליישם לפני שנתחיל ליישם אותו. אם אתה מתחיל עם TDD ולא מצליח להבין מה המבחן אמור לבדוק, אז אתה צריך לשאול שאלות נוספות. תפקיד חשוב נוסף של TDD הוא שימור ואופטימיזציה של קוד. תחזוקת הקוד היא יקרה. לעתים קרובות אני מתבדח שהמתכנת הכי טוב הוא זה שכותב את הקוד הכי תמציתי שפותר בעיה כלשהי. או אפילו זה שמוכיח שאין צורך לפתור בעיה זו, ובכך מסיר לחלוטין את הקוד, שכן מתכנת זה הוא שמצא את הדרך הנכונה לצמצם את מספר השגיאות ולהוזיל את עלות אחזקת האפליקציה. על ידי שימוש ב-TDD, אתה יכול להיות בטוח לחלוטין שאתה לא כותב שום קוד מיותר, מכיוון שאתה כותב קוד רק כדי לעבור מבחנים. יש עקרון פיתוח תוכנה שנקרא YAGNI (לא תזדקק לזה). TDD מונע את YAGNI.

זרימת עבודה טיפוסית לפיתוח מונע מבחן (TDD).

מה זה TDD ובדיקת יחידות [תרגום] - 11
קשה להבין את המשמעות של TDD מנקודת מבט אקדמית גרידא. אז בואו נסתכל על דוגמה למפגש TDD. דמיינו לעצמכם מתיישבים ליד השולחן שלכם ומשרטטים במהירות את מה שאתם חושבים שיהיה עיצוב ברמה גבוהה עבור תכונה המאפשרת למשתמש להיכנס לאפליקציה ולשנות את הסיסמה שלו אם ישכח אותה. אתה מחליט שתתחיל ביישום הראשון של פונקציית הכניסה, יצירת מחלקה שתטפל בכל ההיגיון של תהליך הכניסה. אתה פותח את העורך המועדף עליך ויוצר בדיקת יחידה בשם "כניסה ריקה מונעת מהמשתמש להיכנס." אתה כותב קוד בדיקת יחידה שיוצר תחילה מופע של מחלקת ה-Login (שעוד לא יצרת). לאחר מכן אתה כותב קוד כדי לקרוא למתודה במחלקה Login שמעבירה שם משתמש וסיסמה ריקים. לבסוף, אתה כותב צ'ק מול התוצאה הצפויה, ובודק שהמשתמש עם התחברות ריקה בעצם לא מחובר. אתה מנסה להריץ מבחן, אבל הוא אפילו לא מתחבר כי אין לך מחלקה להתחבר. אתה מתקן את המצב הזה ויוצר מחלקת Login יחד עם שיטה באותה מחלקה לכניסה ושיטה אחרת כדי לבדוק את מצב המשתמש כדי לראות אם הוא מחובר. עד כה לא יישמת את הפונקציונליות של המחלקה הזו ואת השיטה שאנו צריכים. אתה מפעיל את הבדיקה בשלב זה. עכשיו זה מתחבר, אבל מיד נכשל.
מה זה TDD ובדיקת יחידות [תרגום] - 12
כעת אתה חוזר לקוד ומיישם את הפונקציונליות כדי לעבור את המבחן. במקרה שלנו, זה אומר שאנחנו צריכים לקבל את התוצאה: "המשתמש לא מחובר." אתה מריץ את הבדיקה שוב ועכשיו היא עוברת. נעבור למבחן הבא. עכשיו בואו נדמיין שאתם צריכים לכתוב מבחן בשם "המשתמש מחובר אם הוא הזין שם משתמש וסיסמה חוקיים". אתה כותב מבחן יחידה שמציג את מחלקת ה-Login ומנסה להיכנס עם שם משתמש וסיסמה. במבחן יחידה כותבים הצהרה שמחלקת Login צריכה לענות בחיוב לשאלה האם המשתמש מחובר. אתה מפעיל את המבחן החדש הזה וכמובן שהוא נכשל מכיוון שמחלקת ה-Login שלך תמיד מחזירה שהמשתמש לא מחובר. אתה חוזר לשיעור ההתחברות שלך ומיישם קוד כלשהו כדי לוודא שהמשתמש מחובר. במקרה זה, תצטרך להבין כיצד לבודד את המודול הזה. לעת עתה, הדרך הקלה ביותר לעשות זאת היא לקוד קשיח של שם המשתמש והסיסמה שהשתמשת בהם בבדיקה, ואם הם תואמים, החזר את התוצאה "המשתמש מחובר". אתה מבצע את השינוי הזה, מפעיל את שני המבחנים, ושניהם עוברים. נעבור לשלב האחרון: אתה מסתכל על הקוד שנוצר, ומחפש דרך לארגן מחדש ולפשט אותו. אז אלגוריתם TDD הוא:
  1. יצר מבחן.
  2. כתבנו קוד למבחן הזה.
  3. שיחזר את הקוד.

מסקנות

מה זה TDD ובדיקת יחידות [תרגום] - 13
זה כל מה שרציתי לספר לכם על בדיקת יחידות ו-TDD בשלב זה. למעשה, ישנם קשיים רבים הקשורים בניסיון לבודד מודולי קוד, מכיוון שהקוד יכול להיות מאוד מורכב ומבלבל. מעט מאוד כיתות קיימות בבידוד מוחלט. במקום זאת, יש להם תלות, ולתלות האלה יש תלות, וכן הלאה. כדי להתמודד עם מצבים כאלה, ותיק ה-TDD משתמש בלעג, שעוזר לבודד מחלקות בודדות על ידי החלפת אובייקטים במודולים תלויים. מאמר זה הוא רק סקירה כללית והקדמה מעט פשוטה לבדיקת יחידות ו-TDD, לא נפרט על מודולי דמה וטכניקות TDD אחרות. הרעיון הוא לתת לך את המושגים והעקרונות הבסיסיים של TDD ובדיקות יחידות שיש לך בתקווה עכשיו. מקורי - https://simpleprogrammer.com/2017/01/30/tdd-unit-testing/
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION