Recently while debugging some tests that were failing on our build server, but passing locally, we needed to see the state of the Database for the application when a test had failed - using Behat hooks and the Symfony Process component, here's how we did it.
This is a quick context that we came up with that will dump a database to a file when a scenario in Behat fails.
The filename will be:
behat-scenario-failed-{scenarioTitle}-{dateStamp}.sql
So if I have a scenario that was run:
Scenario: A user can filter results
The filename would be along the lines of:
behat-scenario-failed-A user can filter results-20170124113226.sql
Notes:
behat.yml
- homework for you all!)app/logs
directory at the minute, this was just because we have the contents of this directory marked as artefacts at the end of a build.features/bootstrap/App/Context/DbDumpContext.php
<?php
namespace App\Context;
use Behat\Behat\Hook\Scope\AfterScenarioScope;
use Behat\Symfony2Extension\Context\KernelAwareContext;
use Behat\Symfony2Extension\Context\KernelDictionary;
use Symfony\Component\Process\Process;
class DbDumpContext implements KernelAwareContext
{
use KernelDictionary;
/**
* @AfterScenario
*
* @param AfterScenarioScope $scope
*/
public function dumpDatabaseToFile(AfterScenarioScope $scope)
{
if ( ! $scope->getTestResult()->isPassed()) {
$title = $scope->getScenario()->getTitle();
$processCommand = $this->getProcess($title);
$sqlDumpProcess = new Process($processCommand);
$sqlDumpProcess->start();
}
}
/**
* @param string $scenarioTitle
*
* @return string
*/
private function getDumpFileName($scenarioTitle)
{
return sprintf(
'%s/logs/behat-scenario-failed-%s-%s.sql',
$this->getKernel()->getRootDir(),
$scenarioTitle,
(new \DateTimeImmutable)->format('YmdHis')
);
}
/**
* @param string $title
*
* @return string
*/
private function getProcess($title)
{
$kernel = $this->getKernel();
$container = $kernel->getContainer();
return sprintf(
"mysqldump --user='%s' --password='%s' %s > '%s'",
$container->getParameter('database_user'),
$container->getParameter('database_password'),
$container->getParameter('database_name'),
$this->getDumpFileName($title)
);
}
}
Edit: This has been turned into a little package that we’ll be using across our projects when needed - early stages, but you can find it here: vivait/behat-mysql-dump
Article written by:
Matt
A BDD and TDD fan, his aims and goals are to mentor and help the developers to grow, and to continue making great software.
We've found ourselves needing some higher-level tests for some emails that were being sent recently (via a command that's run regularly from a cron) - here's how we did it!
Read more about Swift Mailer, Symfony and spooling emails for testing purposesWe heavily use Docker for Mac for the internal development of our products. It allows us to closely replicate the internal, automated testing, user acceptance testing and production platforms. There is just one problem, that I'm sure you've also found... The performance of the file system when using volume mounts.
Read more about Docker for Mac Performance using NFS (Updated for macOS Catalina)Recently when writing some tests using a data provider in PHPUnit, I wanted to be able to re-run a specific set, rather than the test with every single set in the data provider. I discovered the filtering options available in PHPUnit were a lot more powerful than I'd first thought.
Read more about Running PHPUnit with a specific data provider set