Skip to content

Commit

Permalink
#3: Working on features autoloading.
Browse files Browse the repository at this point in the history
  • Loading branch information
Roy Segall committed May 14, 2015
1 parent 5c7076b commit c7fcbf2
Show file tree
Hide file tree
Showing 29 changed files with 1,120 additions and 391 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
src/Behat
composer.lock
composer.lock
results
114 changes: 56 additions & 58 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,86 +1,84 @@
# Behat for Drupal 8 contribute components.
# Behat for Drupal 8.

The module provide BDD testing framework to contribute components.
The module provide BDD testing framework for contribute components.

## How it's works?
The Behat we all know and love built from a couple of symofony elements. This
module use gherkin library which read the cucumber files(AKA *.feature file).
Each project that uses behat as a testing tool have a FeatureContext class that
contains the step definition or any other additional information.

After tearing down the feature file to steps definition behat module will search
for plugins which their ID match the step.

Eventually the behat module is just a layer which sit above the unit test
framework and trigger PHP commands.
Each module will need to to implement a FeatureContext plugin that will keep the
step definitions and other behat integration(i.e beforeScenario or afterScenario
methods).

## Define a plugin
Defining a plugin is very easy. All you need to do is to implement Behat step
definition plugin. For example the `I visit PATH` plugin:
Behat module implements a FeatureContext plugin:

```php
<?php

/**
* Contains Drupal\behat\Plugin\Step\Visit.
* Contains Drupal\behat\Plugin\FeatureContext\FeatureContextBase.
*/
namespace Drupal\behat\Plugin\Step;

use Drupal\behat\BehatStepAbstract;
use Drupal\behat\BehatTestsAbstract;
namespace Drupal\behat\Plugin\FeatureContext;

/**
* @Step(
* id = "I visit '(.*?)'"
* @FeatureContext(
* id = "behat",
* label = @Translation("Behat"),
* )
*/
class Visit extends BehatStepAbstract {

public function step(BehatTestsAbstract $behat, $url) {
$behat->visit($url);
}

}
```

In the feature file it look like this:
```cucumber
Given I visit 'user'
```

## Define a test
The test definition is quite easy as well. Create a file under the `Tests`
folder:
```php
<?php

/**
* Simple login test.
*
* @group behat
*
* @runTestsInSeparateProcesses
* @preserveGlobalState disabled
*/
class Login extends BehatTestsAbstract {
class FeatureContextBase extends BehatTestsAbstract {

use BasicTrait;

/**
* {@inheritdoc}
*/
public function beforeScenario(ScenarioInterface $scenarioInterface = NULL) {
parent::beforeScenario($scenarioInterface);

public function testLogin() {
$account = $this->drupalCreateUser();
$this
->setPlaceholder('@user-name', $account->label())
->setPlaceholder('@user-pass', $account->passRaw)
->executeScenario('login', 'behat');
$this->placeholders = [
'@user-name' => $account->label(),
'@user-pass' => $account->passRaw,
];
}

}
```

You can see there are arguments passed to the steps definition via `$this->setPlaceholder()`
This wll use us later on in the cucumber files. The key method is `$this->executeScenario()`
Which invoke a file named `login.feature` under the behat module. If you need to
invoke feature file to a theme component you'll need to write
`$this->executeScenario('collapsed', 'bootstrap', 'theme');`
This plugin implements a `beforeScenario` method to a create user for testing.
The `@runTestsInSeparateProcesses` and `@preserveGlobalState disabled`
annotation needed by the PHPUnit testing framework for fire up a mink browser
environment.

## Step definitions
As mentioned above, the FeatureContext plugin is replacing the FeatureContext
class. That class will keep all the step definition.

The default step definitions defined in a trait. In this way other modules could
provide more step definition and your FeatureContext could leverage them.

