Contact

FUxCon 2013


Testdata

CakePHP

To generate test data from our scenario step definitions, the CakePHP implementation provides a custom, ancillary method createProjects() in controller BehatController in file app/Controller/BehatController.php. In the step definition, we call this before running a test suite to initialize the test data:

<?php
class FeatureContext extends MinkContext
{
  const PROJECT_COUNT = 7;

  /**
   * @BeforeSuite
   */
  public static function prepare(SuiteEvent $event)
  {
    $params = $event->getContextParameters();
    $baseUrl = $params['base_url'];

    /* 
     * Initialize test database with more projects than 
     * what fits on a page
     */
    $config = json_decode(file_get_contents($baseUrl . 'behat/config'));
    if (!$config) {
      throw new Exception('Could not get config from ' . $baseUrl);
    }
    $count = $config->pageSize * 3 + intval($config->pageSize / 2);
    $result = json_decode(file_get_contents($baseUrl . 'behat/createProjects/' . self::PROJECT_COUNT));

    if ($result->status != "OK") {
      throw new Exception($result->message);
    }
  }
}

On the server side, there was some ugly fiddling required to make the creation of demo picture uploads work.

<?php
class BehatController {
  function createProjects($count = 0)
  {
    $tmp = tempnam('/tmp', 'testimage.');
    $picture = array(
      'tmp_name' => $tmp,
      'type' => 'image/jpeg',
      'error' => 'behat_test',
    );

    for ($i = 1; $i <= $count; $i++) {
      copy(IMAGES . 'testimage.jpg', $tmp);

      $this->Project->create();
      if (!$this->Project->save(array(
        'picture' => $picture,
      ))) {
        throw new Exception("SAVE failed");
      }
    }
  }
}

In the Project model, this needs to be a special case as in this case the image is not an uploaded one:

<?php
class Project extends AppModel {

  function beforeSave($options = array()) {
    $file = $this->data[$this->alias]['picture'];

    if ($file['error'] === UPLOAD_ERR_NO_FILE 
      || $file['error'] === 'behat_test') {
      return TRUE;
    }
  }
  
  function afterSave($created) {
    $file = $this->data[$this->alias]['picture'];
    if ($file['error'] === 'behat_test') {
      if (!rename($file['tmp_name'], IMAGES . 'project' . DS . $this->id . '.jpg')) {
        throw new Exception("Failed to move file: " 
          . posix_strerror(posix_get_last_error()));
      }
    }
    else
    if ($file['error'] === UPLOAD_ERR_OK) {
      if (!move_uploaded_file($file['tmp_name'], IMAGES . 'project' . DS . $this->id . '.jpg')) {
        throw new Exception("Failed to move file: " 
          . posix_strerror(posix_get_last_error()));
      }
    }
  }
}

Django

In our Django implementation, we use the app autofixture that we install in the usual way:

source env/bin/activate 
pip install django-autofixture

… and register it with Django in file projects/settings.py:

INSTALLED_APPS = (    
  'autofixture',    
)

Whith that, we have a new verb in the manage.py shell that we can use to generate test data:

python manage.py loadtestdata projects.Project:50

Currently, there are not special provisions to re-generate test data during the running of tests from Behat.

Drupal

Our Drupal installation uses devel_generate, a submodule of Devel to (re-)generate test data:

Drupal devel generate

There are quite a view settings that allow to fine-tune the generation of test data:

Drupal devel generate

With that, it is easily possible to generate test projects:

Drupal devel generate

To integrate test data generation into an automatic test framework, the integration into the Drush command line framework is very useful:

Drupal devel generate drush

However, our current implementation has no provision to automate test data generation when running Behat tests.

Symfony

Our Symfony implementation currently does not have any provision for test data generation. The roll-it-yourself approach from our CakePHP implementation is probably ported easily enough.

There are also some solutions that have a more sophisticated approach which could be applied, namely (gleaned from an answer on Stack Overflow):

Some more work is needed to integrate either of these into automated Behat-driven tests.



comments powered by Disqus