Skip to content

Commit a71b599

Browse files
committed
File comparison check
1 parent d32554e commit a71b599

File tree

3 files changed

+182
-9
lines changed

3 files changed

+182
-9
lines changed

src/Check/FileComparisonCheck.php

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@
55
namespace PhpSchool\PhpWorkshop\Check;
66

77
use InvalidArgumentException;
8-
use PhpSchool\PhpWorkshop\Exception\RuntimeException;
8+
use PhpSchool\PhpWorkshop\Exception\SolutionFileDoesNotExistException;
99
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
1010
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
1111
use PhpSchool\PhpWorkshop\Exercise\ProvidesSolution;
1212
use PhpSchool\PhpWorkshop\ExerciseCheck\FileComparisonExerciseCheck;
13-
use PhpSchool\PhpWorkshop\ExerciseCheck\FunctionRequirementsExerciseCheck;
1413
use PhpSchool\PhpWorkshop\Input\Input;
1514
use PhpSchool\PhpWorkshop\Result\Failure;
1615
use PhpSchool\PhpWorkshop\Result\FileComparisonFailure;
1716
use PhpSchool\PhpWorkshop\Result\ResultInterface;
1817
use PhpSchool\PhpWorkshop\Result\Success;
18+
use PhpSchool\PhpWorkshop\Utils\Path;
1919

