Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b080d91

Browse files
Use scenarios in exercises
1 parent 1b6de18 commit b080d91

File tree

11 files changed

+104
-93
lines changed

11 files changed

+104
-93
lines changed

‎phpstan.neon‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
parameters:
22
treatPhpDocTypesAsCertain: false
33
ignoreErrors:
4-
-
5-
message: '#PhpSchool\\PhpWorkshop\\ExerciseRunner\\CliRunner\:\:preserveOldArgFormat\(\) should return#'
6-
path: src/ExerciseRunner/CliRunner.php
74
-
85
message: '#Call to an undefined method PhpParser\\Node\\Expr\|PhpParser\\Node\\Name\:\:__toString\(\)#'
96
path: src/Check/FunctionRequirementsCheck.php

‎src/Exercise/CgiExercise.php‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace PhpSchool\PhpWorkshop\Exercise;
66

7+
use PhpSchool\PhpWorkshop\Exercise\Scenario\CgiScenario;
78
use Psr\Http\Message\RequestInterface;
89

910
/**
@@ -12,10 +13,15 @@
1213
interface CgiExercise extends ProvidesSolution
1314
{
1415
/**
15-
* This method should return an array of PSR-7 requests, which will be forwarded to the student's
16-
* solution.
16+
* This method should return an instance of CgiScenario which contains PSR-7 requests,
17+
* which will be forwarded to the student's solution.
1718
*
18-
* @return array<RequestInterface> An array of PSR-7 requests.
19+
* Use like so:
20+
*
21+
* ```
22+
* return (new CgiScenario())
23+
* ->withExecution($request1)
24+
* ```
1925
*/
20-
public function getRequests(): array;
26+
public function defineTestScenario(): CgiScenario;
2127
}

‎src/Exercise/CliExercise.php‎

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,24 @@
44

55
namespace PhpSchool\PhpWorkshop\Exercise;
66

7+
use PhpSchool\PhpWorkshop\Exercise\Scenario\CliScenario;
8+
79
/**
810
* This interface describes the additional methods a CLI type exercise should implement.
911
*/
1012
interface CliExercise extends ProvidesSolution
1113
{
1214
/**
13-
* This method should return an array of an array of strings.
14-
* Each set of arguments will be passed to the students solution as command line arguments.
15+
* This method should return an instance of CliScenario which contains sets of arguments,
16+
* which will be passed to the students solution as command line arguments.
17+
*
18+
* Use like so:
1519
*
16-
* @return array<array<string>> An array of string arguments.
20+
* ```
21+
* return (new CliScenario())
22+
* ->withExecution(['arg1', 'arg2'])
23+
* ->withExecution(['round2-arg1', 'round2-arg2'])
24+
* ```
1725
*/
18-
public function getArgs(): array;
26+
public function defineTestScenario(): CliScenario;
1927
}

