Skip to content
Browse files

refactored filtering system (closes Behat#154)

  • Loading branch information...
1 parent 3fe2fb5 commit 30ea22dbeb1044a63f5911417a738dfcddb90b8e @everzet everzet committed Jul 1, 2012
View
7 src/Behat/Gherkin/Filter/FilterInterface.php
@@ -37,4 +37,11 @@ public function isFeatureMatch(FeatureNode $feature);
* @return Boolean
*/
public function isScenarioMatch(ScenarioNode $scenario);
+
+ /**
+ * Filters feature according to the filter.
+ *
+ * @param FeatureNode $feature
+ */
+ public function filterFeature(FeatureNode $feature);
}
View
46 src/Behat/Gherkin/Filter/LineFilter.php
@@ -3,7 +3,8 @@
namespace Behat\Gherkin\Filter;
use Behat\Gherkin\Node\FeatureNode,
- Behat\Gherkin\Node\ScenarioNode;
+ Behat\Gherkin\Node\ScenarioNode,
+ Behat\Gherkin\Node\OutlineNode;
/*
* This file is part of the Behat Gherkin.
@@ -53,6 +54,47 @@ public function isFeatureMatch(FeatureNode $feature)
*/
public function isScenarioMatch(ScenarioNode $scenario)
{
- return $this->filterLine === $scenario->getLine();
+ if ($this->filterLine === $scenario->getLine()) {
+ return true;
+ }
+
+ if ($scenario instanceof OutlineNode && $scenario->hasExamples()) {
+ return $this->filterLine === $scenario->getLine()
@cogitatio
cogitatio added a note Jul 1, 2012

This is redunant. Has been done in line 57

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ || in_array($this->filterLine, $scenario->getExamples()->getRowLines());
+ }
+
+ return false;
+ }
+
+ /**
+ * Filters feature according to the filter.
+ *
+ * @param FeatureNode $feature
+ */
+ public function filterFeature(FeatureNode $feature)
+ {
+ $scenarios = $feature->getScenarios();
+ foreach ($scenarios as $i => $scenario) {
+ if (!$this->isScenarioMatch($scenario)) {
+ unset($scenarios[$i]);
+ continue;
+ }
+
+ if ($scenario instanceof OutlineNode && $scenario->hasExamples()) {
+ $lines = $scenario->getExamples()->getRowLines();
+ $rows = $scenario->getExamples()->getNumeratedRows();
+
+ if (current($lines) <= $this->filterLine && end($lines) >= $this->filterLine) {
+ $scenario->getExamples()->setRows(array());
+ $scenario->getExamples()->addRow($rows[$lines[0]], $lines[0]);
+
+ if ($lines[0] !== $this->filterLine) {
+ $scenario->getExamples()->addRow($rows[$this->filterLine], $this->filterLine);
+ }
+ }
+ }
+ }
+
+ $feature->setScenarios($scenarios);
}
}
View
52 src/Behat/Gherkin/Filter/LineRangeFilter.php
@@ -3,7 +3,8 @@
namespace Behat\Gherkin\Filter;
use Behat\Gherkin\Node\FeatureNode,
- Behat\Gherkin\Node\ScenarioNode;
+ Behat\Gherkin\Node\ScenarioNode,
+ Behat\Gherkin\Node\OutlineNode;
/*
* This file is part of the Behat Gherkin.
@@ -60,7 +61,52 @@ public function isFeatureMatch(FeatureNode $feature)
*/
public function isScenarioMatch(ScenarioNode $scenario)
{
- return $this->filterMinLine <= $scenario->getLine()
- && $this->filterMaxLine >= $scenario->getLine();
+ if ($this->filterMinLine <= $scenario->getLine()
+ && $this->filterMaxLine >= $scenario->getLine()) {
+ return true;
+ }
+
+ if ($scenario instanceof OutlineNode && $scenario->hasExamples()) {
+ foreach ($scenario->getExamples()->getRowLines() as $line) {
+ if ($line >= $this->filterMinLine && $line <= $this->filterMaxLine) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Filters feature according to the filter.
+ *
+ * @param FeatureNode $feature
+ */
+ public function filterFeature(FeatureNode $feature)
+ {
+ $scenarios = $feature->getScenarios();
+ foreach ($scenarios as $i => $scenario) {
+ if (!$this->isScenarioMatch($scenario)) {
+ unset($scenarios[$i]);
+ continue;
+ }
+
+ if ($scenario instanceof OutlineNode && $scenario->hasExamples()) {
+ $lines = $scenario->getExamples()->getRowLines();
+ $rows = $scenario->getExamples()->getNumeratedRows();
+
+ $scenario->getExamples()->setRows(array());
+ $scenario->getExamples()->addRow($rows[$lines[0]], $lines[0]);
+ unset($rows[$lines[0]]);
+
+ foreach ($rows as $line => $row) {
+ if ($this->filterMinLine <= $line && $this->filterMaxLine >= $line) {
+ $scenario->getExamples()->addRow($row, $line);
+ }
+ }
+ }
+ }
+
+ $feature->setScenarios($scenarios);
}
}
View
4 src/Behat/Gherkin/Filter/NameFilter.php
@@ -18,14 +18,14 @@
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
-class NameFilter implements FilterInterface
+class NameFilter extends SimpleFilter
{
protected $filterString;
/**
* Initializes filter.
*
- * @param string $filterStringString Name filter string
+ * @param string $filterString Name filter string
*/
public function __construct($filterString)
{
View
38 src/Behat/Gherkin/Filter/SimpleFilter.php
@@ -0,0 +1,38 @@
+<?php
+
+namespace Behat\Gherkin\Filter;
+
+use Behat\Gherkin\Node\FeatureNode;
+
+/*
+ * This file is part of the Behat Gherkin.
+ * (c) 2011 Konstantin Kudryashov <ever.zet@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Abstract filter class.
+ *
+ * @author Konstantin Kudryashov <ever.zet@gmail.com>
+ */
+abstract class SimpleFilter implements FilterInterface
+{
+ /**
+ * Filters feature according to the filter.
+ *
+ * @param FeatureNode $feature
+ */
+ public function filterFeature(FeatureNode $feature)
+ {
+ $scenarios = $feature->getScenarios();
+ foreach ($scenarios as $i => $scenario) {
+ if (!$this->isScenarioMatch($scenario)) {
+ unset($scenarios[$i]);
+ }
+ }
+
+ $feature->setScenarios($scenarios);
+ }
+}
View
6 src/Behat/Gherkin/Filter/TagFilter.php
@@ -19,14 +19,14 @@
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
-class TagFilter implements FilterInterface
+class TagFilter extends SimpleFilter
{
protected $filterString;
/**
* Initializes filter.
*
- * @param string $filterStringString Name filter string
+ * @param string $filterString Name filter string
*/
public function __construct($filterString)
{
@@ -61,6 +61,8 @@ public function isScenarioMatch(ScenarioNode $scenario)
* Checks that node matches condition.
*
* @param AbstractNode $node Node to check
+ *
+ * @return Boolean
*/
protected function matchesCondition(AbstractNode $node)
{
View
13 src/Behat/Gherkin/Gherkin.php
@@ -98,20 +98,11 @@ public function load($resource, array $filters = array())
}
$features = $loader->load($resource);
-
foreach ($features as $feature) {
- $scenarios = $feature->getScenarios();
- foreach ($scenarios as $i => $scenario) {
- foreach ($filters as $filter) {
- if (!$filter->isScenarioMatch($scenario)) {
- unset($scenarios[$i]);
- break;
- }
- }
+ foreach ($filters as $filter) {
+ $filter->filterFeature($feature);
}
- $feature->setScenarios($scenarios);
-
if ($this->freeze) {
$feature->freeze();
}
View
56 src/Behat/Gherkin/Node/TableNode.php
@@ -55,10 +55,6 @@ public function createExampleRowStepArgument(array $tokens)
*/
public function addRow($row, $line = null)
{
- if (null !== $line) {
- $this->rowLines[] = $line;
- }
-
if (is_array($row)) {
$this->rows[] = $row;
} else {
@@ -68,6 +64,8 @@ public function addRow($row, $line = null)
return preg_replace("/^\s*|\s*$/", '', $item);
}, explode('|', $row));
}
+
+ $this->rowLines[count($this->rows) - 1] = $line;
}
/**
@@ -88,6 +86,7 @@ public function getRows()
public function setRows(array $rows)
{
$this->rows = $rows;
+ $this->rowLines = array();
}
/**
@@ -154,25 +153,6 @@ public function getRowsHash()
}
/**
- * Converts table into string
- *
- * @return string
- */
- public function __toString()
- {
- $string = '';
-
- for ($i = 0; $i < count($this->getRows()); $i++) {
- if ('' !== $string) {
- $string .= "\n";
- }
- $string .= $this->getRowAsString($i);
- }
-
- return $string;
- }
-
- /**
* Sets current node definition keyword.
*
* @param string $keyword Sets table keyword
@@ -193,6 +173,17 @@ public function getKeyword()
}
/**
+ * Returns numerated table lines.
+ * Line numbers are keys, lines are values.
+ *
+ * @return array
+ */
+ public function getNumeratedRows()
+ {
+ return array_combine($this->rowLines, $this->rows);
+ }
+
+ /**
* Returns line numbers for rows.
*
* @return array
@@ -213,6 +204,25 @@ public function getLine()
}
/**
+ * Converts table into string
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ $string = '';
+
+ for ($i = 0; $i < count($this->getRows()); $i++) {
+ if ('' !== $string) {
+ $string .= "\n";
+ }
+ $string .= $this->getRowAsString($i);
+ }
+
+ return $string;
+ }
+
+ /**
* Returns max length of specific column.
*
* @param integer $columnNum Column number
View
64 tests/Behat/Gherkin/Filter/FilterTest.php
@@ -0,0 +1,64 @@
+<?php
+
+namespace Tests\Behat\Gherkin\Filter;
+
+use Behat\Gherkin\Keywords\ArrayKeywords,
+ Behat\Gherkin\Lexer,
+ Behat\Gherkin\Parser;
+
+abstract class FilterTest extends \PHPUnit_Framework_TestCase
+{
+ protected function getParser()
+ {
+ return new Parser(
+ new Lexer(
+ new ArrayKeywords(array(
+ 'en' => array(
+ 'feature' => 'Feature',
+ 'background' => 'Background',
+ 'scenario' => 'Scenario',
+ 'scenario_outline' => 'Scenario Outline|Scenario Template',
+ 'examples' => 'Examples|Scenarios',
+ 'given' => 'Given',
+ 'when' => 'When',
+ 'then' => 'Then',
+ 'and' => 'And',
+ 'but' => 'But'
+ )
+ ))
+ )
+ );
+ }
+
+ protected function getGherkinFeature()
+ {
+ return <<<GHERKIN
+Feature: Long feature with outline
+ Scenario: Scenario#1
+ Given initial step
+ When action occurs
+ Then outcomes should be visible
+
+ Scenario: Scenario#2
+ Given initial step
+ And another initial step
+ When action occurs
+ Then outcomes should be visible
+
+ Scenario Outline: Scenario#3
+ When <action> occurs
+ Then <outcome> should be visible
+
+ Examples:
+ | action | outcome |
+ | act#1 | out#1 |
+ | act#2 | out#2 |
+ | act#3 | out#3 |
+GHERKIN;
+ }
+
+ protected function getParsedFeature()
+ {
+ return $this->getParser()->parse($this->getGherkinFeature());
+ }
+}
View
57 tests/Behat/Gherkin/Filter/LineFilterTest.php
@@ -5,7 +5,7 @@
use Behat\Gherkin\Node,
Behat\Gherkin\Filter\LineFilter;
-class LineFilterTest extends \PHPUnit_Framework_TestCase
+class LineFilterTest extends FilterTest
{
public function testIsFeatureMatchFilter()
{
@@ -42,4 +42,59 @@ public function testIsScenarioMatchFilter()
$filter = new LineFilter(20);
$this->assertTrue($filter->isScenarioMatch($outline));
}
+
+ public function testFilterFeatureScenario()
+ {
+ $filter = new LineFilter(2);
+ $filter->filterFeature($feature = $this->getParsedFeature());
+ $this->assertCount(1, $scenarios = $feature->getScenarios());
+ $this->assertSame('Scenario#1', $scenarios[0]->getTitle());
+
+ $filter = new LineFilter(7);
+ $filter->filterFeature($feature = $this->getParsedFeature());
+ $this->assertCount(1, $scenarios = $feature->getScenarios());
+ $this->assertSame('Scenario#2', $scenarios[0]->getTitle());
+
+ $filter = new LineFilter(5);
+ $filter->filterFeature($feature = $this->getParsedFeature());
+ $this->assertCount(0, $scenarios = $feature->getScenarios());
+ }
+
+ public function testFilterFeatureOutline()
+ {
+ $filter = new LineFilter(13);
+ $filter->filterFeature($feature = $this->getParsedFeature());
+ $this->assertCount(1, $scenarios = $feature->getScenarios());
+ $this->assertSame('Scenario#3', $scenarios[0]->getTitle());
+ $this->assertCount(4, $scenarios[0]->getExamples()->getRows());
+
+ $filter = new LineFilter(19);
+ $filter->filterFeature($feature = $this->getParsedFeature());
+ $this->assertCount(1, $scenarios = $feature->getScenarios());
+ $this->assertSame('Scenario#3', $scenarios[0]->getTitle());
+ $this->assertCount(2, $scenarios[0]->getExamples()->getRows());
+ $this->assertSame(array(
+ array('action', 'outcome'),
+ array('act#1', 'out#1'),
+ ), $scenarios[0]->getExamples()->getRows());
+
+ $filter = new LineFilter(21);
+ $filter->filterFeature($feature = $this->getParsedFeature());
+ $this->assertCount(1, $scenarios = $feature->getScenarios());
+ $this->assertSame('Scenario#3', $scenarios[0]->getTitle());
+ $this->assertCount(2, $scenarios[0]->getExamples()->getRows());
+ $this->assertSame(array(
+ array('action', 'outcome'),
+ array('act#3', 'out#3'),
+ ), $scenarios[0]->getExamples()->getRows());
+
+ $filter = new LineFilter(18);
+ $filter->filterFeature($feature = $this->getParsedFeature());
+ $this->assertCount(1, $scenarios = $feature->getScenarios());
+ $this->assertSame('Scenario#3', $scenarios[0]->getTitle());
+ $this->assertCount(1, $scenarios[0]->getExamples()->getRows());
+ $this->assertSame(array(
+ array('action', 'outcome'),
+ ), $scenarios[0]->getExamples()->getRows());
+ }
}
View
39 tests/Behat/Gherkin/Filter/LineRangeFilterTest.php
@@ -5,7 +5,7 @@
use Behat\Gherkin\Node,
Behat\Gherkin\Filter\LineRangeFilter;
-class LineRangeFilterTest extends \PHPUnit_Framework_TestCase
+class LineRangeFilterTest extends FilterTest
{
public function featureLineRangeProvider()
{
@@ -56,4 +56,41 @@ public function testIsScenarioMatchFilter($filterMinLine, $filterMaxLine, $expec
$this->assertEquals($expectedNumberOfMatches, intval($filter->isScenarioMatch($scenario))
+ intval($filter->isScenarioMatch($outline)));
}
+
+ public function testFilterFeatureScenario()
+ {
+ $filter = new LineRangeFilter(1, 3);
+ $filter->filterFeature($feature = $this->getParsedFeature());
+ $this->assertCount(1, $scenarios = $feature->getScenarios());
+ $this->assertSame('Scenario#1', $scenarios[0]->getTitle());
+
+ $filter = new LineRangeFilter(5, 9);
+ $filter->filterFeature($feature = $this->getParsedFeature());
+ $this->assertCount(1, $scenarios = $feature->getScenarios());
+ $this->assertSame('Scenario#2', $scenarios[0]->getTitle());
+
+ $filter = new LineRangeFilter(5, 6);
+ $filter->filterFeature($feature = $this->getParsedFeature());
+ $this->assertCount(0, $scenarios = $feature->getScenarios());
+ }
+
+ public function testFilterFeatureOutline()
+ {
+ $filter = new LineRangeFilter(12, 14);
+ $filter->filterFeature($feature = $this->getParsedFeature());
+ $this->assertCount(1, $scenarios = $feature->getScenarios());
+ $this->assertSame('Scenario#3', $scenarios[0]->getTitle());
+ $this->assertCount(1, $scenarios[0]->getExamples()->getRows());
+
+ $filter = new LineRangeFilter(15, 20);
+ $filter->filterFeature($feature = $this->getParsedFeature());
+ $this->assertCount(1, $scenarios = $feature->getScenarios());
+ $this->assertSame('Scenario#3', $scenarios[0]->getTitle());
+ $this->assertCount(3, $scenarios[0]->getExamples()->getRows());
+ $this->assertSame(array(
+ array('action', 'outcome'),
+ array('act#1', 'out#1'),
+ array('act#2', 'out#2'),
+ ), $scenarios[0]->getExamples()->getRows());
+ }
}
View
30 tests/Behat/Gherkin/GherkinTest.php
@@ -10,6 +10,9 @@ class GherkinTest extends \PHPUnit_Framework_TestCase
{
public function testLoader()
{
+ $customFilter1 = $this->getCustomFilterMock();
+ $customFilter2 = $this->getCustomFilterMock();
+
$gherkin = new Gherkin();
$gherkin->addLoader($loader = $this->getLoaderMock());
$gherkin->addFilter($nameFilter = $this->getNameFilterMock());
@@ -29,34 +32,27 @@ public function testLoader()
->with($resource)
->will($this->returnValue(array($feature)));
+ $filterFeature = clone $feature;
$nameFilter
->expects($this->once())
- ->method('isScenarioMatch')
- ->with($scenario)
- ->will($this->returnValue(true));
-
+ ->method('filterFeature')
+ ->with($filterFeature);
$tagFilter
->expects($this->once())
- ->method('isScenarioMatch')
- ->with($scenario)
- ->will($this->returnValue(true));
-
- $customFilter1 = $this->getCustomFilterMock();
+ ->method('filterFeature')
+ ->with($filterFeature);
$customFilter1
->expects($this->once())
- ->method('isScenarioMatch')
- ->with($scenario)
- ->will($this->returnValue(true));
-
- $customFilter2 = $this->getCustomFilterMock();
+ ->method('filterFeature')
+ ->with($filterFeature);
$customFilter2
->expects($this->once())
- ->method('isScenarioMatch')
- ->with($scenario)
- ->will($this->returnValue(true));
+ ->method('filterFeature')
+ ->with($filterFeature);
$features = $gherkin->load($resource, array($customFilter1, $customFilter2));
$this->assertEquals(1, count($features));
+ $this->assertTrue($feature->isFrozen());
$scenarios = $features[0]->getScenarios();
$this->assertEquals(1, count($scenarios));

0 comments on commit 30ea22d

Please sign in to comment.
Something went wrong with that request. Please try again.