اختبار الحمل ليس مطلوبًا على نطاق واسع ومنتشر مثل أنواع الاختبار الأخرى - لا توجد العديد من الأدوات التي تسمح لك بإجراء هذا الاختبار ، ولكن يمكن احتسابه بشكل بسيط ومريح على أصابع يد واحدة.
عندما يتعلق الأمر باختبار الأداء - أولاً وقبل كل شيء يفكر الجميع في JMeter - فهي بلا شك الأداة الأكثر شهرة مع أكبر عدد من المكونات الإضافية. لم يعجبني JMeter أبدًا بسبب واجهته غير الواضحة وعتبة الدخول العالية ، بمجرد أن يصبح من الضروري اختبار تطبيق غير مرحب به World.
والآن ، مستوحاة من نجاح الاختبار في مشروعين مختلفين ، قررت مشاركة المعلومات حول برنامج بسيط ومريح نسبيًا -
Locustبالنسبة لأولئك الذين هم كسالى جدا للذهاب تحت الخفض ، سجلت فيديو:
ما هذا
أداة مفتوحة المصدر تسمح لك بتحديد سيناريوهات الحمل برمز Python الذي يدعم الحمل الموزع ، وكما يدعي المؤلفون ، تم استخدامها لاختبار الإجهاد Battlelog لسلسلة ألعاب Battlefild (تأسر على الفور)
من الايجابيات:
- وثائق بسيطة بما في ذلك مثال النسخ واللصق. يمكنك البدء في الاختبار ، حتى مع عدم وجود مهارات برمجة تقريبًا.
- يستخدم "تحت الغطاء" مكتبة الطلبات (HTTP للأشخاص). يمكن استخدام وثائقه كلوحة غش ممتدة واختبارات الخصم
- دعم Python - أحب اللغة تمامًا
- تعطي الفقرة السابقة منصة مشتركة لإجراء الاختبارات
- خادم الويب Flask الخاص لعرض نتائج الاختبار
من السلبيات:
- لا التقاط وإعادة - كل الأيدي
- نتيجة الفقرة السابقة - تحتاج إلى دماغ. كما هو الحال مع Postman ، تحتاج إلى فهم كيفية عمل HTTP.
- الحد الأدنى من مهارات البرمجة المطلوبة
- نموذج التحميل الخطي - الذي يزعج المعجبين على الفور لتوليد مستخدمين غوسيين
عملية الاختبار
أي اختبار هو مهمة معقدة تتطلب التخطيط والتحضير ورصد التنفيذ وتحليل النتائج. أثناء اختبار الضغط ، إن أمكن ، من الممكن والضروري جمع كل البيانات الممكنة التي قد تؤثر على النتيجة:
- أجهزة الخادم (CPU و RAM و ROM)
- برنامج الخادم (نظام التشغيل وإصدار الخادم و JAVA و .NET وما إلى ذلك ، وقاعدة البيانات وكمية البيانات نفسها ، والخادم وسجلات تطبيق الاختبار)
- عرض النطاق الترددي للشبكة
- وجود خوادم بروكسي وموازنات تحميل وحماية DDOS
- تحميل بيانات الاختبار (عدد المستخدمين ومتوسط وقت الاستجابة وعدد الطلبات في الثانية)
يمكن تصنيف الأمثلة الموضحة أدناه على أنها اختبار الحمل الوظيفي للصندوق الأسود. حتى بدون معرفة أي شيء عن التطبيق قيد الاختبار ودون الوصول إلى السجلات ، يمكننا قياس أدائه.
قبل أن تبدأ
لاختبار اختبارات التحميل عمليًا ، قمت بنشر خادم ويب بسيط محليًا
https://github.com/typicode/json-server . سأقدم له كل الأمثلة التالية تقريبًا. لقد أخذت البيانات للخادم من مثال على الإنترنت تم نشره -
https://jsonplaceholder.typicode.com/لتشغيله ، مطلوب nodeJS.
المفسد الواضح : كما هو الحال مع اختبار الأمان - من الأفضل إجراء تجارب مع اختبار الإجهاد على القطط محليًا ، دون تحميل الخدمات عبر الإنترنت حتى لا يتم حظرك
للبدء ، مطلوب Python أيضًا - في جميع الأمثلة التي سأستخدم الإصدار 3.6 ، بالإضافة إلى الجراد نفسه (في وقت الكتابة ، الإصدار 0.9.0). يمكن تثبيته بالأمر
python -m pip install locustio
يمكن العثور على تفاصيل التثبيت في الوثائق الرسمية.
تحليل مثال
بعد ذلك نحتاج إلى ملف اختبار. أخذت مثالاً من الوثائق ، لأنها بسيطة جدًا ومباشرة:
from locust import HttpLocust, TaskSet def login(l): l.client.post("/login", {"username":"ellen_key", "password":"education"}) def logout(l): l.client.post("/logout", {"username":"ellen_key", "password":"education"}) def index(l): l.client.get("/") def profile(l): l.client.get("/profile") class UserBehavior(TaskSet): tasks = {index: 2, profile: 1} def on_start(self): login(self) def on_stop(self): logout(self) class WebsiteUser(HttpLocust): task_set = UserBehavior min_wait = 5000 max_wait = 9000
هذا كل شئ! هذا يكفي لبدء الاختبار! دعونا نلقي نظرة على مثال قبل أن نبدأ.
تخطي الواردات ، في البداية نرى وظيفتين متطابقتين تقريبًا لتسجيل الدخول وتسجيل الخروج ، تتكون من سطر واحد.
l.client - كائن جلسة HTTP الذي
سننشئ به تحميلًا . نستخدم طريقة POST ، والتي تكون مطابقة تقريبًا للطريقة الموجودة في مكتبة الطلبات. تقريبًا - لأننا في هذا المثال نمرر باعتبارها الوسيطة الأولى ليس عنوان URL كاملًا ، بل جزءًا منه فقط - خدمة معينة.
الحجة الثانية تمرر البيانات - ولا يسعني إلا أن ألاحظ أنه من السهل جدًا استخدام قواميس Python ، والتي يتم تحويلها تلقائيًا إلى json
يمكنك أيضًا ملاحظة أننا لا نعالج نتيجة الطلب بأي شكل من الأشكال - إذا كان ناجحًا ، فسيتم حفظ النتائج (على سبيل المثال ، ملفات تعريف الارتباط) في هذه الجلسة. في حالة حدوث خطأ ، سيتم تسجيله وإضافته إلى الإحصائيات حول الحمل.
إذا أردنا معرفة ما إذا كنا قد كتبنا الطلب بشكل صحيح ، فيمكننا دائمًا التحقق منه على النحو التالي:
import requests as r response=r.post(base_url+"/login",{"username":"ellen_key","password":"education"}) print(response.status_code)
أضفت فقط متغير
base_url ، الذي يجب أن يحتوي على العنوان الكامل للمورد الجاري اختباره.
الوظائف القليلة التالية هي الاستعلامات ، مما سيؤدي إلى إنشاء تحميل. مرة أخرى ، لسنا بحاجة إلى معالجة استجابة الخادم - سيتم نقل النتائج على الفور إلى الإحصائيات.
التالي هو فئة
UserBehavior (يمكن أن يكون اسم الفئة أي). كما يوحي الاسم ، فإنه سيصف سلوك مستخدم كروي في فراغ التطبيق قيد الاختبار. نمرر إلى خاصية
المهام قاموسًا للطرق التي سيتصل بها المستخدم وتكرار مكالماته. الآن ، على الرغم من أننا لا نعرف أي وظيفة وأي ترتيب سيتصل به كل مستخدم - يتم اختيارهم بشكل عشوائي ، فإننا نضمن أن يتم استدعاء وظيفة
الفهرس بمعدل مرتين أكثر من وظيفة
الملف الشخصي .
بالإضافة إلى السلوك ، يتيح لك TaskSet للفصل الأصلي تحديد 4 وظائف يمكن إجراؤها قبل الاختبارات وبعدها. سيكون ترتيب المكالمات على النحو التالي:
- الإعداد - يسمى مرة واحدة في بداية UserBehavior (TaskSet) - ليس في المثال
- on_start - يسمى مرة واحدة من قبل كل مستخدم جديد للتحميل عند بدء التشغيل
- المهام - تنفيذ المهام نفسها
- on_stop - يتم استدعاءه مرة واحدة من قبل كل مستخدم عند انتهاء الاختبار
- teardown - يُسمى مرة واحدة عند خروج TaskSet - كما أنه ليس في المثال
تجدر الإشارة هنا إلى أن هناك طريقتان للإعلان عن سلوك المستخدم: الأولى مذكورة بالفعل في المثال أعلاه - يتم الإعلان عن الوظائف مسبقًا. الطريقة الثانية هي التصريح عن الأساليب مباشرة داخل فئة
UserBehavior :
from locust import HttpLocust, TaskSet, task class UserBehavior(TaskSet): def on_start(self): self.client.post("/login", {"username":"ellen_key", "password":"education"}) def on_stop(self): self.client.post("/logout", {"username":"ellen_key", "password":"education"}) @task(2) def index(self): self.client.get("/") @task(1) def profile(self): self.client.get("/profile") class WebsiteUser(HttpLocust): task_set = UserBehavior min_wait = 5000 max_wait = 9000
في هذا المثال ، يتم تعيين وظائف المستخدم وتكرار مكالمته باستخدام تعليق
المهمة . من الناحية الوظيفية ، لم يتغير شيء.
الفصل الأخير من المثال هو
WebsiteUser (يمكن أن يكون اسم الصف
موجودًا ). في هذا الفصل ، نحدد نموذج سلوك المستخدم
UserBehavior *** + ، بالإضافة إلى الحد الأدنى والحد الأقصى لأوقات الانتظار بين المكالمات إلى المهام الفردية من قبل كل مستخدم. لتوضيح الأمر ، إليك كيفية تصوره:

