Skip to content

Commit 5ad9aba

Browse files
committed
Get tests running
1 parent 48ad656 commit 5ad9aba

15 files changed

+292
-191
lines changed

src/Exception/InvalidArgumentException.php

+17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22

33
namespace PhpSchool\PhpWorkshop\Exception;
4+
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
45

56
/**
67
* Represents invalid argument exceptions.
@@ -48,6 +49,22 @@ public static function notValidParameter($parameterName, array $allowedValues, $
4849
);
4950
}
5051

52+
/**
53+
* @param object $object
54+
* @param string $requiredInterface
55+
* @return static
56+
*/
57+
public static function missingImplements($object, $requiredInterface)
58+
{
59+
return new static(
60+
sprintf(
61+
'"%s" is required to implement "%s", but it does not',
62+
get_class($object),
63+
$requiredInterface
64+
)
65+
);
66+
}
67+
5168
/**
5269
* @param $value
5370
* @return string

src/Exercise/ExerciseType.php

+25-4
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,43 @@
33
namespace PhpSchool\PhpWorkshop\Exercise;
44

55
use MyCLabs\Enum\Enum;
6-
use PhpSchool\PhpWorkshop\ExerciseRunner\CgiRunner;
7-
use PhpSchool\PhpWorkshop\ExerciseRunner\CliRunner;
86

97
/**
108
* This class is a ENUM which represents the types that exercises can be. Instantiation looks like:
119
*
1210
* ```php
1311
* $typeCli = ExerciseType::CLI();
1412
* $typeCgi = ExerciseType::CGI();
13+
* $typeCustom = ExerciseType::CUSTOM();
1514
* ```
1615
*
1716
* @package PhpSchool\PhpWorkshop\Exercise
1817
* @author Aydin Hassan <[email protected]>
1918
*/
2019
class ExerciseType extends Enum
2120
{
22-
const CLI = CliRunner::class;
23-
const CGI = CgiRunner::class;
21+
const CLI = 'CLI';
22+
const CGI = 'CGI';
23+
24+
/**
25+
* Map of exercise types to the required interfaces exercises of that particular
26+
* type should implement.
27+
*
28+
* @var array
29+
*/
30+
private static $exerciseTypeToExerciseInterfaceMap = [
31+
self::CLI => CliExercise::class,
32+
self::CGI => CgiExercise::class,
33+
];
34+
35+
/**
36+
* Get the FQCN of the interface this exercise should implement for this
37+
* exercise type.
38+
*
39+
* @return string
40+
*/
41+
public function getExerciseInterface()
42+
{
43+
return static::$exerciseTypeToExerciseInterfaceMap[$this->getKey()];
44+
}
2445
}

src/ExerciseRepository.php

+20-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use ArrayIterator;
66
use Countable;
7-
use InvalidArgumentException;
7+
use PhpSchool\PhpWorkshop\Exception\InvalidArgumentException;
88
use IteratorAggregate;
99
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
1010

