Skip to content

Commit

Permalink
Merge pull request #291 from php-school/05-07-use_scenarios_in_exercises
Browse files Browse the repository at this point in the history
Use scenarios in exercises
  • Loading branch information
AydinHassan authored May 17, 2024
2 parents e8424d0 + 801f70f commit 6515c60
Show file tree
Hide file tree
Showing 11 changed files with 277 additions and 335 deletions.
3 changes: 0 additions & 3 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
parameters:
treatPhpDocTypesAsCertain: false
ignoreErrors:
-
message: '#PhpSchool\\PhpWorkshop\\ExerciseRunner\\CliRunner\:\:preserveOldArgFormat\(\) should return#'
path: src/ExerciseRunner/CliRunner.php
-
message: '#Call to an undefined method PhpParser\\Node\\Expr\|PhpParser\\Node\\Name\:\:__toString\(\)#'
path: src/Check/FunctionRequirementsCheck.php
Expand Down
14 changes: 10 additions & 4 deletions src/Exercise/CgiExercise.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace PhpSchool\PhpWorkshop\Exercise;

use PhpSchool\PhpWorkshop\Exercise\Scenario\CgiScenario;
use Psr\Http\Message\RequestInterface;

/**
Expand All @@ -12,10 +13,15 @@
interface CgiExercise extends ProvidesSolution
{
/**
* This method should return an array of PSR-7 requests, which will be forwarded to the student's
* solution.
* This method should return an instance of CgiScenario which contains PSR-7 requests,
* which will be forwarded to the student's solution.
*
* @return array<RequestInterface> An array of PSR-7 requests.
* Use like so:
*
* ```
* return (new CgiScenario())
* ->withExecution($request1)
* ```
*/
public function getRequests(): array;
public function defineTestScenario(): CgiScenario;
}
16 changes: 12 additions & 4 deletions src/Exercise/CliExercise.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,24 @@

namespace PhpSchool\PhpWorkshop\Exercise;

use PhpSchool\PhpWorkshop\Exercise\Scenario\CliScenario;

