@@ -270,30 +270,31 @@ Finally, we got to the automation part. How does Behat know what to do
270270when it sees ``Given there is a "Sith Lord Lightsaber", which costs £5 ``? You
271271tell it. You write PHP code inside your context class (``FeatureContext ``
272272in our case) and tell Behat that this code represents a specific scenario step
273- (via an annotation with a pattern):
273+ (via an attribute with a pattern):
274274
275275.. code-block :: php
276276
277- /**
278- * @Given there is a(n) :arg1, which costs £:arg2
279- */
277+ #[Given('there is a(n) :arg1, which costs £:arg2')]
280278 public function thereIsAWhichCostsPs($arg1, $arg2)
281279 {
282280 throw new PendingException();
283281 }
284282
285283 .. note ::
286284
287- `` /** ... */ `` is a special syntax in PHP called a doc-block. It is
288- discoverable at runtime and used by different PHP frameworks as a
289- way to provide additional meta-information for the classes, methods and
290- functions. Behat uses doc-blocks for step definitions, step
291- transformations and hooks .
285+ Behat uses PHP Attributes for step definitions, step
286+ transformations and hooks. It also supports doc-block
287+ annotations for compatibility with legacy code, but this
288+ syntax is deprecated - see the :doc: ` annotations < /user_guide/annotations >` documentation
289+ for details .
292290
293- ``@ Given there is a(n) :arg1, which costs £:arg2 `` above the method tells Behat
291+ ``#[ Given(' there is a(n) :arg1, which costs £:arg2')] `` above the method tells Behat
294292that this particular method should be executed whenever Behat sees step that
295- looks like ``... there is a ..., which costs £... ``. This pattern will match
296- any of the following steps:
293+ looks like ``... there is a ..., which costs £... ``.
294+
295+ The ``#[Given] ``, ``#[When] `` and ``#[Then] `` attributes are functionally identical - they
296+ only exist separately to help keep the wording of your step definitions readable. So
297+ this pattern will match any of the following steps:
297298
298299.. code-block :: gherkin
299300
@@ -324,9 +325,7 @@ Not only that, but Behat will capture tokens (words starting with ``:``, e.g.
324325
325326 .. code-block :: php
326327
327- /**
328- * @Given /there is an? \"([^\"]+)\", which costs £([\d\.]+)/
329- */
328+ #[Given('/there is an? \"([^\"]+)\", which costs £([\d\.]+)/')]
330329 public function thereIsAWhichCostsPs($arg1, $arg2)
331330 {
332331 throw new PendingException();
341340
342341 --- FeatureContext has missing steps. Define them with these snippets:
343342
344- /**
345- * @Given there is a :arg1, which costs £:arg2
346- */
343+ #[Given('there is a :arg1, which costs £:arg2')]
347344 public function thereIsAWhichCostsPs($arg1, $arg2)
348345 {
349346 throw new PendingException();
@@ -370,36 +367,31 @@ If you executed ``--append-snippets``, your ``FeatureContext`` should look like:
370367 use Behat\Behat\Context\SnippetAcceptingContext;
371368 use Behat\Gherkin\Node\PyStringNode;
372369 use Behat\Gherkin\Node\TableNode;
370+ use Behat\Step\Given;
371+ use Behat\Step\Then;
372+ use Behat\Step\When;
373373
374374 class FeatureContext implements SnippetAcceptingContext
375375 {
376- /**
377- * @Given there is a :arg1, which costs £:arg2
378- */
376+ #[Given('there is a :arg1, which costs £:arg2')]
379377 public function thereIsAWhichCostsPs($arg1, $arg2)
380378 {
381379 throw new PendingException();
382380 }
383381
384- /**
385- * @When I add the :arg1 to the basket
386- */
382+ #[When('I add the :arg1 to the basket')]
387383 public function iAddTheToTheBasket($arg1)
388384 {
389385 throw new PendingException();
390386 }
391387
392- /**
393- * @Then I should have :arg1 product(s) in the basket
394- */
388+ #[Then('I should have :arg1 product(s) in the basket')]
395389 public function iShouldHaveProductInTheBasket($arg1)
396390 {
397391 throw new PendingException();
398392 }
399393
400- /**
401- * @Then the overall basket price should be £:arg1
402- */
394+ #[Then('the overall basket price should be £:arg1')]
403395 public function theOverallBasketPriceShouldBePs($arg1)
404396 {
405397 throw new PendingException();
@@ -433,6 +425,9 @@ code we could come up with to fulfil our scenario. Something like this:
433425 use Behat\Behat\Context\SnippetAcceptingContext;
434426 use Behat\Gherkin\Node\PyStringNode;
435427 use Behat\Gherkin\Node\TableNode;
428+ use Behat\Step\Given;
429+ use Behat\Step\Then;
430+ use Behat\Step\When;
436431
437432 class FeatureContext implements SnippetAcceptingContext
438433 {
@@ -445,25 +440,19 @@ code we could come up with to fulfil our scenario. Something like this:
445440 $this->basket = new Basket($this->shelf);
446441 }
447442
448- /**
449- * @Given there is a :product, which costs £:price
450- */
443+ #[Given('there is a :arg1, which costs £:arg2')]
451444 public function thereIsAWhichCostsPs($product, $price)
452445 {
453446 $this->shelf->setProductPrice($product, floatval($price));
454447 }
455448
456- /**
457- * @When I add the :product to the basket
458- */
449+ #[When('I add the :arg1 to the basket')]
459450 public function iAddTheToTheBasket($product)
460451 {
461452 $this->basket->addProduct($product);
462453 }
463454
464- /**
465- * @Then I should have :count product(s) in the basket
466- */
455+ #[Then('I should have :arg1 product(s) in the basket')]
467456 public function iShouldHaveProductInTheBasket($count)
468457 {
469458 // Normally you would import this class - we are using the fully qualified name
@@ -474,9 +463,7 @@ code we could come up with to fulfil our scenario. Something like this:
474463 );
475464 }
476465
477- /**
478- * @Then the overall basket price should be £:price
479- */
466+ #[Then('the overall basket price should be £:arg1')]
480467 public function theOverallBasketPriceShouldBePs($price)
481468 {
482469 \PHPUnit\Framework\Assert::assertSame(
0 commit comments