‎src/ExerciseRunner/CgiRunner.php‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,15 @@ public function getRequiredChecks(): array
105105
*/
106106
public function verify(ExecutionContext $context): ResultInterface
107107
{
108+
$scenario = $this->exercise->defineTestScenario();
109+
108110
$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.verify.start', $this->exercise, $context->getInput()));
109111
$result = new CgiResult(
110112
array_map(
111113
function (RequestInterface $request) use ($context) {
112114
return $this->doVerify($request, $context);
113115
},
114-
$this->exercise->getRequests()
116+
$scenario->getExecutions()
115117
)
116118
);
117119
$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.verify.finish', $this->exercise, $context->getInput()));
@@ -287,9 +289,11 @@ private function getPhpProcess(string $workingDirectory, string $fileName, Reque
287289
*/
288290
public function run(ExecutionContext $context, OutputInterface $output): bool
289291
{
292+
$scenario = $this->exercise->defineTestScenario();
293+
290294
$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.run.start', $this->exercise, $context->getInput()));
291295
$success = true;
292-
foreach ($this->exercise->getRequests() as $i => $request) {
296+
foreach ($scenario->getExecutions() as $i => $request) {
293297
/** @var CgiExecuteEvent $event */
294298
$event = $this->eventDispatcher->dispatch(
295299
new CgiExecuteEvent('cgi.run.student-execute.pre', $this->exercise, $context->getInput(), $request)

‎src/ExerciseRunner/CliRunner.php‎

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -102,43 +102,26 @@ public function getRequiredChecks(): array
102102
*/
103103
public function verify(ExecutionContext $context): ResultInterface
104104
{
105+
$scenario = $this->exercise->defineTestScenario();
106+
105107
$this->eventDispatcher->dispatch(new CliExerciseRunnerEvent('cli.verify.start', $this->exercise, $context->getInput()));
106108
$result = new CliResult(
107109
array_map(
108-
function (array $args) use ($context) {
110+
function (Collection $args) use ($context) {
109111
return $this->doVerify($context, $args);
110112
},
111-
$this->preserveOldArgFormat($this->exercise->getArgs())
113+
$scenario->getExecutions()
112114
)
113115
);
114116
$this->eventDispatcher->dispatch(new CliExerciseRunnerEvent('cli.verify.finish', $this->exercise, $context->getInput()));
115117
return $result;
116118
}
117119

118120
/**
119-
* BC - getArgs only returned 1 set of args in v1 instead of multiple sets of args in v2
120-
*
121-
* @param array<int, array<string>>|array<int, string> $args
122-
* @return array<int, array<string>>
123-
*/
124-
private function preserveOldArgFormat(array $args): array
125-
{
126-
if (isset($args[0]) && !is_array($args[0])) {
127-
$args = [$args];
128-
} elseif (count($args) === 0) {
129-
$args = [[]];
130-
}
131-
132-
return $args;
133-
}
134-
135-
/**
136-
* @param array<string> $args
121+
* @param Collection<int, string> $args
137122
*/
138-
private function doVerify(ExecutionContext $context, array $args): CliResultInterface
123+
private function doVerify(ExecutionContext $context, Collection $args): CliResultInterface
139124
{
140-
//arrays are not pass-by-ref
141-
$args = new ArrayObject($args);
142125

143126
try {
144127
/** @var CliExecuteEvent $event */
@@ -214,12 +197,14 @@ private function doVerify(ExecutionContext $context, array $args): CliResultInte
214197
*/
215198
public function run(ExecutionContext $context, OutputInterface $output): bool
216199
{
200+
$scenario = $this->exercise->defineTestScenario();
201+
217202
$this->eventDispatcher->dispatch(new CliExerciseRunnerEvent('cli.run.start', $this->exercise, $context->getInput()));
218203
$success = true;
219-
foreach ($this->preserveOldArgFormat($this->exercise->getArgs()) as $i => $args) {
204+
foreach ($scenario->getExecutions() as $i => $args) {
220205
/** @var CliExecuteEvent $event */
221206
$event = $this->eventDispatcher->dispatch(
222-
new CliExecuteEvent('cli.run.student-execute.pre', $this->exercise, $context->getInput(), newArrayObject($args))
207+
new CliExecuteEvent('cli.run.student-execute.pre', $this->exercise, $context->getInput(), $args)
223208
);
224209

225210
$args = $event->getArgs();

‎test/Asset/CgiExerciseImpl.php‎

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
use PhpSchool\PhpWorkshop\Exercise\CgiExercise;
88
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
99
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
10+
use PhpSchool\PhpWorkshop\Exercise\Scenario\CgiScenario;
11+
use PhpSchool\PhpWorkshop\Exercise\Scenario\CliScenario;
1012
use PhpSchool\PhpWorkshop\ExerciseDispatcher;
1113
use PhpSchool\PhpWorkshop\Solution\SolutionInterface;
1214
use Psr\Http\Message\RequestInterface;
@@ -15,12 +17,12 @@ class CgiExerciseImpl implements ExerciseInterface, CgiExercise
1517
{
1618
private string $name;
1719
private SolutionInterface $solution;
18-
/** @var array<RequestInterface> */
19-
private array $requests = [];
20+
private CgiScenario $scenario;
2021

2122
public function __construct(string $name = 'my-exercise')
2223
{
2324
$this->name = $name;
25+
$this->scenario = new CgiScenario();
2426
}
2527

2628
public function getName(): string
@@ -53,36 +55,27 @@ public function tearDown(): void
5355
// TODO: Implement tearDown() method.
5456
}
5557

56-
/**
57-
* @param array<RequestInterface> $requests
58-
*/
59-
public function setRequests(array $requests): void
58+
public function getType(): ExerciseType
6059
{
61-
$this->requests = $requests;
60+
return ExerciseType::CGI();
6261
}
6362

64-
/**
65-
* This method should return an array of PSR-7 requests, which will be forwarded to the student's
66-
* solution.
67-
*
68-
* @return array<RequestInterface> An array of PSR-7 requests.
69-
*/
70-
public function getRequests(): array
63+
public function getRequiredChecks(): array
7164
{
72-
return $this->requests;
65+
return [];
7366
}
7467

75-
public function getType(): ExerciseType
68+
public function defineListeners(EventDispatcher$dispatcher): void
7669
{
77-
return ExerciseType::CGI();
7870
}
7971

80-
public function getRequiredChecks(): array
72+
public function setScenario(CgiScenario$scenario): void
8173
{
82-
return [];
74+
$this->scenario = $scenario;
8375
}
8476

85-
public function defineListeners(EventDispatcher$dispatcher): void
77+
public function defineTestScenario(): CgiScenario
8678
{
79+
return $this->scenario;
8780
}
8881
}

‎test/Asset/CliExerciseImpl.php‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,20 @@
88
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
99
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
1010
use PhpSchool\PhpWorkshop\Exercise\ProvidesSolution;
11+
use PhpSchool\PhpWorkshop\Exercise\Scenario\CliScenario;
1112
use PhpSchool\PhpWorkshop\ExerciseDispatcher;
1213
use PhpSchool\PhpWorkshop\Solution\SolutionInterface;
1314

1415
class CliExerciseImpl implements ExerciseInterface, CliExercise
1516
{
1617
private string $name;
1718
private SolutionInterface $solution;
18-
private array$args = [[]];
19+
private CliScenario$scenario;
1920

2021
public function __construct(string $name = 'my-exercise')
2122
{
2223
$this->name = $name;
24+
$this->scenario = new CliScenario();
2325
}
2426

2527
public function getName(): string
@@ -52,14 +54,14 @@ public function tearDown(): void
5254
// TODO: Implement tearDown() method.
5355
}
5456

55-
public function setArgs(array$args): void
57+
public function setScenario(CliScenario$scenario): void
5658
{
57-
$this->args = $args;
59+
$this->scenario = $scenario;
5860
}
5961

60-
public function getArgs(): array
62+
public function defineTestScenario(): CliScenario
6163
{
62-
return $this->args;
64+
return $this->scenario;
6365
}
6466

6567
public function getType(): ExerciseType

‎test/Asset/DatabaseExercise.php‎

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PhpSchool\PhpWorkshop\Exercise\CliExercise;
99
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
1010
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
11+
use PhpSchool\PhpWorkshop\Exercise\Scenario\CliScenario;
1112
use PhpSchool\PhpWorkshop\ExerciseCheck\DatabaseExerciseCheck;
1213
use PhpSchool\PhpWorkshop\Solution\SolutionInterface;
1314

@@ -16,7 +17,12 @@ class DatabaseExercise implements ExerciseInterface, DatabaseExerciseCheck, CliE
1617
private SolutionInterface $solution;
1718
private ?\Closure $verifier = null;
1819
private ?\Closure $seeder = null;
19-
private array $args = [[]];
20+
private CliScenario $scenario;
21+
22+
public function __construct()
23+
{
24+
$this->scenario = new CliScenario();
25+
}
2026

2127
public function setSeeder(\Closure $seeder): void
2228
{
@@ -92,13 +98,13 @@ public function getSolution(): SolutionInterface
9298
return $this->solution;
9399
}
94100

95-
public function setArgs(array$args): void
101+
public function setScenario(CliScenario$scenario): void
96102
{
97-
$this->args = $args;
103+
$this->scenario = $scenario;
98104
}
99105

100-
public function getArgs(): array
106+
public function defineTestScenario(): CliScenario
101107
{
102-
return $this->args;
108+
return $this->scenario;
103109
}
104110
}

‎test/Check/DatabaseCheckTest.php‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use PhpSchool\PhpWorkshop\Event\EventDispatcher;
1010
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
1111
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
12+
use PhpSchool\PhpWorkshop\Exercise\Scenario\CliScenario;
1213
use PhpSchool\PhpWorkshop\ExerciseCheck\DatabaseExerciseCheck;
1314
use PhpSchool\PhpWorkshop\ExerciseDispatcher;
1415
use PhpSchool\PhpWorkshop\ExerciseRunner\CliRunner;
@@ -111,8 +112,7 @@ public function testIfPDOThrowsExceptionItCleansUp(): void
111112
$this->check = new DatabaseCheck();
112113
$solution = SingleFileSolution::fromFile(realpath(__DIR__ . '/../res/database/solution.php'));
113114
$this->exercise->setSolution($solution);
114-
115-
$this->exercise->setArgs([[1, 2, 3]]);
115+
$this->exercise->setScenario((new CliScenario())->withExecution([1, 2, 3]));
116116
$this->exercise->setVerifier(fn () => true);
117117

118118
$this->checkRepository->registerCheck($this->check);
@@ -139,7 +139,7 @@ public function testSuccessIsReturnedIfDatabaseVerificationPassed(): void
139139
{
140140
$solution = SingleFileSolution::fromFile(realpath(__DIR__ . '/../res/database/solution.php'));
141141
$this->exercise->setSolution($solution);
142-
$this->exercise->setArgs([[1, 2, 3]]);
142+
$this->exercise->setScenario((newCliScenario())->withExecution([1, 2, 3]));
143143

144144
$this->exercise->setVerifier(fn () => true);
145145
$this->checkRepository->registerCheck($this->check);
@@ -191,7 +191,7 @@ public function testFailureIsReturnedIfDatabaseVerificationFails(): void
191191
{
192192
$solution = SingleFileSolution::fromFile(realpath(__DIR__ . '/../res/database/solution.php'));
193193
$this->exercise->setSolution($solution);
194-
$this->exercise->setArgs([[1, 2, 3]]);
194+
$this->exercise->setScenario((newCliScenario())->withExecution([1, 2, 3]));
195195
$this->exercise->setVerifier(fn () => false);
196196

197197
$this->checkRepository->registerCheck($this->check);
@@ -221,6 +221,7 @@ public function testAlteringDatabaseInSolutionDoesNotEffectDatabaseInUserSolutio
221221
{
222222
$solution = SingleFileSolution::fromFile(realpath(__DIR__ . '/../res/database/solution-alter-db.php'));
223223
$this->exercise->setSolution($solution);
224+
$this->exercise->setScenario((new CliScenario())->withExecution());
224225

225226
$this->exercise->setVerifier(function (PDO $db) {
226227
$users = $db->query('SELECT * FROM users');

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /