Permalink
Browse files

implemented working proof of concept

  • Loading branch information...
1 parent 5dd266e commit e1a0bb2ba9a186bd0e0a88816fa1f10101932bf9 @everzet everzet committed Jul 7, 2012
View
@@ -0,0 +1,4 @@
+guard 'ctags-composer', :src_path => ["src"], :vendor_path => ["vendor"] do
+ watch(/^(src|tests)\/.*\.php$/)
+ watch('composer.lock')
+end
View
@@ -18,21 +18,17 @@
],
"require": {
- "php": ">=5.3.1",
- "symfony/console": ">=2.0.0,<2.2.0-dev",
- "symfony/event-dispatcher": ">=2.0.0,<2.2.0-dev",
- "symfony/finder": ">=2.0.0,<2.2.0-dev"
- },
-
- "require-dev": {
- "symfony/console": "@stable",
- "symfony/event-dispatcher": "@stable",
- "symfony/finder": "@stable"
+ "php": ">=5.3.1",
+ "symfony/console": ">=2.0.0,<2.2.0",
+ "symfony/event-dispatcher": ">=2.0.0,<2.2.0",
+ "symfony/finder": ">=2.0.0,<2.2.0",
+ "mockery/mockery": "0.7.*"
},
"autoload": {
"psr-0": {
- "PHPSpec\\PHPSpec2": "src/"
+ "PHPSpec\\PHPSpec2": "src/",
+ "Spec": "specs/"
}
},
@@ -0,0 +1,31 @@
+<?php
+
+namespace Spec\PHPSpec\PHPSpec2;
+
+use PHPSpec\PHPSpec2\SpecificationInterface;
+
+class Stub implements SpecificationInterface
+{
+ public function described_with($stub)
+ {
+ $stub->isAnInstanceOf('PHPSpec\PHPSpec2\Stub');
+ }
+
+ public function registers_matcher_if_it_has_aliases($stub, $matcher)
+ {
+ $matcher->isAMockOf('PHPSpec\PHPSpec2\Matcher\MatcherInterface');
+ $matcher->getAliases()->should_return(array('should_be_equal'));
+
+ $stub->__registerMatcher($matcher);
+ $stub->__getMatchers()->should_contain(1);
+ }
+
+ public function does_not_registers_matcher_if_it_has_no_aliases($stub, $matcher)
+ {
+ $matcher->isAMockOf('PHPSpec\PHPSpec2\Matcher\MatcherInterface');
+ $matcher->getAliases()->should_return(array());
+
+ $stub->__registerMatcher($matcher);
+ $stub->__getMatchers()->should_contain(0);
+ }
+}
@@ -6,6 +6,16 @@
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Finder\Finder;
+use Symfony\Component\Finder\SplFileInfo;
+
+use ReflectionClass;
+use ReflectionMethod;
+
+use PHPSpec\PHPSpec2\Stub;
+use PHPSpec\PHPSpec2\Matcher;
+use PHPSpec\PHPSpec2\SpecificationInterface;
+
class TestCommand extends Command
{
/**
@@ -23,5 +33,92 @@ public function __construct()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
+ $specsPath = realpath('specs');
+
+ $finder = Finder::create();
+ $files = $finder
+ ->files()
+ ->name('*.php')
+ ->in($specsPath)
+ ;
+
+ foreach ($files as $file) {
+ if (!$spec = $this->getSpecReflectionFromFile($file, $specsPath)) {
+ continue;
+ }
+
+ foreach ($spec->getMethods(ReflectionMethod::IS_PUBLIC) as $specMethod) {
+ $specInstance = $spec->newInstance();
+ $stubs = array();
+ foreach (array('describedWith', 'described_with') as $describer) {
+ // describing methods are not specs
+ if ($describer === $specMethod->getName()) {
+ continue 2;
+ }
+
+ // call describing method
+ if ($spec->hasMethod($describer)) {
+ $method = $spec->getMethod($describer);
+ $stubs = $this->getStubsForMethod($method, $stubs);
+ $this->callMethodWithStubs($specInstance, $method, $stubs);
+ }
+ }
+
+ $stubs = $this->getStubsForMethod($specMethod, $stubs);
+ $this->callMethodWithStubs($specInstance, $specMethod, $stubs);
+ }
+ }
+ }
+
+ private function createNewStub($subject = null)
+ {
+ $stub = new Stub($subject);
+ $stub->registerMatcher(new Matcher\ShouldReturnMatcher);
+ $stub->registerMatcher(new Matcher\ShouldContainMatcher);
+
+ return $stub;
+ }
+
+ private function getStubsForMethod(ReflectionMethod $method, array $stubs)
+ {
+ foreach ($method->getParameters() as $parameter) {
+ if (!isset($stubs[$parameter->getName()])) {
+ $stubs[$parameter->getName()] = $this->createNewStub();
+ }
+ }
+
+ return $stubs;
+ }
+
+ private function callMethodWithStubs(SpecificationInterface $spec, ReflectionMethod $method, array $stubs)
+ {
+ $arguments = array();
+ foreach ($method->getParameters() as $parameter) {
+ $arguments[] = $stubs[$parameter->getName()];
+ }
+
+ $method->invokeArgs($spec, $arguments);
+ }
+
+ private function getSpecReflectionFromFile(SplFileInfo $file, $specsPath)
+ {
+ $filename = realpath($file->getPathname());
+ $classname = str_replace(DIRECTORY_SEPARATOR, '\\',
+ str_replace(
+ $specsPath.DIRECTORY_SEPARATOR, '',
+ str_replace('.'.$file->getExtension(), '', $filename)
+ )
+ );
+
+ if (!class_exists($classname)) {
+ return;
+ }
+
+ $reflection = new ReflectionClass($classname);
+ if (!$reflection->implementsInterface('PHPSpec\\PHPSpec2\\SpecificationInterface')) {
+ return;
+ }
+
+ return $reflection;
}
}
@@ -0,0 +1,7 @@
+<?php
+
+namespace PHPSpec\PHPSpec2\Exception;
+
+class ClassDoesNotExistsException extends StubException
+{
+}
@@ -0,0 +1,7 @@
+<?php
+
+namespace PHPSpec\PHPSpec2\Exception;
+
+class Exception extends \Exception
+{
+}
@@ -0,0 +1,9 @@
+<?php
+
+namespace PHPSpec\PHPSpec2\Exception\Matcher;
+
+use PHPSpec\PHPSpec2\Exception\Exception;
+
+class MatcherException extends Exception
+{
+}
@@ -0,0 +1,7 @@
+<?php
+
+namespace PHPSpec\PHPSpec2\Exception;
+
+class MethodNotFoundException extends StubException
+{
+}
@@ -0,0 +1,7 @@
+<?php
+
+namespace PHPSpec\PHPSpec2\Exception;
+
+class PropertyNotFoundException extends StubException
+{
+}
@@ -0,0 +1,7 @@
+<?php
+
+namespace PHPSpec\PHPSpec2\Exception;
+
+class StubException extends Exception
+{
+}
@@ -0,0 +1,11 @@
+<?php
+
+namespace PHPSpec\PHPSpec2\Matcher;
+
+use PHPSpec\PHPSpec2\Stub;
+
+interface MatcherInterface
+{
+ public function getAliases();
+ public function match(Stub $stub, array $arguments);
+}
@@ -0,0 +1,26 @@
+<?php
+
+namespace PHPSpec\PHPSpec2\Matcher;
+
+use PHPSpec\PHPSpec2\Stub;
+use PHPSpec\PHPSpec2\Exception\Matcher\MatcherException;
+
+class ShouldContainMatcher implements MatcherInterface
+{
+ public function getAliases()
+ {
+ return array('should_contain', 'shouldContain', 'contains');
+ }
+
+ public function match(Stub $stub, array $arguments)
+ {
+ if ($arguments[0] !== count($stub->getSubject())) {
+ throw new MatcherException(sprintf(
+ 'Expected to have %d items in %s, got %d',
+ $arguments[0],
+ gettype($stub->getSubject()),
+ count($stub->getSubject())
+ ));
+ }
+ }
+}
@@ -0,0 +1,21 @@
+<?php
+
+namespace PHPSpec\PHPSpec2\Matcher;
+
+use PHPSpec\PHPSpec2\Stub;
+
+class ShouldReturnMatcher implements MatcherInterface
+{
+ public function getAliases()
+ {
+ return array('should_return', 'shouldReturn', 'returns');
+ }
+
+ public function match(Stub $stub, array $arguments)
+ {
+ return new Stub(
+ $stub->getSubject()->andReturn($arguments[0]),
+ $stub->getMatchers()
+ );
+ }
+}
@@ -0,0 +1,7 @@
+<?php
+
+namespace PHPSpec\PHPSpec2;
+
+interface SpecificationInterface
+{
+}
Oops, something went wrong.

0 comments on commit e1a0bb2

Please sign in to comment.