פיתוח/בדיקות מנשק משתמש

From The Document Foundation Wiki
Jump to navigation Jump to search
This page is a translated version of the page Development/UITests and the translation is 100% complete.
Other languages:
English • ‎עברית

זה התיעוד הראשוני לתשתית בדיקות מנשק משתמש עם התמקדות מיוחדת בצד של ה־Python.

מבנה

בדיקות מנשק המשתמש מורכבות משני חלקים, חלק ב־C++‎ שעוטף את מנשק המשתמש של LibreOffice בספריה שבוחנת את המערכת פנימה ותשתית Python עם קוד בדיקה ממשי. החיבור בין שני החלקים נעשה דרך מנשק UNO פשוט שטרם הוקלד.

ספריית הבחינה פנימה ב־C++‎

ספריית הבחינה הפנימית ב־C++‎ מורכבת מ־UNO API שמשמש לתקשורת עם החלק של ה־Python של התשתית והחלקים העוטפים למגוון פריטי מנשק משתמש. למנשק UNO יש מגוון מצומצם של שיטות ורוב התקשורת מתרחשת דרך משתני מחרוזות.

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

תשתית Python

כתיבת בדיקות

המצגת של שיסקו פאולי מ־FOSDEM 2021, אבטחת איכות של LibreOffice - איך לכתוב את הבדיקה הראשונה שלך, עוברת על תהליך יצירת בדיקות.

החלק של ה־Makefile

קובץ makefile פשוט לבדיקות מנשק משתמש נראה כמו ה־makefile לדוגמה. החלק החשוב הוא להשתמש במחלקה UITest של gbuild ולאפשר ל־„gb_UITest_add_module” להצביע לתיקיות עם קובצי הבדיקות.

בדרך כלל לא צריך לעשות שום דבר מעבר לזה והרוב מטופל במסגרת מחלקת ה־UITest של gbuild.

$(eval $(call gb_UITest_UITest,range_name))

$(eval $(call gb_UITest_add_modules,range_name,$(SRCDIR)/sc/qa/uitest,\
    test_dir1/ \
    test_dir2/ \
))