/**
* This interface describes the additional methods a CLI type exercise should implement.
*/
interface CliExercise extends ProvidesSolution
{
/**
* This method should return an array of an array of strings.
* Each set of arguments will be passed to the students solution as command line arguments.
* This method should return an instance of CliScenario which contains sets of arguments,
* which will be passed to the students solution as command line arguments.
*
* Use like so:
*
* @return array<array<string>> An array of string arguments.
* ```
* return (new CliScenario())
* ->withExecution(['arg1', 'arg2'])
* ->withExecution(['round2-arg1', 'round2-arg2'])
* ```
*/
public function getArgs(): array;
public function defineTestScenario(): CliScenario;
}
10 changes: 8 additions & 2 deletions src/ExerciseRunner/CgiRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,16 @@ public function getRequiredChecks(): array
*/
public function verify(Input $input): ResultInterface
{
$scenario = $this->exercise->defineTestScenario();

$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.verify.start', $this->exercise, $input));

$result = new CgiResult(
array_map(
function (RequestInterface $request) use ($input) {
return $this->doVerify($request, $input);
},
$this->exercise->getRequests()
$scenario->getExecutions()
)
);
$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.verify.finish', $this->exercise, $input));
Expand Down Expand Up @@ -283,9 +286,12 @@ private function getPhpProcess(string $workingDirectory, string $fileName, Reque
*/
public function run(Input $input, OutputInterface $output): bool
{
$scenario = $this->exercise->defineTestScenario();

$this->eventDispatcher->dispatch(new CgiExerciseRunnerEvent('cgi.run.start', $this->exercise, $input));

$success = true;
foreach ($this->exercise->getRequests() as $i => $request) {
foreach ($scenario->getExecutions() as $i => $request) {
/** @var CgiExecuteEvent $event */
$event = $this->eventDispatcher->dispatch(
new CgiExecuteEvent('cgi.run.student-execute.pre', $this->exercise, $input, $request)
Expand Down
39 changes: 12 additions & 27 deletions src/ExerciseRunner/CliRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,46 +101,28 @@ public function getRequiredChecks(): array
*/
public function verify(Input $input): ResultInterface
{
$scenario = $this->exercise->defineTestScenario();

$this->eventDispatcher->dispatch(new CliExerciseRunnerEvent('cli.verify.start', $this->exercise, $input));
$result = new CliResult(
array_map(
function (array $args) use ($input) {
return $this->doVerify($args, $input);
function (Collection $args) use ($input) {
return $this->doVerify($input, $args);
},
$this->preserveOldArgFormat($this->exercise->getArgs())
$scenario->getExecutions()
)
);
$this->eventDispatcher->dispatch(new CliExerciseRunnerEvent('cli.verify.finish', $this->exercise, $input));
return $result;
}

/**
* BC - getArgs only returned 1 set of args in v1 instead of multiple sets of args in v2
*
* @param array<int, array<string>>|array<int, string> $args
* @return array<int, array<string>>
*/
private function preserveOldArgFormat(array $args): array
{
if (isset($args[0]) && !is_array($args[0])) {
$args = [$args];
} elseif (count($args) === 0) {
$args = [[]];
}

return $args;
}

/**
* @param array<string> $args
* @param Input $input
* @param Collection<int, string> $args
* @return CliResultInterface
*/
private function doVerify(array $args, Input $input): CliResultInterface
private function doVerify(Input $input, Collection $args): CliResultInterface
{
//arrays are not pass-by-ref
$args = new ArrayObject($args);

try {
/** @var CliExecuteEvent $event */
$event = $this->eventDispatcher->dispatch(
Expand Down Expand Up @@ -213,12 +195,15 @@ private function doVerify(array $args, Input $input): CliResultInterface
*/
public function run(Input $input, OutputInterface $output): bool
{
$scenario = $this->exercise->defineTestScenario();

$this->eventDispatcher->dispatch(new CliExerciseRunnerEvent('cli.run.start', $this->exercise, $input));

$success = true;
foreach ($this->preserveOldArgFormat($this->exercise->getArgs()) as $i => $args) {
foreach ($scenario->getExecutions() as $i => $args) {
/** @var CliExecuteEvent $event */
$event = $this->eventDispatcher->dispatch(
new CliExecuteEvent('cli.run.student-execute.pre', $this->exercise, $input, new ArrayObject($args))
new CliExecuteEvent('cli.run.student-execute.pre', $this->exercise, $input, $args)
);

$args = $event->getArgs();
Expand Down
38 changes: 21 additions & 17 deletions test/Asset/CgiExerciseImpl.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@

namespace PhpSchool\PhpWorkshopTest\Asset;

use PhpSchool\PhpWorkshop\Check\FileComparisonCheck;
use PhpSchool\PhpWorkshop\Event\EventDispatcher;
use PhpSchool\PhpWorkshop\Exercise\CgiExercise;
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
use PhpSchool\PhpWorkshop\Exercise\Scenario\CgiScenario;
use PhpSchool\PhpWorkshop\ExerciseDispatcher;
use PhpSchool\PhpWorkshop\Solution\SolutionInterface;
use Psr\Http\Message\RequestInterface;

class CgiExerciseImpl implements ExerciseInterface, CgiExercise
{
/**
* @var string
*/
private $name;
private string $name;
private SolutionInterface $solution;
private CgiScenario $scenario;

public function __construct(string $name = 'my-exercise')
{
$this->name = $name;
$this->scenario = new CgiScenario();
}

public function getName(): string
Expand All @@ -33,9 +33,14 @@ public function getDescription(): string
return $this->name;
}

public function setSolution(SolutionInterface $solution): void
{
$this->solution = $solution;
}

public function getSolution(): SolutionInterface
{
// TODO: Implement getSolution() method.
return $this->solution;
}

public function getProblem(): string
Expand All @@ -48,17 +53,6 @@ public function tearDown(): void
// TODO: Implement tearDown() method.
}

/**
* This method should return an array of PSR-7 requests, which will be forwarded to the student's
* solution.
*
* @return RequestInterface[] An array of PSR-7 requests.
*/
public function getRequests(): array
{
return []; // TODO: Implement getRequests() method.
}

public function getType(): ExerciseType
{
return ExerciseType::CGI();
Expand All @@ -72,4 +66,14 @@ public function getRequiredChecks(): array
public function defineListeners(EventDispatcher $dispatcher): void
{
}

public function setScenario(CgiScenario $scenario): void
{
$this->scenario = $scenario;
}

public function defineTestScenario(): CgiScenario
{
return $this->scenario;
}
}
24 changes: 12 additions & 12 deletions test/Asset/CliExerciseImpl.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,25 @@

namespace PhpSchool\PhpWorkshopTest\Asset;

use PhpSchool\PhpWorkshop\Check\FileComparisonCheck;
use PhpSchool\PhpWorkshop\Event\EventDispatcher;
use PhpSchool\PhpWorkshop\Exercise\CliExercise;
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
use PhpSchool\PhpWorkshop\Exercise\ProvidesSolution;
use PhpSchool\PhpWorkshop\Exercise\Scenario\CliScenario;
use PhpSchool\PhpWorkshop\ExerciseDispatcher;
use PhpSchool\PhpWorkshop\Solution\SolutionInterface;

class CliExerciseImpl implements ExerciseInterface, CliExercise
{
/**
* @var string
*/
private $name;

/**
* @var SolutionInterface
*/
private $solution;
private string $name;
private SolutionInterface $solution;
private CliScenario $scenario;

public function __construct(string $name = 'my-exercise')
{
$this->name = $name;
$this->scenario = new CliScenario();
}

public function getName(): string
Expand Down Expand Up @@ -58,9 +53,14 @@ public function tearDown(): void
// TODO: Implement tearDown() method.
}

public function getArgs(): array
public function setScenario(CliScenario $scenario): void
{
$this->scenario = $scenario;
}

public function defineTestScenario(): CliScenario
{
return []; // TODO: Implement getArgs() method.
return $this->scenario;
}

public function getType(): ExerciseType
Expand Down
Loading

0 comments on commit 6515c60

Please sign in to comment.