כתיבת בדיקות יחידה למודולי 1C-Bitrix

קוד מודולים של 1C-Bitrix לעתים קרובות מקושר היטב לליבה, מה שהופך אותו לשביר וקשה לשינוי. אנו מפתחים ומיישמים unit tests, מבודדים את הלוגיקה העסקית ויוצרים הגנה אמינה מפני רגרסיות. הצוות שלנו מספק פרויקטים סוהר — מבדיקת קוד ו-refactoring ועד להגדרת PHPUnit ו-mocks, תוך הבטחת פעילות יציבה ותמיכה מתמשכת.
השירותים שאנו מציעים
מציג 1 מתוך 1כל 1626 השירותים
כתיבת בדיקות יחידה למודולי 1C-Bitrix
בינוני
~1-2 שבועות

הכישורים שלנו:

שאלות נפוצות

מבוא

בפרויקט לוגיסטיקה אחד, מודול חישוב המשלוחים הפיק תעריפים שגויים לאחר כל עדכון עקב היעדר בדיקות יחידה. לאחר ריפקטורינג וכתיבת בדיקות, השגיאות נעלמו, וזמן יישום השינויים קוצץ בחצי. עלויות הרגרסיה ירדו ב-70%, ותקציב התמיכה במודול קוצץ בחצי. זהו תרחיש טיפוסי: קוד מודול ביטריקס (Bitrix) לעיתים קרובות צמוד לליבה, מה שמקשה על הבדיקה. הניסיון של הצוות שלנו בעשרות פרויקטים מאשר: ארכיטקטורה נכונה ובדיקות יחידה מקצרות את זמן פיתוח תכונות חדשות בחצי ומפחיתות באגים ב-70%. אנו נתקלים לעיתים קרובות בפרויקטים שבהם הלוגיקה העסקית אינה מבודדת, וכתיבת בדיקות דורשת ריפקטורינג מקדים. עם זאת, גם במקרים כאלה, בדיקות יחידה משתלמות בתוך החודשים הראשונים של התפעול.

מדוע בדיקות יחידה בביטריקס קשות יותר מאשר בפרויקטים אחרים

בעיות נפוצות שאנו רואים בהתחלה:

  • צמידות גבוהה לליבה. מחלקות יורשות מ-CBitrixComponent או קוראות ל-CIBlockElement ישירות. כל בדיקה דורשת אתחול של כל הסביבה.
  • היעדר ממשקים. מאגרי נתונים (Repositories) לרוב אינם מופרדים למחלקות נפרדות. במקום זאת, שאילתות SQL מפוזרות בין מתודות.
  • מצב גלובלי. ביטריקס משתמשת במשתנים גלובליים ($APPLICATION, $DB) ובסינגלטונים. זה שובר את בידוד הבדיקות.
  • אתחול איטי. טעינת הליבה דרך prolog_before.php אורכת 1–3 שניות, מה שהופך הרצת אלף בדיקות לאיטית באופן בלתי מתקבל על הדעת.

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

עקרונות של ארכיטקטורה ניתנת לבדיקה

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

// Бизнес-логика смешана с инфраструктурой — нельзя протестировать изолированно
public function calculateDiscount(int $userId): float
{
    $user = \CUser::GetByID($userId)->Fetch(); // статический вызов Битрикс
    $orders = \CSaleOrder::GetList([], ['USER_ID' => $userId])->Fetch();
    return $orders['count'] > 10 ? 0.15 : 0.05;
}

במקום זאת, הזריקו תלויות (dependencies):

// Логика отделена, зависимости инжектируются
class DiscountCalculator
{
    public function __construct(
        private UserRepositoryInterface $users,
        private OrderRepositoryInterface $orders,
    ) {}

    public function calculate(int $userId): float
    {
        $user = $this->users->findById($userId);
        $orderCount = $this->orders->countByUserId($userId);
        return $orderCount > 10 ? 0.15 : 0.05;
    }
}

מאגרי נתונים מיושמים דרך ה-API של ביטריקס בקוד הייצור ודרך מוקים (mocks) בבדיקות. הריפקטורינג הזה משתלם לאחר מחזור השינויים הראשון. מידע נוסף על הזרקת תלויות נמצא בתיעוד של ביטריקס.

תשתית בדיקות

הקמנו PHPUnit עם שני bootstraps: אחד לבדיקות יחידה טהורות (ללא קרנל, רק Composer autoload), והשני לבדיקות אינטגרציה הטוענות את ביטריקס.

דוגמה ל-bootstrap לבדיקות אינטגרציה:

// tests/bootstrap.php
define('NO_KEEP_STATISTIC', true);
define('NOT_CHECK_PERMISSIONS', true);
define('BX_WITH_ON_AFTER_EPILOG', false);
define('BX_NO_ACCELERATOR_RESET', true);
$_SERVER['DOCUMENT_ROOT'] = realpath(__DIR__ . '/../../../..');
require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php';
\Bitrix\Main\Loader::includeModule('your.module');