الشروع في العمل
قم بتشغيل الخادم ، الذي سنختبر أداءه:
json-server --watch sample_server/db.json
نقوم أيضًا بتعديل ملف المثال بحيث يمكنه اختبار الخدمة وإزالة تسجيل الدخول وتسجيل الخروج وتعيين سلوك المستخدم:
- افتح الصفحة الرئيسية مرة واحدة في بداية العمل
- احصل على قائمة بجميع مشاركات x2
- اكتب تعليقًا على أول مشاركة x1
from locust import HttpLocust, TaskSet, task class UserBehavior(TaskSet): def on_start(self): self.client.get("/") @task(2) def posts(self): self.client.get("/posts") @task(1) def comment(self): data = { "postId": 1, "name": "my comment", "email": "test@user.habr", "body": "Author is cool. Some text. Hello world!" } self.client.post("/comments", data) class WebsiteUser(HttpLocust): task_set = UserBehavior min_wait = 1000 max_wait = 2000
للبدء في موجه الأوامر ، قم بتشغيل الأمر
locust -f my_locust_file.py --host=http://localhost:3000
حيث host هو عنوان المصدر المختبر. ويضاف إليه عناوين الخدمات المبينة في الاختبار.
إذا لم تكن هناك أخطاء في الاختبار ، فسيبدأ خادم التحميل وسيكون متاحًا على
http: // localhost: 8089 /
كما ترى ، تتم الإشارة إلى الخادم الذي سنختبره هنا - من خلال عنوان URL هذا سيتم إضافة عناوين الخدمات من ملف الاختبار.
أيضًا هنا يمكننا الإشارة إلى عدد المستخدمين للحمل ونموهم في الثانية.
على الزر ، نبدأ التحميل!

