الاختبارات و TDD

التطوير الموجه بالسلوك (BDD)

20 دقيقة الدرس 28 من 35

التطوير الموجه بالسلوك (BDD)

يسد التطوير الموجه بالسلوك (BDD) الفجوة بين أعضاء الفريق التقنيين وغير التقنيين باستخدام اللغة الطبيعية لوصف سلوك التطبيق. يركز BDD على سلوك التطبيق من منظور المستخدم.

فهم BDD

فوائد BDD:
  • تعاون أفضل بين المطورين، ضمان الجودة، وأصحاب المصلحة
  • توثيق حي لسلوك النظام
  • متطلبات ومعايير قبول أوضح
  • اختبارات مكتوبة بلغة الأعمال
  • التركيز على قيمة المستخدم

بناء جملة Gherkin

Gherkin هي اللغة المستخدمة لكتابة سيناريوهات BDD. تستخدم تنسيق Given-When-Then:

# features/user_authentication.feature Feature: User Authentication As a user I want to login to the system So that I can access my account Scenario: Successful login with valid credentials Given I am on the login page When I enter "user@example.com" as email And I enter "password123" as password And I click the "Login" button Then I should see "Welcome back" And I should be on the dashboard page Scenario: Failed login with invalid credentials Given I am on the login page When I enter "wrong@example.com" as email And I enter "wrongpass" as password And I click the "Login" button Then I should see "Invalid credentials" And I should remain on the login page Scenario Outline: Login validation Given I am on the login page When I enter "" as email And I enter "" as password And I click the "Login" button Then I should see "" Examples: | email | password | message | | valid@example.com | password123 | Welcome back | | invalid@test.com | wrong | Invalid credentials | | user@example.com | | Password is required | | | password123 | Email is required |

Behat لـ PHP

Behat هو إطار عمل BDD الأكثر شعبية لـ PHP:

// تثبيت Behat composer require --dev behat/behat vendor/bin/behat --init
// features/bootstrap/FeatureContext.php use Behat\Behat\Context\Context; use Behat\Behat\Tester\Exception\PendingException; use PHPUnit\Framework\Assert; class FeatureContext implements Context { private $response; private $email; private $password; /** * @Given I am on the login page */ public function iAmOnTheLoginPage() { $this->response = $this->get('/login'); Assert::assertEquals(200, $this->response->getStatusCode()); } /** * @When I enter :arg1 as email */ public function iEnterAsEmail($email) { $this->email = $email; } /** * @When I enter :arg1 as password */ public function iEnterAsPassword($password) { $this->password = $password; } /** * @When I click the :arg1 button */ public function iClickTheButton($button) { $this->response = $this->post('/login', [ 'email' => $this->email, 'password' => $this->password ]); } /** * @Then I should see :arg1 */ public function iShouldSee($text) { Assert::assertStringContainsString( $text, $this->response->getContent() ); } /** * @Then I should be on the dashboard page */ public function iShouldBeOnTheDashboardPage() { Assert::assertEquals('/dashboard', $this->response->headers->get('Location')); } }

تكامل Laravel و Behat

// تثبيت امتداد Laravel Behat composer require --dev laracasts/behat-laravel-extension // behat.yml default: extensions: Laracasts\Behat: env_path: .env.behat suites: default: contexts: - FeatureContext - Laracasts\Behat\Context\DatabaseTransactions - Laracasts\Behat\Context\Services\FilesystemManager

سيناريوهات BDD المعقدة

# features/shopping_cart.feature Feature: Shopping Cart Management As a customer I want to manage items in my cart So that I can purchase products Background: Given the following products exist: | name | price | stock | | Laptop | 999 | 10 | | Mouse | 25 | 50 | | Keyboard | 75 | 30 | And I am logged in as "customer@example.com" Scenario: Add product to cart Given I am on the product page for "Laptop" When I click "Add to Cart" Then I should see "Product added to cart" And my cart should contain 1 item And the cart total should be "$999.00" Scenario: Update product quantity in cart Given I have the following items in my cart: | product | quantity | | Laptop | 1 | | Mouse | 2 | When I am on the cart page And I change the quantity of "Mouse" to 5 And I click "Update Cart" Then the cart should contain: | product | quantity | subtotal | | Laptop | 1 | $999.00 | | Mouse | 5 | $125.00 | And the cart total should be "$1,124.00" Scenario: Remove product from cart Given I have "Laptop" in my cart When I am on the cart page And I click "Remove" for "Laptop" Then my cart should be empty And I should see "Your cart is empty"
أفضل ممارسات BDD:
  • كتابة السيناريوهات قبل التنفيذ (من الخارج إلى الداخل)
  • استخدام لغة الأعمال، وليس المصطلحات التقنية
  • التركيز على السلوك، وليس التنفيذ
  • إبقاء السيناريوهات مستقلة
  • استخدام Background للإعداد المشترك
  • إعادة استخدام تعريفات الخطوات عبر الميزات

العلامات لتنظيم الاختبارات

# استخدام العلامات لتنظيم وتصفية الاختبارات @smoke @critical Feature: User Registration @javascript @slow Scenario: Register with email verification # Steps here @wip Scenario: Social media registration # Steps here
# تشغيل اختبارات محددة بعلامات vendor/bin/behat --tags=smoke vendor/bin/behat --tags=~@slow # استبعاد الاختبارات البطيئة vendor/bin/behat --tags="@smoke&&@critical"
أخطاء BDD الشائعة:
  • كتابة سيناريوهات تقنية للغاية
  • اختبار التنفيذ بدلاً من السلوك
  • إنشاء سيناريوهات تابعة
  • الإفراط في استخدام Background (يجعل السيناريوهات غير واضحة)
  • عدم إشراك أصحاب المصلحة في كتابة السيناريوهات
تمرين:
  1. اكتب ملف ميزة لتدفق تسجيل المستخدم
  2. قم بتضمين سيناريوهات لـ: التسجيل الناجح، البريد الإلكتروني المكرر، البيانات غير الصالحة
  3. نفذ تعريفات الخطوات باستخدام Behat
  4. أضف مخطط سيناريو للتحقق من صحة كلمة المرور
  5. استخدم العلامات لوضع علامة على السيناريوهات الحرجة

BDD مقابل TDD

الاختلافات الرئيسية:
  • TDD: يركز على اختبارات الوحدة، مدفوع بالتنفيذ، لغة تقنية
  • BDD: يركز على السلوك، مدفوع بالأعمال، لغة طبيعية
  • كلاهما: يمكن استخدامهما معًا - BDD للميزات، TDD للتنفيذ

ينشئ BDD مواصفات قابلة للتنفيذ تعمل كتوثيق واختبارات آلية، مما يحسن التواصل ويقلل من سوء الفهم بين أعضاء الفريق.