Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Focused tests #188

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions fixtures/focused.spec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

describe('Suite with focused sub-suites', function() {
it('should not run a normal test', function () {
throw new RuntimeException();
});

xit('should not run a pending test', function () {
throw new RuntimeException();
});

describe('a normal suite', function () {
it('should not be run', function () {
throw new RuntimeException();
});
});

xdescribe('a pending suite', function () {
it('should not be run', function () {
throw new RuntimeException();
});
});

fit('should run a focused test', function () {});

fdescribe('a focused suite', function () {
it('should run each test', function () {});
it('should run each test', function () {});

xit('should allow pending tests', function () {
throw new RuntimeException();
});

xdescribe('a nested pending suite', function () {
it('should have pending child tests', function () {
throw new RuntimeException();
});
});
});

fdescribe('a focused suite with nested focused tests', function () {
it('should not run unfocused tests', function () {
throw new RuntimeException();
});

fit('should run focused tests', function () {});
});

describe('an unfocused suite with nested focused tests', function () {
it('should not run unfocused tests', function () {
throw new RuntimeException();
});

fit('should run focused tests', function () {});
});

xdescribe('a pending suite with nested focused tests', function () {
it('should not run unfocused child tests', function () {
throw new RuntimeException();
});

fit('should mark focused child tests as pending', function () {
throw new RuntimeException();
});
});
});
28 changes: 24 additions & 4 deletions specs/context.spec.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,26 @@
assert($tests[1] === $sibling2, "sibling2 should have been added to parent");
});