לבדיקות מבודדות, נעשה שימוש ב-bootstrap נפרד ללא // Бизнес-логика смешана с инфраструктурой — нельзя протестировать изолированно public function calculateDiscount(int $userId): float { $user = \CUser::GetByID($userId)->Fetch(); // статический вызов Битрикс $orders = \CSaleOrder::GetList([], ['USER_ID' => $userId])->Fetch(); return $orders['count'] > 10 ? 0.15 : 0.05; } . זה מאיץ את ההרצה פי 10–50.

דוגמאות לבדיקות יחידה

בדיקת לוגיקה עסקית (ללא קרנל):

class DiscountCalculatorTest extends TestCase
{
    private DiscountCalculator $calculator;

    protected function setUp(): void
    {
        $this->calculator = new DiscountCalculator(
            users: $this->createStub(UserRepositoryInterface::class),
            orders: $this->createConfiguredMock(
                OrderRepositoryInterface::class,
                ['countByUserId' => 5]
            ),
        );
    }

    public function testLessThan10OrdersGivesBasicDiscount(): void
    {
        $this->assertSame(0.05, $this->calculator->calculate(1));
    }

    public function testMoreThan10OrdersGivesPremiumDiscount(): void
    {
        $repo = $this->createConfiguredMock(
            OrderRepositoryInterface::class,
            ['countByUserId' => 15]
        );
        $calc = new DiscountCalculator($this->createStub(UserRepositoryInterface::class), $repo);
        $this->assertSame(0.15, $calc->calculate(1));
    }
}

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

מהו ה-ROI שבדיקות יחידה מספקות?

יישום בדיקות יחידה מקצר את זמן הניפוי באגים ב-70% ומפחית את עלויות התחזוקה בחצי עקב זיהוי מוקדם של רגרסיות. בממוצע, פעולה עסקית אחת (חישוב, ולידציה) דורשת 2 עד 6 שעות לכתיבת בדיקות. מחזור מלא למודול בינוני הוא 2–5 ימים. לוחות הזמנים תלויים בארכיטקטורה הקיימת ובצורך בריפקטורינג. אם אתם רוצים לשפר את יציבות הפרויקט, צרו קשר לצורך ביקורת יכולת בדיקה (testability audit).

השוואת גישות

קריטריון בדיקות יחידה מבודדות אינטגרציה עם הקרנל
מהירות הרצה 0.01–0.1 שניות 1–5 שניות
תלות במסד נתונים לא כן
דורש מוקים כן לא
מכסה לוגיקה עסקית כן כן
מכסה תשתית לא כן
קלות ניפוי באגים גבוהה בינונית

בדיקות מבודדות מהירות פי 50 — אנו בוחרים בהן לרוב התרחישים.

כיסוי ותיעדוף

אין צורך לכסות 100% מהקוד. סדר העדיפויות:

עדיפות מה לבדוק
גבוהה חישובי מחיר, הנחה, עלות משלוח
גבוהה לוגיקה עסקית של מצבים (state machine)
גבוהה מפענחי נתונים ומיפוי (ייבוא מ-1C, Excel)
בינונית וולידטורים של קלט
בינונית אלגוריתמים לייצור דוחות
נמוכה תבניות רכיבים, לוגיקת UI

כיסוי יעד ללוגיקה עסקית מרכזית הוא 80%+. עבור קוד תשתית (מאגרי נתונים, מתאמים), בדיקות אינטגרציה מספיקות. זה מאזן בין מהירות לאמינות.

מה כולל כתיבת בדיקות יחידה

  1. ביקורת קוד המודול ליכולת בדיקה, ריפקטורינג של נקודות הזרקת תלויות.
  2. הקמת PHPUnit עם bootstrap לסביבת ביטריקס.
  3. כתיבת בדיקות ללוגיקה עסקית: חישובים, state machines, מפענחים.
  4. הקמת דוח כיסוי באמצעות Xdebug.
  5. שילוב הרצת הבדיקות ב-CI (GitHub Actions / GitLab CI).
  6. תיעוד כיצד להריץ בדיקות ולהוסיף חדשות.

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

טעויות נפוצות בכתיבת בדיקות לביטריקס

  • ניסיון לטעון את הקרנל לכל בדיקה: השתמשו בשני bootstraps.
  • שימוש במסד נתונים אמיתי בבדיקות יחידה: בצעו mock למאגרי נתונים.
  • התעלמות מקאש תוצאות: נקו את הקאש בין בדיקות.
  • בדיקת מתודות מוגנות באמצעות reflection: חלצו לוגיקה למתודות ציבוריות.