## Cucumber files
The cucumber files should be located at MODULE/src/Features/*.feature
By default all the feature files will be located at MODULE/src/Features. In the
future, you could specify other folder location in the plugin definition.

## Running the tests
There are two ways to run the tests. One way is using the UI under
`admin/config/development/behat` and you can check which files you want to run.
This isn't a good practice since it's not running in batch operation.

The best way is to use drush: `drush bin/behat PROVIDER URL`.

The `PROVIDER` is the ID for the FeatureContext plugin. In our case is `behat`.

The `URL` is the URL of your Drupal 8 installation.

For example: `drush bin/behat behat http://localhost/drupal8`

Running specific features could be done with the feature option:
`drush bin/behat behat http://localhost/drupal8 --features=login`

## Patch
You'll need to patch Drupal core with the latest [patch](https://www.drupal.org/node/2232861)
This will run only the login.feature file defined by the behat module.
6 changes: 6 additions & 0 deletions behat.links.menu.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
behat.test_form:
title: Behat
description: 'Run behat features files.'
route_name: behat.test_form
parent: system.admin_config_development
weight: -6
3 changes: 3 additions & 0 deletions behat.permissions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
run behat tests:
title: 'Run behat tests'
restrict access: true
18 changes: 17 additions & 1 deletion behat.routing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,20 @@ behat.state_system_page:
options:
_admin_route: TRUE
requirements:
_permission: 'access devel information'
_permission: 'run behat tests'

behat.test_form:
path: '/admin/config/development/behat'
defaults:
_form: '\Drupal\behat\Form\BehatTestForm'
_title: 'Behat'
requirements:
_permission: 'run behat tests'

behat.result_form:
path: '/admin/config/development/behat/results/{test_id}'
defaults:
_form: 'Drupal\behat\Form\BehatResultsForm'
_title: 'Test result'
requirements:
_permission: 'administer unit tests'
2 changes: 1 addition & 1 deletion behat.services.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
services:
plugin.manager.behat.step:
plugin.manager.behat.FeatureContext:
class: Drupal\behat\BehatPluginManager
parent: default_plugin_manager
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{
"require": {
"behat/gherkin": "~4.3"
"behat/gherkin": "~4.3",
"symfony/filesystem": "2.6"
},
"config": {
"vendor-dir": "src/Behat"
}
}
}
Binary file added composer.phar
Binary file not shown.
81 changes: 81 additions & 0 deletions drush/behat.drush.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php

/**
* @file
* Behat module drush integration.
*/

use Drupal\behat\Behat;
use Drupal\behat\BehatDrushHelper;
use Drupal\behat\Exception;
use Symfony\Component\HttpFoundation;

/**
* Implements hook_drush_command().
*/
function behat_drush_command() {
$items = [];

$items['behat-run-tests'] = [
'description' => dt('Run behat scenarios.'),
'examples' => [
'drush bin/behat behat http://localhost/drupal8' => dt('Run all the features files provided by the behat module.'),
'drush bin/behat behat http://localhost/drupal8 --features=login,comment' => dt('Run selected features files provided by the behat module.'),
],
'arguments' => [
'provider' => dt('The provider ID as defined in the plugin annotation.'),
'url' => dt('The URL for the Drupal installation.'),
],
'options' => [
'features' => dt('List of features in the provider.'),
],
'aliases' => ['bin/behat'],
];

return $items;
}

/**
* Running the tests using drush.
*
* @param $provider
* The name of the provider as defined in the FeaturesContext plugin
* definition.
*
* @throws \Drupal\behat\Exception\BehatException
*/
function drush_behat_run_tests($provider, $url) {
if (!$provider_info = Behat::getFeatureContexts($provider)) {
throw new Exception\BehatException(dt('The provider @provider was not found', ['@provider' => $provider]));
}

if (!$url) {
throw new Exception\BehatException(dt('You must provide the url to the current Drupal installation.'));
}

$class = $provider_info['class'];

$features = $providers = [];

// Store the feature context and the defining providers.
// todo: Consider themes and features files location defined by provider.
$providers[$class] = DRUPAL_ROOT . '/' . drupal_get_path('module', $provider) . '/src/Features/';

$components = BehatDrushHelper::FeaturesForProvider($provider);

foreach ($components as $component) {
$explode = explode('/', $component);
$features[$class][] = end($explode);
}

// todo: populate the values.
BehatDrushHelper::SetEnvInformation('FEATURES_PROVIDERS', serialize($providers));
BehatDrushHelper::SetEnvInformation('FEATURES_RUN', serialize($features));
BehatDrushHelper::SetEnvInformation('SIMPLETEST_BASE_URL', $url);
$tests_list['phpunit'][] = $class;

// Run tests.
$test_id = Behat::runTests($tests_list, 'drupal');

BehatDrushHelper::DisplaySearchResults($test_id);
}
10 changes: 5 additions & 5 deletions src/Annotation/Step.php → src/Annotation/FeatureContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@
use Drupal\Component\Annotation\Plugin;

/**
* Define a step definition annotation.
* Define a feature context plugin.
*
* @Annotation
*/
class Step extends Plugin {
class FeatureContext extends Plugin {

/**
* @var String
*
* The step.
* The directory.
*/
public $step;
public $directory;

}
}
Loading

0 comments on commit c7fcbf2

Please sign in to comment.