إتقان Tox للاختبار متعدد البيئات. يغطي هذا الدليل الشامل تكوين tox.ini، وتكامل CI/CD، والاستراتيجيات المتقدمة لضمان عمل كود Python الخاص بك بشكل لا تشوبه شائبة عبر إصدارات Python المختلفة والتبعيات وأنظمة التشغيل.
أتمتة اختبار Tox: نظرة متعمقة في الاختبار متعدد البيئات للفرق العالمية
في مشهد البرمجيات العالمي اليوم، عبارة "إنه يعمل على جهازي" هي أكثر من مجرد عبارة مبتذلة للمطورين؛ إنها خطر تجاري كبير. ينتشر المستخدمون والعملاء والمتعاونون معك في جميع أنحاء العالم، ويستخدمون مجموعة متنوعة من أنظمة التشغيل وإصدارات Python ومكدسات التبعيات. كيف يمكنك التأكد من أن التعليمات البرمجية الخاصة بك ليست وظيفية فحسب، بل قوية بشكل موثوق للجميع، في كل مكان؟
تكمن الإجابة في الاختبار المنهجي الآلي متعدد البيئات. هذا هو المكان الذي تصبح فيه Tox، وهي أداة أتمتة مدفوعة بسطر الأوامر، جزءًا لا غنى عنه من مجموعة أدوات مطور Python الحديثة. فهو يوحد الاختبار، مما يسمح لك بتحديد وتنفيذ الاختبارات عبر مصفوفة من التكوينات بأمر واحد.
سيأخذك هذا الدليل الشامل من أساسيات Tox إلى الاستراتيجيات المتقدمة للاختبار متعدد البيئات. سنستكشف كيفية إنشاء خط أنابيب اختبار مرن يضمن أن برنامجك متوافق ومستقر وجاهز لجمهور عالمي.
ما هو الاختبار متعدد البيئات ولماذا هو بالغ الأهمية؟
الاختبار متعدد البيئات هو ممارسة تشغيل مجموعة الاختبار الخاصة بك مقابل تكوينات متعددة ومتميزة. تختلف هذه التكوينات، أو "البيئات"، عادةً حسب:
- إصدارات مترجم Python: هل يعمل الكود الخاص بك على Python 3.8 كما هو الحال على Python 3.11؟ ماذا عن Python 3.12 القادم؟
- إصدارات التبعية: قد يعتمد تطبيقك على مكتبات مثل Django أو Pandas أو Requests. هل سينهار إذا كان لدى المستخدم إصدار أقدم أو أحدث قليلاً من هذه الحزم؟
- أنظمة التشغيل: هل يتعامل الكود الخاص بك مع مسارات الملفات واستدعاءات النظام بشكل صحيح على Windows و macOS و Linux؟
- البنيات: مع ظهور المعالجات المستندة إلى ARM (مثل Apple Silicon)، أصبح الاختبار على معماريات وحدة المعالجة المركزية المختلفة (x86_64، arm64) ذا أهمية متزايدة.
الحالة التجارية لاستراتيجية متعددة البيئات
إن استثمار الوقت في إعداد هذا النوع من الاختبارات ليس مجرد تمرين أكاديمي؛ لها آثار تجارية مباشرة:
- يقلل تكاليف الدعم: من خلال اكتشاف مشكلات التوافق مبكرًا، فإنك تمنع تدفقًا من تذاكر الدعم من المستخدمين الذين لم تكن تتوقع بيئاتهم.
- يزيد ثقة المستخدم: يُنظر إلى البرامج التي تعمل بشكل موثوق عبر إعدادات مختلفة على أنها ذات جودة أعلى. وهذا أمر بالغ الأهمية بالنسبة للمكتبات مفتوحة المصدر والمنتجات التجارية على حد سواء.
- يتيح ترقيات أكثر سلاسة: عند إصدار إصدار Python جديد، يمكنك ببساطة إضافته إلى مصفوفة الاختبار الخاصة بك. إذا نجحت الاختبارات، فأنت تعلم أنك مستعد لدعمها. إذا فشلوا، فلديك قائمة واضحة وقابلة للتنفيذ بما يجب إصلاحه.
- يدعم الفرق العالمية: فهو يضمن أن المطور في بلد ما باستخدام أحدث الأدوات يمكنه التعاون بفعالية مع فريق في منطقة أخرى قد يكون على مكدس مؤسسي موحد وأقدم قليلاً.
تقديم Tox: مركز التحكم في الأتمتة الخاص بك
تم تصميم Tox لحل هذه المشكلة بأناقة. في جوهره، يقوم Tox بأتمتة إنشاء بيئات افتراضية معزولة لـ Python، وتثبيت مشروعك وتبعياته فيها، ثم تشغيل الأوامر المحددة (مثل الاختبارات أو أدوات التدقيق أو إنشاء الوثائق).
يتم التحكم في كل هذا بواسطة ملف تكوين بسيط واحد: tox.ini
.
البدء: التثبيت والتكوين الأساسي
التثبيت بسيط باستخدام pip:
pip install tox
بعد ذلك، قم بإنشاء ملف tox.ini
في جذر مشروعك. لنبدأ بتكوين بسيط للاختبار مقابل إصدارات Python متعددة.
مثال: tox.ini
أساسي
[tox] min_version = 3.7 isolated_build = true envlist = py38, py39, py310, py311 [testenv] description = Run the main test suite deps = pytest commands = pytest
دعنا نحلل هذا:
- قسم
[tox]
: هذا مخصص لإعدادات Tox العالمية. min_version
: يحدد الحد الأدنى لإصدار Tox المطلوب لتشغيل هذا التكوين.isolated_build
: أفضل ممارسة حديثة (PEP 517) تضمن إنشاء الحزمة الخاصة بك في بيئة معزولة قبل تثبيتها للاختبار.envlist
: هذا هو جوهر الاختبار متعدد البيئات. إنها قائمة مفصولة بفواصل للبيئات التي تريد أن يديرها Tox. هنا، قمنا بتحديد أربع بيئات: واحدة لكل إصدار Python من 3.8 إلى 3.11.- قسم
[testenv]
: هذا قالب لجميع البيئات المحددة فيenvlist
. description
: رسالة مفيدة تشرح ما تفعله البيئة.deps
: قائمة بالتبعيات اللازمة لتشغيل أوامرك. هنا، نحتاج فقط إلىpytest
.commands
: الأوامر المراد تنفيذها داخل البيئة الافتراضية. هنا، نقوم ببساطة بتشغيل أداة تشغيل اختبارpytest
.
لتشغيل هذا، انتقل إلى دليل جذر مشروعك في جهازك الطرفي واكتب ببساطة:
tox
سيقوم Tox الآن بتنفيذ الخطوات التالية لكل بيئة في `envlist` (py38، py39، إلخ):
- ابحث عن مترجم Python المقابل على نظامك (على سبيل المثال، `python3.8`، `python3.9`).
- قم بإنشاء بيئة افتراضية جديدة ومعزولة داخل دليل
.tox/
. - قم بتثبيت مشروعك والتبعيات المدرجة ضمن `deps`.
- قم بتنفيذ الأوامر المدرجة ضمن `commands`.
إذا فشلت أي خطوة في أي بيئة، فسوف يقوم Tox بالإبلاغ عن الخطأ والخروج برمز حالة غير صفري، مما يجعله مثاليًا لأنظمة التكامل المستمر (CI).
نظرة متعمقة: صياغة tox.ini
قوي
الإعداد الأساسي قوي، ولكن السحر الحقيقي لـ Tox يكمن في خيارات التكوين المرنة لإنشاء مصفوفات اختبار معقدة.
البيئات المولدة: المفتاح للاختبار التوافقي
تخيل أن لديك مكتبة تحتاج إلى دعم إصدارات Django 3.2 و 4.2، التي تعمل على Python 3.9 و 3.10. سيكون تحديد جميع المجموعات الأربعة يدويًا أمرًا متكررًا:
الطريقة المتكررة: envlist = py39-django32, py39-django42, py310-django32, py310-django42
يوفر Tox بناء جملة توليديًا أنظف بكثير باستخدام الأقواس المتعرجة {}
:
الطريقة التوليدية: envlist = {py39,py310}-django{32,42}
يتوسع هذا السطر الواحد إلى نفس البيئات الأربعة. هذا النهج قابل للتطوير بدرجة كبيرة. إضافة إصدار Python جديد أو إصدار Django هو مجرد مسألة إضافة عنصر واحد إلى القائمة المعنية.
إعدادات مشروطة بالعامل: تخصيص كل بيئة
الآن بعد أن حددنا مصفوفتنا، كيف نخبر Tox بتثبيت الإصدار الصحيح من Django في كل بيئة؟ يتم ذلك باستخدام الإعدادات المشروطة بالعامل.
[tox] envlist = {py39,py310}-django{32,42} [testenv] deps = pytest django32: Django>=3.2,<3.3 django42: Django>=4.2,<4.3 commands = pytest
هنا، السطر `django32: Django>=3.2,<3.3` يخبر Tox: "قم بتضمين هذه التبعية فقط إذا كان اسم البيئة يحتوي على العامل `django32`." وبالمثل بالنسبة إلى `django42`. يتمتع Tox بالذكاء الكافي لتحليل أسماء البيئات (على سبيل المثال، `py310-django42`) وتطبيق الإعدادات الصحيحة.
هذه ميزة قوية بشكل لا يصدق لإدارة:
- التبعيات غير المتوافقة مع إصدارات Python الأقدم / الأحدث.
- الاختبار مقابل إصدارات مختلفة من مكتبة أساسية (Pandas، NumPy، SQLAlchemy، إلخ).
- التثبيت المشروط للتبعيات الخاصة بالنظام الأساسي.
هيكلة مشروعك بما يتجاوز الاختبارات الأساسية
يتضمن خط أنابيب الجودة القوي أكثر من مجرد تشغيل الاختبارات. تحتاج أيضًا إلى تشغيل أدوات التدقيق والمدققين الكتابيين وإنشاء الوثائق. من أفضل الممارسات تحديد بيئات Tox منفصلة لهذه المهام.
[tox] envlist = py{39,310}, lint, typing, docs [testenv] deps = pytest commands = pytest [testenv:lint] description = Run linters (ruff, black) basepython = python3.10 deps = ruff black commands = ruff check . black --check . [testenv:typing] description = Run static type checker (mypy) basepython = python3.10 deps = mypy # also include other dependencies with type hints django djangorestframework commands = mypy my_project/ [testenv:docs] description = Build the documentation basepython = python3.10 deps = sphinx commands = sphinx-build -b html docs/source docs/build/html
إليك الجديد:
- أقسام البيئة المحددة: لقد أضفنا `[testenv:lint]` و `[testenv:typing]` و `[testenv:docs]`. تحدد هذه الأقسام إعدادات خاصة بتلك البيئات المسماة، متجاوزة الإعدادات الافتراضية في `[testenv]`.
basepython
: بالنسبة للبيئات غير الاختبارية مثل `lint` أو `docs`، غالبًا ما لا نحتاج إلى تشغيلها على كل إصدار Python. يسمح لنا `basepython` بتثبيتها على مترجم معين، مما يجعلها أسرع وأكثر تحديدًا.- فصل نظيف: يحافظ هذا الهيكل على نظافة تبعياتك. تقوم بيئة `lint` فقط بتثبيت أدوات التدقيق؛ لا تحتاج بيئات الاختبار الرئيسية الخاصة بك إليها.
يمكنك الآن تشغيل جميع البيئات باستخدام `tox`، أو مجموعة معينة باستخدام `tox -e py310,lint`، أو بيئة واحدة فقط باستخدام `tox -e docs`.
دمج Tox مع CI/CD للأتمتة على نطاق عالمي
يعد تشغيل Tox محليًا أمرًا رائعًا، ولكن يتم إطلاق العنان لقوته الحقيقية عند دمجه في خط أنابيب التكامل المستمر / النشر المستمر (CI/CD). يضمن هذا التحقق من صحة كل تغيير في التعليمات البرمجية تلقائيًا مقابل مصفوفة الاختبار الكاملة الخاصة بك.
تعتبر خدمات مثل GitHub Actions و GitLab CI و Jenkins مثالية لهذا الغرض. يمكنهم تشغيل مهامك على أنظمة تشغيل مختلفة، مما يسمح لك بإنشاء مصفوفة توافق شاملة لنظام التشغيل.
مثال: سير عمل GitHub Actions
لنقم بإنشاء سير عمل GitHub Actions يقوم بتشغيل بيئات Tox الخاصة بنا بالتوازي عبر Linux و macOS و Windows.
قم بإنشاء ملف في .github/workflows/ci.yml
:
name: CI on: [push, pull_request] jobs: test: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] python-version: ['3.8', '3.9', '3.10', '3.11'] steps: - name: Check out repository uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Install Tox run: pip install tox tox-gh-actions - name: Run Tox run: tox -e py
دعنا نحلل سير العمل هذا:
strategy.matrix
: هذا هو جوهر مصفوفة CI الخاصة بنا. ستقوم GitHub Actions بإنشاء مهمة منفصلة لكل مجموعة من `os` و `python-version`. بالنسبة لهذا التكوين، هذا هو 3 أنظمة تشغيل × 4 إصدارات Python = 12 مهمة متوازية.actions/setup-python@v4
: يقوم هذا الإجراء القياسي بإعداد إصدار Python المحدد المطلوب لكل مهمة.tox-gh-actions
: هذه إضافة Tox مفيدة تقوم تلقائيًا بتعيين إصدار Python في بيئة CI إلى بيئة Tox الصحيحة. على سبيل المثال، في المهمة التي تعمل على Python 3.9، سيتم تلقائيًا حل `tox -e py` لتشغيل `tox -e py39`. يوفر لك هذا كتابة منطق معقد في برنامج CI النصي الخاص بك.
الآن، في كل مرة يتم فيها دفع التعليمات البرمجية، يتم تنفيذ مصفوفة الاختبار بأكملها تلقائيًا عبر جميع أنظمة التشغيل الرئيسية الثلاثة. يمكنك الحصول على تعليقات فورية حول ما إذا كان التغيير قد أدخل عدم توافق، مما يسمح لك بالبناء بثقة لقاعدة مستخدمين عالمية.
الاستراتيجيات المتقدمة وأفضل الممارسات
تمرير الوسيطات إلى الأوامر باستخدام {posargs}
في بعض الأحيان تحتاج إلى تمرير وسيطات إضافية إلى أداة تشغيل الاختبار الخاصة بك. على سبيل المثال، قد ترغب في تشغيل ملف اختبار معين: pytest tests/test_api.py
. يدعم Tox هذا من خلال استبدال {posargs}
.
قم بتعديل `tox.ini` الخاص بك:
[testenv] deps = pytest commands = pytest {posargs}
الآن، يمكنك تشغيل Tox مثل هذا:
tox -e py310 -- -k "test_login" -v
يفصل --
الوسيطات المخصصة لـ Tox عن الوسيطات المخصصة للأمر. سيتم استبدال كل شيء بعد ذلك بـ `{posargs}`. سيقوم Tox بتنفيذ: pytest -k "test_login" -v
داخل بيئة `py310`.
التحكم في متغيرات البيئة
قد يتصرف تطبيقك بشكل مختلف بناءً على متغيرات البيئة (على سبيل المثال، `DJANGO_SETTINGS_MODULE`). يسمح لك توجيه `setenv` بالتحكم في هذه المتغيرات داخل بيئات Tox الخاصة بك.
[testenv] setenv = PYTHONPATH = . MYAPP_MODE = testing [testenv:docs] setenv = SPHINX_BUILD = 1
نصائح لتشغيل Tox بشكل أسرع
مع نمو مصفوفتك، يمكن أن تصبح عمليات تشغيل Tox بطيئة. فيما يلي بعض النصائح لتسريعها:
- الوضع المتوازي: قم بتشغيل `tox -p auto` لجعل Tox يقوم بتشغيل بيئاتك بالتوازي، باستخدام عدد نوى وحدة المعالجة المركزية المتاحة. هذا فعال للغاية على الأجهزة الحديثة.
- إعادة إنشاء البيئات بشكل انتقائي: بشكل افتراضي، يعيد Tox استخدام البيئات. إذا تغيرت تبعياتك في `tox.ini` أو `requirements.txt`، فأنت بحاجة إلى إخبار Tox بإعادة بناء البيئة من البداية. استخدم علامة إعادة الإنشاء: `tox -r -e py310`.
- تخزين CI مؤقتًا: في خط أنابيب CI/CD الخاص بك، قم بتخزين دليل
.tox/
مؤقتًا. يمكن أن يؤدي هذا إلى تسريع عمليات التشغيل اللاحقة بشكل كبير حيث لن تحتاج التبعيات إلى التنزيل والتثبيت في كل مرة، إلا إذا تغيرت.
حالات الاستخدام العالمية في الممارسة العملية
دعونا نفكر في كيفية تطبيق ذلك على أنواع مختلفة من المشاريع في سياق عالمي.
السيناريو 1: مكتبة تحليل بيانات مفتوحة المصدر
أنت تحتفظ بمكتبة شائعة مبنية على Pandas و NumPy. المستخدمون هم علماء بيانات ومحللون في جميع أنحاء العالم.
- التحدي: يجب عليك دعم إصدارات متعددة من Python و Pandas و NumPy والتأكد من أنها تعمل على خوادم Linux وأجهزة كمبيوتر macOS المحمولة وأجهزة كمبيوتر Windows المكتبية.
- حل Tox:
envlist = {py39,py310,py311}-{pandas1,pandas2}-{numpy18,numpy19}
سيستخدم `tox.ini` الخاص بك إعدادات مشروطة بالعامل لتثبيت إصدارات المكتبة الصحيحة لكل بيئة. سيختبر سير عمل GitHub Actions هذه المصفوفة عبر جميع أنظمة التشغيل الرئيسية الثلاثة. يضمن هذا أن يحصل المستخدم في البرازيل الذي يستخدم إصدار Pandas أقدم على نفس التجربة الموثوقة التي يحصل عليها المستخدم في اليابان على أحدث مجموعة.
السيناريو 2: تطبيق SaaS للمؤسسات مع مكتبة عميل
تقدم شركتك، التي يقع مقرها الرئيسي في أوروبا، منتج SaaS. عملاؤك هم شركات عالمية كبيرة، يستخدم الكثير منهم إصدارات دعم طويلة الأجل (LTS) الأقدم من أنظمة التشغيل و Python لتحقيق الاستقرار.
- التحدي: يستخدم فريق التطوير الخاص بك أدوات حديثة، ولكن يجب أن تكون مكتبة العميل الخاصة بك متوافقة مع الإصدارات السابقة مع بيئات المؤسسات القديمة.
- حل Tox:
envlist = py38, py39, py310, py311
يضمن `tox.ini` الخاص بك اجتياز جميع الاختبارات مقابل Python 3.8، والذي قد يكون المعيار في عميل رئيسي في أمريكا الشمالية. من خلال تشغيل هذا تلقائيًا في CI، فإنك تمنع المطورين من إدخال الميزات التي تستخدم بناء الجملة أو المكتبات المتاحة فقط في إصدارات Python الأحدث عن طريق الخطأ، مما يمنع حالات فشل النشر المكلفة.
الخلاصة: الشحن بثقة عالمية
لم يعد الاختبار متعدد البيئات ترفًا؛ إنها ممارسة أساسية لتطوير برامج احترافية عالية الجودة. من خلال تبني الأتمتة باستخدام Tox، فإنك تحول هذا التحدي المعقد إلى عملية مبسطة وقابلة للتكرار.
من خلال تحديد البيئات المدعومة في ملف tox.ini
واحد ودمجها مع خط أنابيب CI/CD، فإنك تنشئ بوابة جودة قوية. تضمن هذه البوابة أن يكون تطبيقك قويًا ومتوافقًا وجاهزًا لجمهور عالمي متنوع. يمكنك التوقف عن القلق بشأن مشكلة "إنه يعمل على جهازي" الرهيبة والبدء في شحن التعليمات البرمجية بثقة أنها ستعمل على جهاز الجميع، بغض النظر عن مكان وجودهم في العالم.