2020
/**
2121
* This check verifies that any additional files which should be created by a student, match the ones
@@ -45,18 +45,15 @@ public function check(ExerciseInterface $exercise, Input $input): ResultInterfac
4545
}
4646

4747
foreach ($exercise->getFilesToCompare() as $file) {
48-
$studentFile = dirname($input->getRequiredArgument('program')) . '/' . ltrim($file, '/');
49-
$referenceFile = $exercise->getSolution()->getBaseDirectory() . '/' . ltrim($file, '/');
48+
$studentFile = Path::join(dirname($input->getRequiredArgument('program')), $file);
49+
$referenceFile = Path::join($exercise->getSolution()->getBaseDirectory(), $file);
5050

5151
if (!file_exists($referenceFile)) {
52-
throw new RuntimeException(sprintf('File: "%s" does not exist in solution folder', $file));
52+
throw SolutionFileDoesNotExistException::fromExpectedFile($file);
5353
}
5454

5555
if (!file_exists($studentFile)) {
56-
return Failure::fromCheckAndReason(
57-
$this,
58-
sprintf('File: "%s" does not exist', $file)
59-
);
56+
return Failure::fromCheckAndReason($this, sprintf('File: "%s" does not exist', $file));
6057
}
6158

6259
$actual = (string) file_get_contents($studentFile);

test/Asset/FileComparisonExercise.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
namespace PhpSchool\PhpWorkshopTest\Asset;
4+
5+
use PhpSchool\PhpWorkshop\Check\ComposerCheck;
6+
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
7+
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
8+
use PhpSchool\PhpWorkshop\ExerciseCheck\FileComparisonExerciseCheck;
9+
use PhpSchool\PhpWorkshop\ExerciseDispatcher;
10+
use PhpSchool\PhpWorkshop\Solution\SolutionInterface;
11+
12+
class FileComparisonExercise implements ExerciseInterface, FileComparisonExerciseCheck
13+
{
14+
/**
15+
* @var array<string>
16+
*/
17+
private $files;
18+
19+
/**
20+
* @var SolutionInterface
21+
*/
22+
private $solution;
23+
24+
public function __construct(array $files)
25+
{
26+
$this->files = $files;
27+
}
28+
29+
public function getName(): string
30+
{
31+
// TODO: Implement getName() method.
32+
}
33+
34+
public function getDescription(): string
35+
{
36+
// TODO: Implement getDescription() method.
37+
}
38+
39+
public function setSolution(SolutionInterface $solution): void
40+
{
41+
$this->solution = $solution;
42+
}
43+
44+
public function getSolution(): SolutionInterface
45+
{
46+
return $this->solution;
47+
}
48+
49+
public function getProblem(): string
50+
{
51+
// TODO: Implement getProblem() method.
52+
}
53+
54+
public function tearDown(): void
55+
{
56+
// TODO: Implement tearDown() method.
57+
}
58+
59+
public function getArgs(): array
60+
{
61+
return []; // TODO: Implement getArgs() method.
62+
}
63+
64+
public function getType(): ExerciseType
65+
{
66+
return ExerciseType::CLI();
67+
}
68+
69+
public function configure(ExerciseDispatcher $dispatcher): void
70+
{
71+
$dispatcher->requireCheck(ComposerCheck::class);
72+
}
73+
74+
public function getFilesToCompare(): array
75+
{
76+
return $this->files;
77+
}
78+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
3+
namespace PhpSchool\PhpWorkshopTest\Check;
4+
5+
use PhpSchool\PhpWorkshop\Check\FileComparisonCheck;
6+
use PhpSchool\PhpWorkshop\Check\SimpleCheckInterface;
7+
use PhpSchool\PhpWorkshop\Exception\SolutionFileDoesNotExistException;
8+
use PhpSchool\PhpWorkshop\Exercise\ExerciseType;
9+
use PhpSchool\PhpWorkshop\ExerciseCheck\FileComparisonExerciseCheck;
10+
use PhpSchool\PhpWorkshop\Input\Input;
11+
use PhpSchool\PhpWorkshop\Result\FileComparisonFailure;
12+
use PhpSchool\PhpWorkshop\Solution\SingleFileSolution;
13+
use PhpSchool\PhpWorkshopTest\Asset\FileComparisonExercise;
14+
use PhpSchool\PhpWorkshopTest\BaseTest;
15+
use PhpSchool\PhpWorkshop\Result\Failure;
16+
use PhpSchool\PhpWorkshop\Result\Success;
17+
18+
class FileComparisonCheckTest extends BaseTest
19+
{
20+
/**
21+
* @var FileComparisonCheck
22+
*/
23+
private $check;
24+
25+
public function setUp(): void
26+
{
27+
$this->check = new FileComparisonCheck();
28+
$this->assertEquals('File Comparison Check', $this->check->getName());
29+
$this->assertEquals(FileComparisonExerciseCheck::class, $this->check->getExerciseInterface());
30+
$this->assertEquals(SimpleCheckInterface::CHECK_AFTER, $this->check->getPosition());
31+
32+
$this->assertTrue($this->check->canRun(ExerciseType::CGI()));
33+
$this->assertTrue($this->check->canRun(ExerciseType::CLI()));
34+
}
35+
36+
public function testExceptionIsThrownIfReferenceFileDoesNotExist(): void
37+
{
38+
$this->expectException(SolutionFileDoesNotExistException::class);
39+
$this->expectExceptionMessage('File: "some-file.txt" does not exist in solution folder');
40+
41+
$exercise = new FileComparisonExercise(['some-file.txt']);
42+
$exercise->setSolution(new SingleFileSolution($this->getTemporaryFile('solution/solution.php')));
43+
44+
$this->check->check($exercise, new Input('app', ['program' => 'my-solution.php']));
45+
}
46+
47+
public function testFailureIsReturnedIfStudentsFileDoesNotExist(): void
48+
{
49+
$file = $this->getTemporaryFile('solution/some-file.txt');
50+
file_put_contents($file, "name,age\nAydin,33\nMichael,29\n");
51+
52+
$exercise = new FileComparisonExercise(['some-file.txt']);
53+
$exercise->setSolution(new SingleFileSolution($this->getTemporaryFile('solution/solution.php')));
54+
55+
$failure = $this->check->check($exercise, new Input('app', ['program' => 'my-solution.php']));
56+
57+
$this->assertInstanceOf(Failure::class, $failure);
58+
$this->assertEquals('File: "some-file.txt" does not exist', $failure->getReason());
59+
}
60+
61+
public function testFailureIsReturnedIfStudentFileDosNotMatchReferenceFile(): void
62+
{
63+
$file = $this->getTemporaryFile('solution/some-file.txt');
64+
file_put_contents($file, "name,age\nAydin,33\nMichael,29\n");
65+
66+
$studentSolution = $this->getTemporaryFile('student/my-solution.php');
67+
$studentFile = $this->getTemporaryFile('student/some-file.txt');
68+
file_put_contents($studentFile, "somegibberish");
69+
70+
$exercise = new FileComparisonExercise(['some-file.txt']);
71+
$exercise->setSolution(new SingleFileSolution($this->getTemporaryFile('solution/solution.php')));
72+
73+
$failure = $this->check->check($exercise, new Input('app', ['program' => $studentSolution]));
74+
75+
$this->assertInstanceOf(FileComparisonFailure::class, $failure);
76+
$this->assertEquals($failure->getFileName(), 'some-file.txt');
77+
$this->assertEquals($failure->getExpectedValue(), "name,age\nAydin,33\nMichael,29\n");
78+
$this->assertEquals($failure->getActualValue(), "somegibberish");
79+
}
80+
81+
public function testSuccessIsReturnedIfFilesMatch(): void
82+
{
83+
$file = $this->getTemporaryFile('solution/some-file.txt');
84+
file_put_contents($file, "name,age\nAydin,33\nMichael,29\n");
85+
86+
$studentSolution = $this->getTemporaryFile('student/my-solution.php');
87+
$studentFile = $this->getTemporaryFile('student/some-file.txt');
88+
file_put_contents($studentFile, "name,age\nAydin,33\nMichael,29\n");
89+
90+
$exercise = new FileComparisonExercise(['some-file.txt']);
91+
$exercise->setSolution(new SingleFileSolution($this->getTemporaryFile('solution/solution.php')));
92+
93+
$this->assertInstanceOf(
94+
Success::class,
95+
$this->check->check($exercise, new Input('app', ['program' => $studentSolution]))
96+
);
97+
}
98+
}

0 commit comments

Comments
 (0)