המשתנה range_name (שם טווח) הוא שם יעד הבדיקה. ‎$(SRCDIR/sc/qa/uitest היא תיקיית הבסיס והמשתנים בחלק הזה מציגים את התיקיות בהן יתבצע החיפוש אחר הבדיקות.

ניתן להריץ את הבדיקה עם קובץ registrymodifications.xcu מסוים כדי לתמוך בהרצה עם הגדרות תצורה מסוימות. לכל בדיקה יש פרופיל משתמש משלה תחת workdir/UITest/test_name/user/‎. עם מקטע הקוד הבא כ־Makefile ניתן להעתיק קובץ לתיקייה הזאת.

$(eval $(call gb_UITest_use_configuration,range_name,$(SRCDIR)/sc/qa/uitest/range_name/registrymodifications.xcu))

פעולה זו תעתיק את הקובץ sc/qa/uitest/range_name/registrymodifications.xcu לפרופיל המשתמש והבדיקה תרוץ עם ההגדרות האלו.

כתיבת הקוד ב־Python

תשתית

פקודות שזמינות מול רכיבי מנשק משתמש

כללי

טיפול במצב רכיבי מנשק משתמש

השיטה לקבלת מצב פריט מנשק המשתמש מסופקת על ידי כלל רכיבי מנשק המשתמש. השיטה מחזירה את המצב כרצף של PropertyValue.

ui_element.getState()

תשתית בדיקת מנשק המשתמש מספקת שיטה להמרת הרצף שמוחזק של PropertyValue למילון (dict) ב־Python.

from uitest.uihelper.common import get_state_as_dict

get_state_as_dict(ui_element)

שליחת קלט מקלדת לרכיב

from uitest.uihelper.common import type_text

xWriterDoc = self.xUITest.getTopFocusWindow()
xWriterEdit = xWriterDoc.getChild("writer_edit")
type_text(xWriterEdit, "Test")

בחירת טקסט

from uitest.uihelper.common import select_text

xEdit = xAddNameDlg.getChild("edit")
select_text(xEdit, from_pos="2", to="12")

הגדרת תקריב

xWriterEdit = xWriterDoc.getChild("writer_edit")
xWriterEdit.executeAction("SET", mkPropertyValues({"ZOOM": "200"}))

קפיצה אל עמוד

xWriterEdit = xWriterDoc.getChild("writer_edit")
xWriterEdit.executeAction("GOTO", mkPropertyValues({"PAGE": "1"}))

פעולות בקרה

בקרה קוד הנחה
כפתור
xControl.executeAction("CLICK", tuple())

---

תיבת טקסט
from uitest.uihelper.common import type_pos

type_text(xControl, "Text")
self.assertEqual(get_state_as_dict(xTitleText)["Text"], "Text")
תיבת סימון
xControl.executeAction("CLICK", tuple())
self.assertEqual(get_state_as_dict(xControl)["Selected"], "true")
וידג׳ט מפת תווים
from libreoffice.uno.propertyvalue import mkPropertyValues

xControl.executeAction("SELECT", mkPropertyValues({"COLUMN": "2", "ROW": "2"}))

---

רשימת עץ
# פריסת/קיפול העץ
xTreelist = xExDBDlg.getChild("availablelb")         
xTreeEntry = xTreelist.getChild('0')
xTreeEntry.executeAction("EXPAND", tuple())  #Available Databases
xTreeEntry.executeAction("COLLAPSE", tuple()) #Click on the Bibliography

xTreeEntry2 = xTreeEntry.getChild('0')
xTreeEntry2.executeAction("SELECT", tuple())

---

תיבת בחירה
from uitest.uihelper.common import select_pos

select_pos(xCombobox, "1")
self.assertEqual(get_state_as_dict(xNumbering)["SelectEntryText"], "List 1")
לשוניות
from uitest.uihelper.common import select_pos

xTabs = xDialog.getChild("tabcontrol")
select_pos(xTabs, "0")
self.assertEqual(get_state_as_dict(xTabs)["CurrPagePos"], "0")
ListBox (תיבת רשימה - לפי מיקום)
from uitest.uihelper.common import select_pos

select_pos(xListBox, "1")
self.assertEqual(get_state_as_dict(xListBox)["SelectEntryText"], "List 1")
ListBox (תיבת רשימה - לפי שם)
from uitest.uihelper.common import select_pos

categoryLB = xCellsDlg.getChild("categorylb")
        props = {"TEXT": "Time"}

actionProps = mkPropertyValues(props)
        categoryLB.executeAction("SELECT", actionProps)
self.assertEqual(get_state_as_dict(categoryLB)["SelectEntryText"], "Time")
פקד לשונית
from uitest.uihelper.common import select_pmacOSTabs = xFunctionDlg.getChild("tabs")
        select_pos(xTabs, "1")

---

חלונית לשונית (לפי מיקום)
from uitest.uihelper.common import select_pmacOSTabs = xFunctionDlg.getChild("tabs")
        select_pos(xTabs, "1")

---

חלונית לשונית (לפי שם)
        props = {"NAME": "Borders"}
        propsUNO = mkPropertyValues(props)
        xCellsDlg.executeAction("SELECT", propsUNO)

---

שדה נגלל
xDecimalPlaces.executeAction("UP", tuple())
xDecimalPlaces.executeAction("DOWN", tuple())
self.assertEqual(get_state_as_dict(xDecimalPlaces)["Text"], "Title text")
כפתור בחירה
xSuperscript.executeAction("CLICK", tuple())
self.assertEqual(get_state_as_dict(xSuperscript)["Checked"], "true")

פעולות מילות מפתח

דוגמה:

from libreoffice.uno.propertyvalue import mkPropertyValues

ui_object.executeAction("TYPE", mkPropertyValues({"KEYCODE":"CTRL+A"}))

קודים של מקשים:

  • ESC
  • TAB
  • DOWN
  • UP
  • LEFT
  • RIGHT
  • DELETE
  • INSERT
  • BACKSPACE
  • RETURN
  • HOME
  • END
  • PAGEUP
  • PAGEDOWN
  • CTRL
  • ALT
  • SHIFT

איך להרחיב את ספריית הבחינה הפנימית

רכיבי מנשק משתמש שמרחיבים את vcl::Window

רכיבי מנשק משתמש אחרים

כלים לכתיבת בדיקות

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

  1. יש להשתמש בפקודות האלו ב־‎.bashrc או ב־‎.cshrc:
    export PYTHONPATH=/"Path of LibreOffice repo"/instdir/program/
    export URE_BOOTSTRAP=file:///"Path of LibreOffice repo"/instdir/program/fundamentalrc
    
  2. להפעיל את LibreOffice עם
    LO_COLLECT_UIINFO="test.log" SAL_USE_VCLPLUGIN=gen instdir/program/soffice
    
  3. לדמות מה מעניין אותך לעשות עם העכבר
  4. לסגור את LibreOffice
  5. לפתוח את הקובץ שמתקבל תחת instdir/uitest/test.log
  6. להיכנס לתיקיית מתעד מנשק המשתמש עם הפקודה הבאה:
    cd uitest/ui_logger_dsl/
    
  7. לוודא של־python יש את ספריית textX מותקנת
  8. להשתמש בפקודה הבאה
    python dsl_core.py <נתיב_לקובץ_תיעוד> <נתיב_לקובץ_python_חדש>
    
    את <נתיב_לקובץ_תיעוד> יש להחליף במשהו כמו SourceDirectory/core/instdir/uitest/test.log ואילו <נתיב_לקובץ_python_חדש> יכול להיות המיקום לבחירתך בו עדיף לך לצפות בקוד שנוצר.

ניתן לעקוב אחר כל השלבים האלו בסרטון ה־YouTube הבא:

הרצת הבדיקה

לפני דחיפת (push) הבדיקה ל־master כדאי לבדוק שהבדיקה עובדת. הדרך הפשוטה היא להפעיל את כל בדיקות מנשק המשתמש במודול uitest דרך make uitest.uicheck. עם זאת, עדיף לראות את מנשק המשתמש בזמן הפעלת הבדיקה והבדיקות רצות ללא תצוגה כבררת מחדל. אפשר לעשות זאת על ידי הרצת הרצף הבא בתיקיית הליבה:

(cd sc && make -srj1 UITest_sort UITEST_TEST_NAME="sorting.CalcSorting.test_Sortingbuttons_detect_columnheaders" SAL_USE_VCLPLUGIN=gen)

אפשר גם להשתמש בסקריפט shell להתחלת בדיקה.

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

export PYTHONPATH=/home/user/libreoffice/instdir/program/
export PYTHONPATH=$PYTHONPATH:/home/user/libreoffice/unotest/source/python/
export URE_BOOTSTRAP=file:///home/user/libreoffice/instdir/program/fundamentalrc
export TestUserDir=file:///tmp
export TDOC=/home/user/libreoffice/sw/qa/uitest/data
export SAL_USE_VCLPLUGIN=gen

rm -rf /tmp/libreoffice/4

SRCDIR="${SRCDIR:-$(pwd)}"
python3 "$SRCDIR"/uitest/test_main.py --debug --soffice=path:"$SRCDIR"/instdir/program/soffice --userdir=file:///tmp/libreoffice/4 --file="$SRCDIR"/sc/qa/uitest/calc_tests/sorting.py

במקרה שהבדיקה קוראת ל־‚get_url_for_data_file’ (קבלת כתובת עבור קובץ נתונים) כדי לפתוח קובץ, יש לשנות את המשתנה TDOC בהתאם כך שיצביע לתיקייה בה נמצא הקובץ. בעת הפעלת הבדיקה עם מנשק המשתמש הגלוי ניתן לראות שהבדיקה מהירה מדי ואי אפשר לראות מה קורה. פתרון מהיר ומלוכלך לכך הוא להוסיף את הפונקציה time.sleep ב־Python שעוצרת את הפעולה לזמן קצר. המקומות האחרים הם uitest.debug.sleep. השיטה הזאת לא חלה אלמלא הבדיקה הופעלה במצב ניפוי שגיאות (debug) על ידי העברת המשתנה ‎--debug לבדיקה.

כשעליך להריץ בדיקה אחת בקובץ סקריפט בדיקות, יש להפעיל את הפקודה הבאה:

UITEST_TEST_NAME="FILENAME.CLASS_NAME.TEST_NAME" ./execute.sh

למשל

UITEST_TEST_NAME="sorting.CalcSorting.test_Sortingbuttons_detect_columnheaders" ./execute.sh


פריטי מנשק משתמש שאינם נתמכים

  • תמיכה ב־Base
  • מסדר השקופיות ב־Impress
  • לחיצה כפולה בטפסים. לפרטים: https://bugs.documentfoundation.org/show_bug.cgi?id=133641
  • אשפי קבצים
  • Impress - ממזער המצגות
  • תיעוד ( LO_COLLECT_UIINFO) תחת Windows
  • לחיצה כפולה
  • תיעוד תרשימים
  • סרגל המידע התחתון ב־Calc
  • תמיכה טובה יותר בקיצורי דרך (tdf124931)

רשימה של בדיקות מנשק משתמש ב־master

ניתן לעיין ברשימת בדיקות מנשק המשתמש שכבר הוטמעו.

איתור תקלות

מילת המפתח needUITest בבאגזילה קיימת כדי לעקוב אחר כל התקלות שדורשות בדיקה אוטומטית עם UITest:

מידע נוסף