>> Cách bật Disqus module trong Drupal 7
>> Drupal 7 Form API: Sử dụng #states cho multiple conditionals (AND, OR and XOR)
Behat is one of the more popular testing frameworks in the Drupal community at the moment, for various reasons. One of these reasons is the useful Behat Drupal Extension that provides a DrupalContext
class that can be extended to get a lot of Drupal specific functionality in yourFeatureContext
right off the bat.
In this post, I'm going to show you how to make Behat aware of any PHP errors that are logged to the watchdog
table during each scenario that it runs. In Behat's default setup, a notice or warning level PHP error will not usually break site functionality and so won't fail any tests. Generally though, we want to squash every bug we know about during our QA phase so it would be great to fail any tests that incidentally throw errors along the way.
The main benefits of this technique are:
-
No need to write extra step definitions or modify existing steps, but you'll get some small degree of coverage for all functionality that just happens to be on the same page as whatever you are writing tests for
-
Very simple to implement once you have a working Behat setup with the
DrupalContext
class and Drupal API driver
-
PHP errors are usually very easy to cleanup if you notice them immediately after introducing them, but not necessarily 6 months later. This is probably the easiest way I've found to nip them in the bud, especially when upgrading contrib modules between minor versions (where it's quite common to find new PHP notices being introduced).
The setup
Once you've configured the Drupal extension for Behat, and set the api_driver
to drupal
in your behat.yml
file, you can use Drupal API functions directly inside your FeatureContext.php
file (inside your step definitions).
Conceptually, what we're trying to achieve is pretty straightforward. We want to flush the watchdog
table before we run any tests and then fail any scenario that has resulted in one or more PHP messages logged by the end of it. It's also important that we give ourselves enough debugging information to track down errors that we detect. Luckily, watchdog
already keeps serlialized PHP error debug information serialized by default, so we can unserlialize what we need and print it straight to the console as required.
You will need to write a custom FeatureContext
class extending DrupalContext
with hooks for @BeforeSuite
and @AfterScenario
.
Your @BeforeSuite
should look something like this:
<?php
/**
* @BeforeSuite
*/
public static function prepare(SuiteEvent $event) {
// Clear out anything that might be in the watchdog table from god knows
// where.
db_truncate('watchdog')->execute();
}
And your corresponding @AfterScenario
would look like this:
<?php
/**
* Run after every scenario.
*/
public function afterScenario($event) {
$log = db_select('watchdog', 'w')
->fields('w')
->condition('w.type', 'php', '=')
->execute()
->fetchAll();
if (!empty($log)) {
foreach ($log as $error) {
// Make the substitutions easier to read in the log.
$error->variables = unserialize($error->variables);
print_r($error);
}
throw new \Exception('PHP errors logged to watchdog in this scenario.');
}
}
My apologies, I know this code is a little rough, I'm just using print_r()
to spit out the data I'm interested in without even bothering to process the Drupal variable substitutions through format_string()
, but hey, it's still legible enough for the average PHP developer and it totally works! Maybe someone else will see this, be inspired, and share a nicer version back here...