From e0a9e1a00c051f59b3889d5065a617c0d4a8e5a8 Mon Sep 17 00:00:00 2001 From: bocharsky-bw Date: Mon, 9 Nov 2015 20:53:22 +0200 Subject: [PATCH 1/2] Add vendor's file to VSC for code blocks --- .../Context/KernelDictionary.php | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 vendor/behat/symfony2-extension/src/Behat/Symfony2Extension/Context/KernelDictionary.php diff --git a/vendor/behat/symfony2-extension/src/Behat/Symfony2Extension/Context/KernelDictionary.php b/vendor/behat/symfony2-extension/src/Behat/Symfony2Extension/Context/KernelDictionary.php new file mode 100644 index 0000000..4420e81 --- /dev/null +++ b/vendor/behat/symfony2-extension/src/Behat/Symfony2Extension/Context/KernelDictionary.php @@ -0,0 +1,55 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Behat\Symfony2Extension\Context; + +use Symfony\Component\HttpKernel\KernelInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Kernel support methods for Symfony2Extension. + * + * @author Konstantin Kudryashov + */ +trait KernelDictionary +{ + private $kernel; + + /** + * Sets Kernel instance. + * + * @param KernelInterface $kernel + */ + public function setKernel(KernelInterface $kernel) + { + $this->kernel = $kernel; + } + + /** + * Returns HttpKernel instance. + * + * @return KernelInterface + */ + public function getKernel() + { + return $this->kernel; + } + + /** + * Returns HttpKernel service container. + * + * @return ContainerInterface + */ + public function getContainer() + { + return $this->kernel->getContainer(); + } +} From 4e3417d6b42a10e2182874f7fbd7cdfea8494544 Mon Sep 17 00:00:00 2001 From: bocharsky-bw Date: Mon, 9 Nov 2015 21:08:54 +0200 Subject: [PATCH 2/2] Add code blocks to the ch14 (clear-data-symfony-extension) --- knpu/clear-data-symfony-extension.md | 86 ++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 24 deletions(-) diff --git a/knpu/clear-data-symfony-extension.md b/knpu/clear-data-symfony-extension.md index 09bd3c2..535a5f7 100644 --- a/knpu/clear-data-symfony-extension.md +++ b/knpu/clear-data-symfony-extension.md @@ -1,7 +1,11 @@ # The SymfonyExtension & Clearing Data Between Scenarios Change the user and pass back to match the original user in the database: "admin" -and "admin". *Now* rerun the scenario: +and "admin": + +[[[ code('40b5daac0b') ]]] + +*Now* rerun the scenario: ```bash ./vendor/bin/behat features/web/authentication.feature @@ -9,7 +13,7 @@ and "admin". *Now* rerun the scenario: Boom! This time it explodes! -> Integrity constraint violation Unique constraint failed user.username +> Integrity constraint violation: UNIQUE constraint failed: user.username We already have a user called "admin" in the database... and since I made that a unique column, creating *another* user in `Given` is putting a stop to our party. @@ -26,12 +30,28 @@ want to empty the database before each scenario... except for any lookup tables. Since *we* don't have any of these pesky look-up guys, we can empty everything before every scenario. To do this, we'll of course, use hooks. -Create a new `public function clearData`. Clearing data now is pretty easy, since -we have access to the entity manager via `self::container->get('doctrine')->getManager();`. +Create a new `public function clearData()`: + +[[[ code('664a9b2c3b') ]]] + +Clearing data now is pretty easy, since we have access to the entity manager via +`self::container->get('doctrine')->getManager();`: + +[[[ code('73379cb924') ]]] + Now we can issue DELETE queries on the two entities that we care about so far: -product and user. I'll use `$em->createQuery('DELETE FROM AppBundle:Product')->execute();`. -Copy and paste that line and change "Product" to "User". Oh and make sure that says -"Product" and not "Products". Activate all of this with the `@BeforeScenario` annotation. +product and user. I'll use `$em->createQuery('DELETE FROM AppBundle:Product')->execute();`: + +[[[ code('ef81ad1396') ]]] + +Copy and paste that line and change "Product" to "User": + +[[[ code('17d499e619') ]]] + +Oh and make sure that says "Product" and not "Products". Activate all of this with the +`@BeforeScenario` annotation: + +[[[ code('ff2e48a1ed') ]]] Try it all again: @@ -47,30 +67,44 @@ And, surprise! There's an easier way to bootstrap Symfony and clear out the data I always like taking the long way first so we can see how things work. First, install a new library called `behat/symfony2-extension` with `--dev` so it -goes into my require dev: +goes into my require `dev` section: ```bash composer require behat/symfony2-extension --dev ``` -An `extension` in Behat is a plugin. We're already using the `MinkExtension`. +An `extension` in Behat is a plugin. We're already using the `MinkExtension`: + +[[[ code('27daea06b7') ]]] -Activate the new plugin in `behat.yml`: `Behat\Symfony2Extension:`. And as luck would -have it, it doesn't need any configuration. It looks like we still need to wait for -it to finish installing in the terminal... there we go! +Activate the new plugin in `behat.yml`: `Behat\Symfony2Extension:`: + +[[[ code('f5e71d6cc0') ]]] + +And as luck would have it, it doesn't need any configuration. It looks like we still +need to wait for it to finish installing in the terminal... there we go! The most important thing the Symfony2 Extension gives you is, access to Symfony's -container...but wait, we already have that? Well, this just makes it easier. +container... but wait, we already have that? Well, this just makes it easier. + +Remove the `private static $container;` property and the `bootstrapSymfony()` function. +Instead of these, we'll use a PHP 5.4 trait called `KernelDictionary`: + +[[[ code('a636d6da19') ]]] + +This gives us two new functions, `getKernel()`, but more importantly `getContainer()`: + +[[[ code('cc77eab4d3') ]]] -Remove the `private static $container;` property and the `bootstrapSymfony` function. -Instead of these, we'll use a PHP 5.4 trait called `KernelDictionary`. -This gives us two new functions, `getKernel()`, but more importantly `getContainer()`. It takes care of all of the booting of the kernel stuff for us, and it even reboots the kernel between each scenario so they don't run into each other. That's important because remember, each scenario should be completely independent of the others. -Search for the old `self::$container` code. Change it to `$this->getContainer()`. -You see that PhpStorm all of a sudden autocompletes the methods on the services +Search for the old `self::$container` code. Change it to `$this->getContainer()`: + +[[[ code('c1941ef181') ]]] + +You see that PhpStorm all of a sudden auto-completes the methods on the services we fetch because it recognizes this as the container and so knows that this returns the entity manager. @@ -85,10 +119,15 @@ can use the `KernelDictionary` on all of them to get access to the container. ## Clearing the Database Easily -Ok, so what about clearing the database? It'll be a huge pain to add more and more +OK, so what about clearing the database? It'll be a huge pain to add more and more manual queries. Fortunately Doctrine gives us a better way: a `Purger`. Create a new -variable called `$purger` and set it to a `new ORMPurger()`. Pass it the entity manager. -After that, type `$purger->purge();`, and that's it. +variable called `$purger` and set it to a `new ORMPurger()`. Pass it the entity manager: + +[[[ code('4a1ce99a60') ]]] + +After that, type `$purger->purge();`, and that's it: + +[[[ code('61566dcc53') ]]] This will go through each entity and clear out all of your data. If it's working, then our tests should pass: @@ -97,10 +136,9 @@ then our tests should pass: ./vendor/bin/behat features/web/authentication.feature ``` -And they do! Same functionality and a lot less code. For bigger databases with lots +And they do! Same functionality and a lot less code. For bigger databases with lots of lookup tables, it may be too much to clear every table and re-add all the data you need. In those cases, trying experimenting with creating a SQL file that populates -the database and executing that before each scenario. Or, populate an Sqlite file +the database and executing that before each scenario. Or, populate an SQLite file with whatever you want to start with, then copy this and use it as your database before each test. That's a super-fast way to roll back to your known data set. - \ No newline at end of file