Skip to content

Commit fbb94e4

Browse files
committed
update to tell PHPUnit assertions stopped working
resolve Behat/Behat#1618
1 parent 1f13e84 commit fbb94e4

File tree

2 files changed

+76
-27
lines changed

2 files changed

+76
-27
lines changed

quick_start.rst

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -455,49 +455,46 @@ code we could come up with to fulfil our scenario. Something like this:
455455
#[Then('I should have :arg1 product(s) in the basket')]
456456
public function iShouldHaveProductInTheBasket($count)
457457
{
458-
// Normally you would import this class - we are using the fully qualified name
459-
// to highlight that Behat does not come with an assertion tool (see note below).
460-
\PHPUnit\Framework\Assert::assertCount(
461-
intval($count),
462-
$this->basket
463-
);
458+
if (count($this->basket) !== intval($count)) {
459+
throw new \Exception(
460+
sprintf(
461+
'The basket should have %d item(s), but it has %d.',
462+
intval($count),
463+
count($this->basket)
464+
)
465+
);
466+
}
464467
}
465468
466469
#[Then('the overall basket price should be £:arg1')]
467470
public function theOverallBasketPriceShouldBePs($price)
468471
{
469-
\PHPUnit\Framework\Assert::assertSame(
470-
floatval($price),
471-
$this->basket->getTotalPrice()
472-
);
472+
$expectedPrice = floatval($price);
473+
$actualPrice = $this->basket->getTotalPrice();
474+
475+
if ($expectedPrice !== $actualPrice) {
476+
throw new \Exception(
477+
sprintf(
478+
'Expected basket total price to be %s, but got %s.',
479+
$expectedPrice,
480+
$actualPrice
481+
)
482+
);
483+
}
473484
}
474485
}
475486
476487
As you can see, in order to test and implement our application, we introduced 2 objects -
477488
``Shelf`` and ``Basket``. The first is responsible for storing products and their prices,
478489
the second is responsible for the representation of our customer basket. Through appropriate step
479490
definitions we declare products' prices and add products to the basket. We then compare the
480-
state of our ``Basket`` object with our expectations using PHPUnit assertions.
491+
state of our ``Basket`` object with our expectations and throw exception if the expectations aren't met.
481492

482493
.. note::
483494

484495
Behat doesn't come with its own assertion tool, but you can use any proper assertion
485-
tool out there. A proper assertion tool is a library whose assertions throw
486-
exceptions on failure. For example, if you're familiar with PHPUnit you can use
487-
its assertions in Behat by installing it via composer:
488-
489-
.. code-block:: bash
490-
491-
$ php composer.phar require --dev phpunit/phpunit
492-
493-
and then by simply using assertions in your steps:
494-
495-
.. code-block:: php
496-
497-
\PHPUnit\Framework\Assert::assertCount(
498-
intval($count),
499-
$this->basket
500-
);
496+
tool out there.
497+
Learn more in the paragraph :ref:`assertion-tools`
501498

502499
Now try to execute your feature tests:
503500

useful_resources.rst

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,58 @@ Integrating Behat with PHPStorm
1818
More information on integrating Behat with PHPStorm can be found in this
1919
`blog post`_.
2020

21+
.. _assertion-tools:
22+
23+
Assertion tools
24+
---------------
25+
26+
A proper assertion tool is a library whose assertions throw exceptions on failure.
27+
28+
For example a list of the most known:
29+
30+
- https://github.com/webmozarts/assert
31+
- https://github.com/beberlei/assert
32+
- https://github.com/zenstruck/assert
33+
34+
.. caution::
35+
If you are familiar with PHPUnit, you can use its assertion library
36+
37+
.. code-block:: bash
38+
39+
$ php composer.phar require --dev phpunit/phpunit
40+
41+
and then by simply using assertions in your steps:
42+
43+
.. code-block:: php
44+
45+
\PHPUnit\Framework\Assert::assertCount(
46+
intval($count),
47+
$this->basket
48+
);
49+
50+
**However, using PHPUnit for assertions no longer works with PHP 11.3.0 and later**.
51+
52+
This is due to a change in how PHPUnit's internal components are initialized.
53+
A direct alternative that provides a complete object and array comparison is not readily available.
54+
55+
Learn more at https://github.com/Behat/Behat/issues/1618.
56+
57+
However, a workaround exists by modifying the PHPUnit bootstrap file (in Symfony is usually at `tests/bootstrap.php`)
58+
to explicitly initialize the PHPUnit configuration when running Behat.
59+
This involves adding the following lines to your bootstrap file:
60+
61+
.. code-block:: php
62+
63+
if (defined('BEHAT_BIN_PATH')) {
64+
(new \PHPUnit\TextUI\Configuration\Builder())->build([]);
65+
}
66+
67+
This is a hack that forces PHPUnit to load the necessary components.
68+
The downside is that it creates a tight coupling between your project and PHPUnit's internal non-public API
69+
and it forces the entire PHPUnit framework to be bootstrapped along with Behat, which results in a larger memory footprint.
70+
This makes the workaround brittle and prone to breaking with future updates.
71+
72+
2173
Behat cheat sheet
2274
-----------------
2375

0 commit comments

Comments
 (0)