Sudoku Solver: Add functional tests and fix Unit Tests

This commit is contained in:
CherryKitten 2022-11-12 10:35:00 +01:00
parent 70cee77a95
commit 0d2e39e7ba
Signed by: sammy
GPG key ID: 0B696A86A853E955
4 changed files with 237 additions and 76 deletions

View file

@ -1,22 +1,41 @@
export const puzzlesAndSolutions = [ export const puzzlesAndSolutions = [
[ [
'1.5..2.84..63.12.7.2..5.....9..1....8.2.3674.3.7.2..9.47...8..1..16....926914.37.', "1.5..2.84..63.12.7.2..5.....9..1....8.2.3674.3.7.2..9.47...8..1..16....926914.37.",
'135762984946381257728459613694517832812936745357824196473298561581673429269145378' "135762984946381257728459613694517832812936745357824196473298561581673429269145378",
], ],
[ [
'5..91372.3...8.5.9.9.25..8.68.47.23...95..46.7.4.....5.2.......4..8916..85.72...3', "5..91372.3...8.5.9.9.25..8.68.47.23...95..46.7.4.....5.2.......4..8916..85.72...3",
'568913724342687519197254386685479231219538467734162895926345178473891652851726943' "568913724342687519197254386685479231219538467734162895926345178473891652851726943",
], ],
[ [
'..839.7.575.....964..1.......16.29846.9.312.7..754.....62..5.78.8...3.2...492...1', "..839.7.575.....964..1.......16.29846.9.312.7..754.....62..5.78.8...3.2...492...1",
'218396745753284196496157832531672984649831257827549613962415378185763429374928561' "218396745753284196496157832531672984649831257827549613962415378185763429374928561",
], ],
[ [
'.7.89.....5....3.4.2..4..1.5689..472...6.....1.7.5.63873.1.2.8.6..47.1..2.9.387.6', ".7.89.....5....3.4.2..4..1.5689..472...6.....1.7.5.63873.1.2.8.6..47.1..2.9.387.6",
'473891265851726394926345817568913472342687951197254638734162589685479123219538746' "473891265851726394926345817568913472342687951197254638734162589685479123219538746",
], ],
[ [
'82..4..6...16..89...98315.749.157.............53..4...96.415..81..7632..3...28.51', "82..4..6...16..89...98315.749.157.............53..4...96.415..81..7632..3...28.51",
'827549163531672894649831527496157382218396475753284916962415738185763249374928651' "827549163531672894649831527496157382218396475753284916962415738185763249374928651",
] ],
];
export const invalidStrings = [
"135762984946-8125772845961369451783281293674535B82419647329856158167342926:145378",
'56891372434268751"%=7254386685479231219538467734162895926345178473891652851726943',
"/////////////////////////////////////////////////////////////////////////////////",
"NyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyan.",
];
export const unsolvableStrings = [
"115..2.84..63.12.7.2..5.....9..1....8.2.3674.3.7.2..9.420..8..1..16....926969.37.",
"4206942069.......................................................................",
"111111111111111111111111111111111111111111111111111111111111111111111111111111111",
];
export const wrongLengthStrings = [
"123456",
"9999999.9999992",
"1.5..2.84..63.12.7.2..5.....9..1....8.2.3674.3.7.2..9.47...8..1..16....926914.37.5..91372.3...8.5.9.9.25..8.68.47.23...95..46.7.4.....5.2.......4..8916..85.72...3",
]; ];

View file

@ -41,7 +41,7 @@ class SudokuSolver {
checkRegionPlacement(puzzleString, row, column, value) {} checkRegionPlacement(puzzleString, row, column, value) {}
solve(puzzleString) { solve(puzzleString) {
return false; return { error: "test" };
} }
} }

View file