it("should set pending if value is not null", function() {
it("should set pending if pending value is not null", function() {
$suite = $this->context->addSuite("desc", function() {}, true);
assert($suite->getPending(), "suite should be pending");
});

it("should ignore pending if value is null", function() {
it("should ignore pending if pending value is null", function() {
$suite = $this->context->addSuite("desc", function() {});
assert(is_null($suite->getPending()), "pending status should be null");
});

it("should set focused if focused value is supplied", function() {
$suite = $this->context->addSuite("desc", function() {}, null, true);
assert($suite->getFocused(), "suite should be focused");
});

it("should set focused to false if focused value is not supplied", function() {
$suite = $this->context->addSuite("desc", function() {});
assert(!$suite->getFocused(), "focused status should be false");
});

it("should execute a suites bound definition", function() {
$suite = $this->context->addSuite("desc", function() {
$this->value = "hello";
Expand All @@ -54,12 +64,12 @@
});

describe('->addTest()', function() {
it("should set pending status if value is not null", function() {
it("should set pending status if pending value is not null", function() {
$test = $this->context->addTest("is a spec", function() {}, true);
assert($test->getPending(), "pending status should be true");
});

it("should ignore pending status if value is null", function() {
it("should ignore pending status if pending value is null", function() {
$test = $this->context->addTest("is a spec", function() {});
assert(is_null($test->getPending()), "pending status should be null");
});
Expand All @@ -69,6 +79,16 @@
assert($test->getPending(), "pending status should be true");
});

it("should set focused status if focused value is supplied", function() {
$test = $this->context->addTest("is a spec", function() {}, null, true);
assert($test->getFocused(), "focused status should be true");
});

it("should set focused status if focused value is supplied", function() {
$test = $this->context->addTest("is a spec", function() {});
assert(!$test->getFocused(), "focused status should be false");
});

it('should increase size of root suite', function () {
$this->context->addTest('spec', function () { });
$suite = $this->context->getCurrentSuite();
Expand Down
64 changes: 64 additions & 0 deletions specs/suite.spec.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@
$this->eventEmitter = new EventEmitter();
});

context("when constructed with default parameters", function() {
it("it should default to an unfocused state", function() {
$suite = new Suite("Suite", function() {});
assert(!$suite->getFocused(), "suite should not be focused if focused value is not supplied");
});
});

describe('->run()', function() {
it("should run multiple tests", function () {
$suite = new Suite("Suite", function() {});
Expand Down Expand Up @@ -138,6 +145,23 @@

assert($result->getTestCount() == 2, "test count should be 2");
});

context('when there are focused tests', function() {
it("should run only the focused tests", function () {
$suite = new Suite("Suite", function() {});
$suite->addTest(new ItWasRun("should pass", function () {}, true));
$suite->addTest(new ItWasRun('should fail', function () {
throw new \Exception('woooooo!');
}, true));
$suite->addTest(new ItWasRun("should not be run", function () {}));
$suite->addTest(new ItWasRun("should also not be run", function () {}));

$result = new TestResult($this->eventEmitter);
$suite->setEventEmitter($this->eventEmitter);
$suite->run($result);
assert('2 run, 1 failed' == $result->getSummary(), "result summary should show 2/1");
});
});
});

describe("->addTest()", function() {
Expand Down Expand Up @@ -197,6 +221,46 @@
assert($this->arg === 1, 'should have set definition arguments');
});
});

describe('->getFocused()', function() {
context('when explicitly marked as focused', function () {
beforeEach(function() {
$this->suite = new Suite("test suite", function() {}, true);
});

it('should return true even if nested tests are not focused', function() {
$test = new Test("test", function() {});
$this->suite->addTest($test);
assert($this->suite->getFocused(), "suite should not be focused");
});
});

context('when not explicitly marked as focused', function () {
beforeEach(function() {
$this->suite = new Suite("test suite", function() {});
});

it('should return false if nested tests are not focused', function() {
$test = new Test("test", function() {});
$this->suite->addTest($test);
assert(!$this->suite->getFocused(), "suite should not be focused");
});

it('should return true if nested tests are focused', function() {
$test = new Test("test", function() {}, true);
$this->suite->addTest($test);
assert($this->suite->getFocused(), "suite should be focused");
});

it('should return true if nested suites are focused', function() {
$suite = new Suite("nested suite", function() {});
$test = new Test("test", function() {}, true);
$suite->addTest($test);
$this->suite->addTest($suite);
assert($this->suite->getFocused(), "suite should be focused");
});
});
});
});

class SuiteScope extends Scope
Expand Down
2 changes: 1 addition & 1 deletion specs/suiteloader.spec.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
describe('->getTests()', function() {
it("should return file paths matching *.spec.php recursively", function() {
$tests = $this->loader->getTests($this->fixtures);
assert(count($tests) == 4, "suite loader should have loaded 4 specs");
assert(count($tests) == 5, "suite loader should have loaded 5 specs");
});

it("should return single file if it exists", function() {
Expand Down
7 changes: 6 additions & 1 deletion specs/test.spec.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@

describe("Test", function() {

context("when constructed with null definition", function() {
context("when constructed with default parameters", function() {
it("it should default to a pending state", function() {
$test = new Test("it should be pending");
assert($test->getPending(), "test should be pending if definition is null");
});

it("it should default to an unfocused state", function() {
$test = new Test("it should not be focused");
assert(!$test->getFocused(), "test should not be focused if focused value is not supplied");
});
});

describe('->run()', function() {
Expand Down
9 changes: 8 additions & 1 deletion src/Core/AbstractTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ abstract class AbstractTest implements TestInterface
*/
protected $pending = null;

/**
* @var bool
*/
protected $focused;

/**
* @var Scope
*/
Expand All @@ -65,11 +70,13 @@ abstract class AbstractTest implements TestInterface
/**
* @param string $description
* @param callable $definition
* @param bool $focused
*/
public function __construct($description, callable $definition)
public function __construct($description, callable $definition, $focused = false)
{
$this->definition = $definition;
$this->description = $description;
$this->focused = $focused;
$this->scope = new Scope();
}

Expand Down
39 changes: 37 additions & 2 deletions src/Core/Suite.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ class Suite extends AbstractTest
*/
protected $halted = false;

/**
* {@inheritdoc}
*
* @return bool
*/
public function getFocused()
{
foreach ($this->tests as $test) {
if ($test->getFocused()) {
return true;
}
}

return $this->focused;
}

/**
* Add a test to the suite
*
Expand Down Expand Up @@ -74,14 +90,14 @@ public function run(TestResult $result)
$this->eventEmitter->emit('suite.start', [$this]);
$this->eventEmitter->on('suite.halt', [$this, 'halt']);

foreach ($this->tests as $test) {

foreach ($this->focusedTests() as $test) {
if ($this->halted) {
break;
}

$this->runTest($test, $result);
}

$this->eventEmitter->emit('suite.end', [$this]);
}

Expand Down Expand Up @@ -111,4 +127,23 @@ protected function runTest(TestInterface $test, TestResult $result)
$test->setEventEmitter($this->eventEmitter);
$test->run($result);
}

private function focusedTests()
{
$tests = [];
$hasFocusedTests = false;

foreach ($this->tests as $test) {
if ($test->getFocused()) {
$hasFocusedTests = true;
$tests[] = $test;
}
}

if ($hasFocusedTests) {
return $tests;
}

return $this->tests;
}
}
14 changes: 12 additions & 2 deletions src/Core/Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,25 @@ class Test extends AbstractTest
* @param string $description
* @param callable $definition
*/
public function __construct($description, callable $definition = null)
public function __construct($description, callable $definition = null, $focused = false)
{
if ($definition === null) {
$this->pending = true;
$definition = function () {
//noop
};
}
parent::__construct($description, $definition);
parent::__construct($description, $definition, $focused);
}

/**
* {@inheritdoc}
*
* @return bool
*/
public function getFocused()
{
return $this->focused;
}

/**
Expand Down
7 changes: 7 additions & 0 deletions src/Core/TestInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ public function getPending();
*/
public function setPending($state);

/**
* Return whether or not the test is focused
*
* @return bool
*/
public function getFocused();

/**
* Return scope for this test. Scope contains instance variables
* for a spec
Expand Down
Loading