النتائج
بعد فترة معينة ، نوقف الاختبار ونلقي نظرة على النتائج الأولى:
- كما هو متوقع ، انتقل كل من المستخدمين العشرة الذين تم إنشاؤهم في البداية إلى الصفحة الرئيسية
- تم فتح قائمة المشاركات في المتوسط مرتين أكثر من كتابة تعليق
- يوجد متوسط ووقت استجابة متوسط لكل عملية ، عدد العمليات في الثانية هو بيانات مفيدة بالفعل ، على الرغم من أنه يأخذها الآن ويقارنها بالنتيجة المتوقعة من المتطلبات
في علامة التبويب الثانية ، يمكنك رؤية الرسوم البيانية للتحميل في الوقت الفعلي. إذا تعطل الخادم عند تحميل معين أو تغير سلوكه ، فسيظهر هذا على الفور على الرسم البياني.

في علامة التبويب الثالثة ، يمكنك رؤية الأخطاء - في حالتي ، هذا خطأ عميل. ولكن إذا عرض الخادم خطأ 4XX أو 5XX ، فسيتم كتابة نصه هنا
إذا حدث خطأ في رمز النص الخاص بك ، فسيقع في علامة التبويب استثناءات. حتى الآن لدي الخطأ الأكثر شيوعًا المتعلق باستخدام الأمر print () في الكود - هذه ليست أفضل طريقة لتسجيل الدخول :)
في علامة التبويب الأخيرة ، يمكنك تنزيل جميع نتائج الاختبار بتنسيق csv
هل هذه النتائج ذات صلة؟ دعونا نكتشف ذلك. في أغلب الأحيان ، تبدو متطلبات الأداء (إن وجدت مذكورة على الإطلاق) شيئًا كهذا: يجب أن يكون متوسط وقت تحميل الصفحة (استجابة الخادم) أقل من N ثانية مع وجود حمل من المستخدمين. عدم تحديد ما يجب على المستخدمين فعله. وأنا أحب الجراد لهذا - إنه يخلق نشاطًا لعدد معين من المستخدمين الذين يقومون بشكل عشوائي بالإجراءات المتوقعة التي يتوقعونها من المستخدمين.
إذا كنا بحاجة إلى تنفيذ معيار - لقياس سلوك النظام في الأحمال المختلفة ، فيمكننا إنشاء عدة فئات من السلوك وإجراء العديد من الاختبارات بأحمال مختلفة.
هذا يكفي لبداية. إذا أعجبك المقال ، أخطط للكتابة عنه:
- سيناريوهات الاختبار المعقدة التي يتم فيها استخدام نتائج خطوة واحدة في ما يلي
- معالجة استجابة الخادم ، مثل قد يكون من الخطأ حتى لو وصل HTTP 200 OK
- الصعوبات غير الواضحة التي يمكن مواجهتها وكيفية الالتفاف عليها
- اختبار دون استخدام واجهة المستخدم
- اختبار الحمل الموزع