@ -1,19 +1,11 @@
const chai = require("chai"); const chai = require("chai");
const assert = chai.assert; const assert = chai.assert;
import { puzzlesAndSolutions } from "../controllers/puzzle-strings"; import {
puzzlesAndSolutions,
const invalidStrings = [ invalidStrings,
"135762984946-8125772845961369451783281293674535B82419647329856158167342926:145378", unsolvableStrings,
'56891372434268751"%=7254386685479231219538467734162895926345178473891652851726943', wrongLengthStrings,
"/////////////////////////////////////////////////////////////////////////////////", } from "../controllers/puzzle-strings";
"NyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyanNyan.",
];
const unsolvableStrings = [
"115..2.84..63.12.7.2..5.....9..1....8.2.3674.3.7.2..9.420..8..1..16....926969.37.",
"4206942069.......................................................................",
"111111111111111111111111111111111111111111111111111111111111111111111111111111111",
];
const Solver = require("../controllers/sudoku-solver.js"); const Solver = require("../controllers/sudoku-solver.js");
let solver = new Solver(); let solver = new Solver();
@ -35,10 +27,12 @@ suite("Unit Tests", () => {
} }
}); });
test("Logic handles a puzzle string that is not 81 characters in length", () => { test("Logic handles a puzzle string that is not 81 characters in length", () => {
for (let i in wrongLengthStrings) {
assert.equal( assert.equal(
solver.validate("135762984946145378").error, solver.validate(wrongLengthStrings[i]).error,
"Expected puzzle to be 81 characters long" "Expected puzzle to be 81 characters long"
); );
}
}); });
}); });
suite("Placement Checks", () => { suite("Placement Checks", () => {
@ -106,7 +100,6 @@ suite("Unit Tests", () => {
suite("Solver", () => { suite("Solver", () => {
test("Valid puzzle strings pass the solver", () => { test("Valid puzzle strings pass the solver", () => {
for (let i in puzzlesAndSolutions) { for (let i in puzzlesAndSolutions) {
console.log(i);
assert.equal( assert.equal(
solver.solve(puzzlesAndSolutions[i][1]), solver.solve(puzzlesAndSolutions[i][1]),
puzzlesAndSolutions[i][1] puzzlesAndSolutions[i][1]
@ -116,21 +109,9 @@ suite("Unit Tests", () => {
test("Invalid puzzle strings fail the solver", () => { test("Invalid puzzle strings fail the solver", () => {
for (let i in invalidStrings) { for (let i in invalidStrings) {
assert.equal( assert.equal(
solver.solve(invalidStrings[i].error), solver.solve(invalidStrings[i]),
"Invalid characters in puzzle", { error: "Invalid characters in puzzle" },
"invalid characters" + invalidStrings[i] "invalid characters"
);
}
assert.equal(
solver.solve("135762984946145378").error,
"Expected puzzle to be 81 characters long",
"wrong length"
);
for (let i in unsolvableStrings) {
assert.equal(
solver.solve().error,
"Puzzle cannot be solved",
"not solvable" + unsolvableStrings[i]
); );
} }
}); });
@ -145,12 +126,3 @@ suite("Unit Tests", () => {
}); });
}); });
}); });
/*
TODO:
Valid puzzle strings pass the solver
*/

View file

@ -2,27 +2,197 @@ const chai = require("chai");
const chaiHttp = require("chai-http"); const chaiHttp = require("chai-http");
const assert = chai.assert; const assert = chai.assert;
const server = require("../server"); const server = require("../server");
import {
puzzlesAndSolutions,
invalidStrings,
unsolvableStrings,
wrongLengthStrings,
} from "../controllers/puzzle-strings";
chai.use(chaiHttp); chai.use(chaiHttp);
suite("Functional Tests", () => {}); suite("Functional Tests", () => {
suite("Solving puzzles", () => {
/* test("Solve a puzzle with valid puzzle string: POST request to /api/solve", (done) => {
TODO: for (let i in puzzlesAndSolutions) {
chai
Solve a puzzle with valid puzzle string: POST request to /api/solve .request(server)
Solve a puzzle with missing puzzle string: POST request to /api/solve .post("/api/solve")
Solve a puzzle with invalid characters: POST request to /api/solve .send({ puzzle: puzzlesAndSolutions[i][0] })
Solve a puzzle with incorrect length: POST request to /api/solve .end((err, res) => {
Solve a puzzle that cannot be solved: POST request to /api/solve assert.equal(res.status, 200);
Check a puzzle placement with all fields: POST request to /api/check assert.equal(res.body.solution, puzzlesAndSolutions[i][1]);
Check a puzzle placement with single placement conflict: POST request to /api/check done();
Check a puzzle placement with multiple placement conflicts: POST request to /api/check });
Check a puzzle placement with all placement conflicts: POST request to /api/check }
Check a puzzle placement with missing required fields: POST request to /api/check });
Check a puzzle placement with invalid characters: POST request to /api/check test("Solve a puzzle with missing puzzle string: POST request to /api/solve", (done) => {
Check a puzzle placement with incorrect length: POST request to /api/check for (let i in puzzlesAndSolutions) {
Check a puzzle placement with invalid placement coordinate: POST request to /api/check chai
Check a puzzle placement with invalid placement value: POST request to /api/check .request(server)
.post("/api/solve")
*/ .send({})
.end((err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.error, "Required field missing");
done();
});
}
});
test("Solve a puzzle with invalid characters: POST request to /api/solve", (done) => {
for (let i in invalidStrings) {
chai
.request(server)
.post("/api/solve")
.send({ puzzle: invalidStrings[i] })
.end((err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.error, "Invalid characters in puzzle");
done();
});
}
});
test("Solve a puzzle with incorrect length: POST request to /api/solve", (done) => {
for (let i in wrongLengthStrings) {
chai
.request(server)
.post("/api/solve")
.send({ puzzle: wrongLengthStrings[i] })
.end((err, res) => {
assert.equal(res.status, 200);
assert.equal(
res.body.error,
"Expected puzzle to be 81 charcters long"
);
done();
});
}
});
test("Solve a puzzle that cannot be solved: POST request to /api/solve", (done) => {
for (let i in unsolvableStrings) {
chai
.request(server)
.post("/api/solve")
.send({ puzzle: unsolvableStrings[i] })
.end((err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.error, "Puzzle cannot be solved");
done();
});
}
});
});
suite("Placement Checks", () => {
test("Check a puzzle placement with all fields: POST request to /api/check", (done) => {
chai
.request(server)
.post("/api/check")
.send({ puzzle: puzzlesAndSolutions[0][0], coordinate: "A2", value: 3 })
.end((err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.valid, true);
done();
});
});
test("Check a puzzle placement with single placement conflict: POST request to /api/check", (done) => {
chai
.request(server)
.post("/api/check")
.send({ puzzle: puzzlesAndSolutions[0][0], coordinate: "A2", value: 4 })
.end((err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.valid, false);
assert.include(res.body.conflict, "row");
assert.notInclude(res.body.conflict, "region");
assert.notInclude(res.body.conflict, "column");
done();
});
});
test("Check a puzzle placement with multiple placement conflicts: POST request to /api/check", (done) => {
chai
.request(server)
.post("/api/check")
.send({ puzzle: puzzlesAndSolutions[0][0], coordinate: "A2", value: 1 })
.end((err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.valid, false);
assert.include(res.body.conflict, "row");
assert.include(res.body.conflict, "region");
assert.notInclude(res.body.conflict, "column");
done();
});
});
test("Check a puzzle placement with all placement conflicts: POST request to /api/check", (done) => {
chai
.request(server)
.post("/api/check")
.send({ puzzle: puzzlesAndSolutions[0][0], coordinate: "A2", value: 2 })
.end((err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.valid, false);
assert.include(res.body.conflict, "row");
assert.include(res.body.conflict, "region");
assert.include(res.body.conflict, "column");
done();
});
});
test("Check a puzzle placement with missing required fields: POST request to /api/check", (done) => {
chai
.request(server)
.post("/api/check")
.send({ puzzle: puzzlesAndSolutions[0][0], coordinate: "A2" })
.end((err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.error, "Required field(s) missing");
done();
});
});
test("Check a puzzle placement with invalid characters: POST request to /api/check", (done) => {
chai
.request(server)
.post("/api/check")
.send({ puzzle: invalidStrings[0], coordinate: "A2", value: "3" })
.end((err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.error, "Invalid characters in puzzle");
done();
});
});
test("Check a puzzle placement with incorrect length: POST request to /api/check", (done) => {
chai
.request(server)
.post("/api/check")
.send({ puzzle: wrongLengthStrings[0], coordinate: "A2", value: "3" })
.end((err, res) => {
assert.equal(res.status, 200);
assert.equal(
res.body.error,
"Expected puzzle to be 81 characters long"
);
done();
});
});
test("Check a puzzle placement with invalid placement coordinate: POST request to /api/check", (done) => {
chai
.request(server)
.post("/api/check")
.send({ puzzle: puzzlesAndSolutions[0], coordinate: "Z11", value: "3" })
.end((err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.error, "Invalid coordinate");
done();
});
});
test("Check a puzzle placement with invalid placement value: POST request to /api/check", (done) => {
chai
.request(server)
.post("/api/check")
.send({ puzzle: puzzlesAndSolutions[0], coordinate: "A2", value: "22" })
.end((err, res) => {
assert.equal(res.status, 200);
assert.equal(res.body.error, "Invalid value");
done();
});
});
});
});