@@ -28,12 +28,28 @@ class ExerciseRepository implements IteratorAggregate, Countable
2828
*/
2929
public function __construct(array $exercises)
3030
{
31-
//type safety
32-
$this->exercises = array_map(function (ExerciseInterface $e) {
33-
return $e;
31+
$this->exercises = array_map(function (ExerciseInterface $exercise) {
32+
return $this->validateExercise($exercise);
3433
}, $exercises);
3534
}
3635

36+
/**
37+
* @param ExerciseInterface $exercise
38+
* @return ExerciseInterface
39+
*/
40+
private function validateExercise(ExerciseInterface $exercise)
41+
{
42+
$type = $exercise->getType();
43+
44+
$requiredInterface = $type->getExerciseInterface();
45+
46+
if (!$exercise instanceof $requiredInterface) {
47+
throw InvalidArgumentException::missingImplements($exercise, $requiredInterface);
48+
}
49+
50+
return $exercise;
51+
}
52+
3753
/**
3854
* Retrieve all of the exercises as an array.
3955
*

src/ExerciseRunner/RunnerManager.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public function configureInput(ExerciseInterface $exercise, CommandDefinition $c
4141
*/
4242
public function getRunner(ExerciseInterface $exercise)
4343
{
44-
return $this->getFactory($exercise)->create($exercise, $this->container);
44+
return $this->getFactory($exercise)->create($exercise);
4545
}
4646

4747
/**

test/Asset/CliExerciseImpl.php

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?php
2+
3+
namespace PhpSchool\PhpWorkshopTest\Asset;
4+
5+
use PhpSchool\PhpWorkshop\Check\ComposerCheck;
6+
use PhpSchool\PhpWorkshop\Exercise\CliExercise;
7+
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
8+
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
9+
use PhpSchool\PhpWorkshop\ExerciseCheck\ComposerExerciseCheck;
10+
use PhpSchool\PhpWorkshop\ExerciseDispatcher;
11+
12+
/**
13+
* @package PhpSchool\PhpWorkshopTest\Asset
14+
* @author Aydin Hassan <[email protected]>
15+
*/
16+
class CliExerciseImpl implements ExerciseInterface, CliExercise
17+
{
18+
19+
/**
20+
* @return string
21+
*/
22+
public function getName()
23+
{
24+
return 'my-exercise';
25+
}
26+
27+
/**
28+
* @return string
29+
*/
30+
public function getDescription()
31+
{
32+
return 'my-exercise';
33+
}
34+
35+
/**
36+
* @return string
37+
*/
38+
public function getSolution()
39+
{
40+
// TODO: Implement getSolution() method.
41+
}
42+
43+
/**
44+
* @return string
45+
*/
46+
public function getProblem()
47+
{
48+
// TODO: Implement getProblem() method.
49+
}
50+
51+
/**
52+
* @return void
53+
*/
54+
public function tearDown()
55+
{
56+
// TODO: Implement tearDown() method.
57+
}
58+
59+
/**
60+
* @return array
61+
*/
62+
public function getArgs()
63+
{
64+
// TODO: Implement getArgs() method.
65+
}
66+
67+
/**
68+
* @return ExerciseType
69+
*/
70+
public function getType()
71+
{
72+
return ExerciseType::CLI();
73+
}
74+
75+
/**
76+
* @param ExerciseDispatcher $dispatcher
77+
*/
78+
public function configure(ExerciseDispatcher $dispatcher)
79+
{
80+
$dispatcher->requireCheck(ComposerCheck::class);
81+
}
82+
}

test/Asset/ComposerExercise.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class ComposerExercise implements ExerciseInterface, ComposerExerciseCheck
2121
*/
2222
public function getName()
2323
{
24-
// TODO: Implement getName() method.
24+
return 'composer-exercise';
2525
}
2626

2727
/**

test/Check/DatabaseCheckTest.php

+20-12
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
use PhpSchool\PhpWorkshop\ExerciseCheck\DatabaseExerciseCheck;
1515
use PhpSchool\PhpWorkshop\ExerciseDispatcher;
1616
use PhpSchool\PhpWorkshop\ExerciseRunner\CliRunner;
17-
use PhpSchool\PhpWorkshop\Factory\RunnerFactory;
17+
use PhpSchool\PhpWorkshop\ExerciseRunner\RunnerManager;
1818
use PhpSchool\PhpWorkshop\Input\Input;
1919
use PhpSchool\PhpWorkshop\Output\OutputInterface;
2020
use PhpSchool\PhpWorkshop\ResultAggregator;
@@ -61,6 +61,7 @@ public function setUp()
6161

6262
$this->check = new DatabaseCheck;
6363
$this->exercise = $this->createMock(DatabaseExerciseInterface::class);
64+
$this->exercise->expects($this->any())->method('getType')->willReturn(ExerciseType::CLI());
6465
$this->dbDir = sprintf(
6566
'%s/PhpSchool_PhpWorkshop_Check_DatabaseCheck',
6667
str_replace('\\', '/', realpath(sys_get_temp_dir()))
@@ -75,20 +76,25 @@ public function setUp()
7576
* @param EventDispatcher $eventDispatcher
7677
* @return \PHPUnit_Framework_MockObject_MockObject
7778
*/
78-
private function getRunnerFactory(ExerciseInterface $exercise, EventDispatcher $eventDispatcher)
79+
private function getRunnerManager(ExerciseInterface $exercise, EventDispatcher $eventDispatcher)
7980
{
8081
$runner = $this->getMockBuilder(CliRunner::class)
8182
->setConstructorArgs([$exercise, $eventDispatcher])
82-
->setMethods(['configure'])
83+
->setMethods(['configure', 'getRequiredChecks'])
8384
->getMock();
8485

85-
$runnerFactory = $this->createMock(RunnerFactory::class);
86-
$runnerFactory
86+
$runner
87+
->expects($this->any())
88+
->method('getRequiredChecks')
89+
->willReturn([]);
90+
91+
$runnerManager = $this->createMock(RunnerManager::class);
92+
$runnerManager
8793
->expects($this->once())
88-
->method('create')
94+
->method('getRunner')
8995
->willReturn($runner);
9096

91-
return $runnerFactory;
97+
return $runnerManager;
9298
}
9399

94100
public function testIfDatabaseFolderExistsExceptionIsThrown()
@@ -153,7 +159,7 @@ public function testIfPDOThrowsExceptionItCleansUp()
153159
$results = new ResultAggregator;
154160
$eventDispatcher = new EventDispatcher($results);
155161
$dispatcher = new ExerciseDispatcher(
156-
$this->getRunnerFactory($this->exercise, $eventDispatcher),
162+
$this->getRunnerManager($this->exercise, $eventDispatcher),
157163
$results,
158164
$eventDispatcher,
159165
$this->checkRepository
@@ -194,7 +200,7 @@ public function testSuccessIsReturnedIfDatabaseVerificationPassed()
194200
$results = new ResultAggregator;
195201
$eventDispatcher = new EventDispatcher($results);
196202
$dispatcher = new ExerciseDispatcher(
197-
$this->getRunnerFactory($this->exercise, $eventDispatcher),
203+
$this->getRunnerManager($this->exercise, $eventDispatcher),
198204
$results,
199205
$eventDispatcher,
200206
$this->checkRepository
@@ -225,7 +231,7 @@ public function testRunExercise()
225231
$results = new ResultAggregator;
226232
$eventDispatcher = new EventDispatcher($results);
227233
$dispatcher = new ExerciseDispatcher(
228-
$this->getRunnerFactory($this->exercise, $eventDispatcher),
234+
$this->getRunnerManager($this->exercise, $eventDispatcher),
229235
$results,
230236
$eventDispatcher,
231237
$this->checkRepository
@@ -241,6 +247,8 @@ public function testRunExercise()
241247
public function testFailureIsReturnedIfDatabaseVerificationFails()
242248
{
243249
$solution = SingleFileSolution::fromFile(realpath(__DIR__ . '/../res/database/solution.php'));
250+
251+
244252
$this->exercise
245253
->expects($this->once())
246254
->method('getSolution')
@@ -269,7 +277,7 @@ public function testFailureIsReturnedIfDatabaseVerificationFails()
269277
$results = new ResultAggregator;
270278
$eventDispatcher = new EventDispatcher($results);
271279
$dispatcher = new ExerciseDispatcher(
272-
$this->getRunnerFactory($this->exercise, $eventDispatcher),
280+
$this->getRunnerManager($this->exercise, $eventDispatcher),
273281
$results,
274282
$eventDispatcher,
275283
$this->checkRepository
@@ -337,7 +345,7 @@ public function testAlteringDatabaseInSolutionDoesNotEffectDatabaseInUserSolutio
337345
$results = new ResultAggregator;
338346
$eventDispatcher = new EventDispatcher($results);
339347
$dispatcher = new ExerciseDispatcher(
340-
$this->getRunnerFactory($this->exercise, $eventDispatcher),
348+
$this->getRunnerManager($this->exercise, $eventDispatcher),
341349
$results,
342350
$eventDispatcher,
343351
$this->checkRepository

test/Command/PrintCommandTest.php

+9-12
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
namespace PhpSchool\PhpWorkshop\Command;
44

55
use Colors\Color;
6+
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
7+
use PhpSchool\PhpWorkshopTest\Asset\CliExerciseInterface;
8+
use PhpSchool\PhpWorkshopTest\Asset\ComposerExercise;
69
use PHPUnit_Framework_TestCase;
710
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
811
use PhpSchool\PhpWorkshop\ExerciseRepository;
@@ -22,21 +25,15 @@ public function testExerciseIsPrintedIfAssigned()
2225
$file = tempnam(sys_get_temp_dir(), 'pws');
2326
file_put_contents($file, '### Exercise 1');
2427

25-
$exercise = $this->createMock(ExerciseInterface::class);
26-
$exercise
27-
->expects($this->once())
28-
->method('getProblem')
29-
->will($this->returnValue($file));
30-
31-
$exercise
32-
->expects($this->once())
33-
->method('getName')
34-
->will($this->returnValue('current-exercise'));
28+
$exercise = $this->prophesize(CliExerciseInterface::class);
29+
$exercise->getProblem()->willReturn($file);
30+
$exercise->getType()->willReturn(ExerciseType::CLI());
31+
$exercise->getName()->willReturn('some-exercise');
3532

36-
$repo = new ExerciseRepository([$exercise]);
33+
$repo = new ExerciseRepository([$exercise->reveal()]);
3734

3835
$state = new UserState;
39-
$state->setCurrentExercise('current-exercise');
36+
$state->setCurrentExercise('some-exercise');
4037

4138
$output = $this->createMock(OutputInterface::class);
4239
$renderer = $this->createMock(MarkdownRenderer::class);

0 commit comments

Comments
 (0)