Skip to content

Commit

Permalink
Fix/tests (#7)
Browse files Browse the repository at this point in the history
* Remove obsolete resources

* Fix the wrong class to test and make tests independent of implementation

* Improve tests

* Improve tests

* accidently removed main code

---------

Co-authored-by: nyanyan <[email protected]>
  • Loading branch information
zentox and zentox authored Dec 27, 2023
1 parent e82457e commit fd4c08f
Show file tree
Hide file tree
Showing 49 changed files with 223 additions and 2,704 deletions.
64 changes: 52 additions & 12 deletions src/graderPrivate/java/h06/H3_MazeSolverRecursiveTest.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package h06;

import com.fasterxml.jackson.databind.node.ArrayNode;
import h06.mock.TestWorld;
import h06.problems.MazeSolver;
import h06.problems.MazeSolverIterative;
import h06.problems.MazeSolverRecursive;
import h06.world.DirectionVector;
import h06.world.World;
Expand Down Expand Up @@ -63,11 +63,6 @@
@SkipAfterFirstFailedTest(TestConstants.SKIP_AFTER_FIRST_FAILED_TEST)
public class H3_MazeSolverRecursiveTest {

/**
* The {@link MazeSolver} to test.
*/
private final MazeSolver solver = new MazeSolverIterative();

/**
* The {@link TypeLink} to {@link MazeSolverRecursive} used for context information.
*
Expand All @@ -94,6 +89,11 @@ private MethodLink getMethod(String name) {
@DisplayName("H3.1 | nextStep(World, Point, DirectionVector)")
public class NextStepTest {

/**
* The {@link MazeSolver} to test.
*/
private final MazeSolver solver = new MazeSolverRecursive();

/**
* Tests whether {@link MazeSolverRecursive#nextStep(World, Point, DirectionVector)} computes the next step
* correctly.
Expand All @@ -105,7 +105,7 @@ public class NextStepTest {
*/
private void assertNextStep(WorldProperties properties, Point p, DirectionVector d, DirectionVector expected) {
MethodLink method = getMethod("nextStep");
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
DirectionVector actual = solver.nextStep(world, p, d);
Context context = contextBuilder().subject(method)
.add(buildWorldContext(properties))
Expand Down Expand Up @@ -267,6 +267,11 @@ public void testRequirements() {
@DisplayName("H3.2 | numberOfSteps(World, Point, Point, Direction)")
public class NumberOfStepsTest {

/**
* The {@link MazeSolver} to test.
*/
private final MazeSolver solver = new TestNextStepWorld();

/**
* Returns the method for context information.
*
Expand Down Expand Up @@ -346,7 +351,7 @@ public void testNextStep() {
*/
private void assertNumberOfSteps(WorldProperties properties, Point s, Point e, DirectionVector d, int expected) {
MethodLink method = getMethod();
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
int actual = solver.numberOfSteps(world, s, e, d);
Context context = contextBuilder().subject(method)
.add(buildWorldContext(properties))
Expand Down Expand Up @@ -460,6 +465,11 @@ public void testRequirements() {
@DisplayName("H3.3 | solve(World, Point, Point, Direction)")
public class SolveTest {

/**
* The {@link MazeSolver} to test.
*/
private final MazeSolver solver = new TestSolverWorld();

/**
* Returns the method for context information.
*
Expand Down Expand Up @@ -527,7 +537,7 @@ public void testCorrectArraySize(
expected[i] = new Point(node.get(i).get("x").asInt(), node.get(i).get("y").asInt());
}
MethodLink method = getMethod();
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
Point[] actual = solver.solve(world, s, e, d);
Context context = contextBuilder().subject(method)
.add(buildWorldContext(properties))
Expand Down Expand Up @@ -573,7 +583,7 @@ public void testContainsStart(
expected[i] = new Point(node.get(i).get("x").asInt(), node.get(i).get("y").asInt());
}
MethodLink method = getMethod();
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
Point[] actual = solver.solve(world, s, e, d);

Context context = contextBuilder().subject(method)
Expand Down Expand Up @@ -620,7 +630,7 @@ public void testContainsEnd(
expected[i] = new Point(node.get(i).get("x").asInt(), node.get(i).get("y").asInt());
}
MethodLink method = getMethod();
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
Point[] actual = solver.solve(world, s, e, d);

Context context = contextBuilder().subject(method)
Expand Down Expand Up @@ -668,7 +678,7 @@ public void testContainsAll(
}

MethodLink method = getMethod();
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
Point[] actual = solver.solve(world, s, e, d);

for (int i = 1; i < expected.length - 1; i++) {
Expand Down Expand Up @@ -698,4 +708,34 @@ public void testRequirements() {
assertRecursive(method.getCtElement(), "MazeSolverRecursive#solve(World, Point, Point, Direction))", context);
}
}

/**
* Used to make testing of implementation independent of next step.
*/
@SkipCheck
private static class TestNextStepWorld extends MazeSolverRecursive {

@Override
public DirectionVector nextStep(World world, Point p, DirectionVector d) {
return !world.isBlocked(p, TutorUtils.rotate270(d))
? TutorUtils.rotate270(d) :
nextStep(world, p, TutorUtils.rotate90(d));
}
}

/**
* Used to make testing of implementation independent of the next step and number of steps.
*/
@SkipCheck
private static class TestSolverWorld extends TestNextStepWorld {

@Override
public int numberOfSteps(World world, Point s, Point e, DirectionVector d) {
if (s.equals(e)) {
return 1;
}
DirectionVector next = nextStep(world, s, d);
return 1 + numberOfSteps(world, next.getMovement(s), e, next);
}
}
}
71 changes: 61 additions & 10 deletions src/graderPrivate/java/h06/H4_MazeSolverIterativeTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package h06;

import com.fasterxml.jackson.databind.node.ArrayNode;
import h06.mock.TestWorld;
import h06.problems.MazeSolver;
import h06.problems.MazeSolverIterative;
import h06.problems.MazeSolverRecursive;
Expand Down Expand Up @@ -53,11 +54,6 @@
@SkipAfterFirstFailedTest(TestConstants.SKIP_AFTER_FIRST_FAILED_TEST)
public class H4_MazeSolverIterativeTest {

/**
* The {@link MazeSolver} to test.
*/
private final MazeSolver solver = new MazeSolverIterative();

/**
* The {@link TypeLink} to {@link MazeSolverRecursive} used for context information.
*
Expand All @@ -84,6 +80,11 @@ private MethodLink getMethod(String name) {
@DisplayName("H4.1 | nextStep(World, Point, DirectionVector)")
public class NextStepTest {

/**
* The {@link MazeSolver} to test.
*/
private final MazeSolver solver = new MazeSolverIterative();

/**
* Tests whether {@link MazeSolverRecursive#nextStep(World, Point, DirectionVector)} computes the next step
* correctly.
Expand All @@ -95,7 +96,7 @@ public class NextStepTest {
*/
private void assertNextStep(WorldProperties properties, Point p, DirectionVector d, DirectionVector expected) {
MethodLink method = getMethod("nextStep");
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
DirectionVector actual = solver.nextStep(world, p, d);
Context context = contextBuilder().subject(method)
.add(buildWorldContext(properties))
Expand Down Expand Up @@ -221,6 +222,11 @@ public void testRequirements() {
@DisplayName("H4.2 | numberOfSteps(World, Point, Point, Direction)")
public class NumberOfStepsTest {

/**
* The {@link MazeSolver} to test.
*/
private final MazeSolver solver = new TestNextStepWorld();

/**
* Returns the method for context information.
*
Expand Down Expand Up @@ -272,7 +278,7 @@ private void assertNumberOfSteps(
int expected
) {
MethodLink method = getMethod();
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
int actual = solver.numberOfSteps(world, s, e, d);
Context context = contextBuilder().subject(method)
.add(buildWorldContext(properties))
Expand Down Expand Up @@ -385,6 +391,11 @@ public void testRequirements() {
@DisplayName("H4.3 | solve(World, Point, Point, Direction)")
public class SolveTest {

/**
* The {@link MazeSolver} to test.
*/
private final MazeSolver solver = new TestSolverWorld();

/**
* Returns the method for context information.
*
Expand Down Expand Up @@ -452,7 +463,7 @@ public void testCorrectArraySize(
expected[i] = new Point(node.get(i).get("x").asInt(), node.get(i).get("y").asInt());
}
MethodLink method = getMethod();
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
Point[] actual = solver.solve(world, s, e, d);
Context context = contextBuilder().subject(method)
.add(buildWorldContext(properties))
Expand Down Expand Up @@ -498,7 +509,7 @@ public void testContainsStartEnd(
expected[i] = new Point(node.get(i).get("x").asInt(), node.get(i).get("y").asInt());
}
MethodLink method = getMethod();
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
Point[] actual = solver.solve(world, s, e, d);

Context.Builder<?> context = contextBuilder().subject(method)
Expand Down Expand Up @@ -551,7 +562,7 @@ public void testContainsAll(
}

MethodLink method = getMethod();
World world = properties.createWorld();
World world = properties.createWorld(TestWorld::new);
Point[] actual = solver.solve(world, s, e, d);

for (int i = 1; i < expected.length - 1; i++) {
Expand Down Expand Up @@ -580,4 +591,44 @@ public void testRequirements() {
assertIterative(method.getCtElement(), "MazeSolverIterative#solve(World, Point, Point, Direction)", context);
}
}

/**
* Used to make testing of implementation independent of next step.
*/
@SkipCheck
private static class TestNextStepWorld extends MazeSolverIterative {

@Override
public DirectionVector nextStep(World world, Point p, DirectionVector d) {
DirectionVector next = TutorUtils.rotate270(d);
for (int i = 0; i < DirectionVector.values().length; i++) {
if (!world.isBlocked(p, next)) {
return next;
}
next = TutorUtils.rotate90(next);
}
return d;
}
}

/**
* Used to make testing of implementation independent of the next step and number of steps.
*/
@SkipCheck
private static class TestSolverWorld extends TestNextStepWorld {

@Override
public int numberOfSteps(World world, Point s, Point e, DirectionVector d) {
int steps = 0;
Point next = s;
DirectionVector nextDir = d;
while (!next.equals(e)) {
nextDir = nextStep(world, next, nextDir);
next = nextDir.getMovement(next);
steps++;
}
steps++;
return steps;
}
}
}
16 changes: 16 additions & 0 deletions src/graderPrivate/java/h06/SkipCheck.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package h06;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Mark class which should not be checked for rubrics.
*
* @author Nhan Huynh
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface SkipCheck {
}
35 changes: 34 additions & 1 deletion src/graderPrivate/java/h06/TutorUtils.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package h06;

import h06.world.DirectionVector;
import org.junit.jupiter.api.DisplayName;
import org.sourcegrade.jagr.api.rubric.Criterion;
import org.sourcegrade.jagr.api.rubric.Grader;
Expand Down Expand Up @@ -164,7 +165,9 @@ private static Criterion singleCriterion(Class<?> source) {
* @return the criterion for a nested test class
*/
public static Criterion criterionNested(Class<?> source) {
Class<?>[] classes = source.getDeclaredClasses();
Class<?>[] classes = Arrays.stream(source.getDeclaredClasses())
.filter(clazz -> !clazz.isAnnotationPresent(SkipCheck.class))
.toArray(Class[]::new);
Criterion[] mainCriteria = new Criterion[classes.length];
for (int i = 0; i < classes.length; i++) {
Class<?> clazz = classes[i];
Expand All @@ -187,6 +190,7 @@ public static Criterion criterionNested(Class<?> source) {
}
mainCriteria[i] = Criterion.builder()
.shortDescription(clazz.getAnnotation(DisplayName.class).value())
.minPoints(0)
.addChildCriteria(criteria.toArray(Criterion[]::new))
.build();
}
Expand Down Expand Up @@ -272,4 +276,33 @@ private static boolean isRecursive(
return false;
}

/**
* Returns the direction vector counterclockwise to given direction vector (90 degrees to the left).
*
* @param d the direction vector to rotate
* @return the direction vector counterclockwise to the given direction vector
*/
public static DirectionVector rotate270(DirectionVector d) {
return switch (d) {
case UP -> DirectionVector.LEFT;
case RIGHT -> DirectionVector.UP;
case DOWN -> DirectionVector.RIGHT;
case LEFT -> DirectionVector.DOWN;
};
}

/**
* Returns the direction vector clockwise to given direction vector (90 degrees to the right).
*
* @param d the direction vector to rotate
* @return the direction vector clockwise to the given direction vector
*/
public static DirectionVector rotate90(DirectionVector d) {
return switch (d) {
case UP -> DirectionVector.RIGHT;
case RIGHT -> DirectionVector.DOWN;
case DOWN -> DirectionVector.LEFT;
case LEFT -> DirectionVector.UP;
};
}
}
13 changes: 12 additions & 1 deletion src/graderPrivate/java/h06/WorldProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import h06.world.World;

import java.awt.Point;
import java.util.function.BiFunction;


/**
Expand Down Expand Up @@ -42,7 +43,17 @@ public class WorldProperties {
* @return the world with the given properties
*/
public World createWorld() {
World world = new World(width, height);
return createWorld(World::new);
}

/**
* Constructs a world with the given properties.
*
* @param mapper a function used to create dynamic world instance
* @return the world with the given properties
*/
public World createWorld(BiFunction<Integer, Integer, World> mapper) {
World world = mapper.apply(width, height);
for (Point p : horizontal) {
world.placeWall(p.x, p.y, true);
}
Expand Down
Loading

0 comments on commit fd4c08f

Please sign in to comment.