diff --git a/tmc-langs-r/src/main/java/fi/helsinki/cs/tmc/langs/r/RExerciseDescParser.java b/tmc-langs-r/src/main/java/fi/helsinki/cs/tmc/langs/r/RExerciseDescParser.java index d49a052a8..f607a2989 100644 --- a/tmc-langs-r/src/main/java/fi/helsinki/cs/tmc/langs/r/RExerciseDescParser.java +++ b/tmc-langs-r/src/main/java/fi/helsinki/cs/tmc/langs/r/RExerciseDescParser.java @@ -13,15 +13,14 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; -import java.util.Map; class RExerciseDescParser { private static Path RESULT_FILE = Paths.get(".available_points.json"); - private static final TypeReference>> MAP_TYPE_REFERENCE = - new TypeReference>>() {}; + private static final TypeReference> MAP_TYPE_REFERENCE = + new TypeReference>() {}; private Path path; private ObjectMapper mapper; @@ -31,12 +30,13 @@ public RExerciseDescParser(Path path) { } public ImmutableList parse() throws IOException { + List testDescs = new ArrayList<>(); byte[] json = Files.readAllBytes(path.resolve(RESULT_FILE)); - Map> parse = mapper.readValue(json, MAP_TYPE_REFERENCE); - for (String name : parse.keySet()) { - ImmutableList points = ImmutableList.copyOf(parse.get(name)); - testDescs.add(new TestDesc(name, points)); + List parse = mapper.readValue(json, MAP_TYPE_REFERENCE); + for (RResult result : parse) { + ImmutableList points = ImmutableList.copyOf(result.getPoints()); + testDescs.add(new TestDesc(result.getName(), points)); } return ImmutableList.copyOf(testDescs); } diff --git a/tmc-langs-r/src/main/java/fi/helsinki/cs/tmc/langs/r/RResult.java b/tmc-langs-r/src/main/java/fi/helsinki/cs/tmc/langs/r/RResult.java new file mode 100644 index 000000000..a151aac96 --- /dev/null +++ b/tmc-langs-r/src/main/java/fi/helsinki/cs/tmc/langs/r/RResult.java @@ -0,0 +1,33 @@ + +package fi.helsinki.cs.tmc.langs.r; + +import java.util.List; + + +public class RResult { + + private String name; + private List points; + + public RResult(){ + + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getPoints() { + return points; + } + + public void setPoints(List points) { + this.points = points; + } + + +} diff --git a/tmc-langs-r/src/test/java/fi/helsinki/cs/tmc/langs/r/RExerciseDescParserTest.java b/tmc-langs-r/src/test/java/fi/helsinki/cs/tmc/langs/r/RExerciseDescParserTest.java index 7e8b84953..10cea2a29 100644 --- a/tmc-langs-r/src/test/java/fi/helsinki/cs/tmc/langs/r/RExerciseDescParserTest.java +++ b/tmc-langs-r/src/test/java/fi/helsinki/cs/tmc/langs/r/RExerciseDescParserTest.java @@ -30,18 +30,32 @@ public RExerciseDescParserTest() { @Test public void testThatParseSeemsToWorkOnExampleJson() { - assertEquals(re.size(),6); - assertEquals(re.get(0).points.size(),2); + assertEquals(re.size(),22); + assertEquals(re.get(0).points.size(),3); assertEquals(re.get(0).name,"Addition works"); - assertEquals(re.get(1).points.size(),2); + assertEquals(re.get(1).points.size(),3); assertEquals(re.get(1).name,"Multiplication works"); - assertEquals(re.get(2).points.size(),1); + assertEquals(re.get(2).points.size(),2); assertEquals(re.get(2).name,"Subtraction works"); - assertEquals(re.get(3).points.size(),1); + assertEquals(re.get(3).points.size(),2); assertEquals(re.get(3).name,"Division works"); - assertEquals(re.get(4).points.size(),0); + assertEquals(re.get(4).points.size(),1); assertEquals(re.get(4).name, "Test with no points"); - assertEquals(re.get(5).points.size(),0); + assertEquals(re.get(5).points.size(),1); assertEquals(re.get(5).name, "Dummy test set to fail"); + assertEquals(re.get(6).points.size(),2); + assertEquals(re.get(6).name, "Matrix transpose with [[1,2]] works"); + assertEquals(re.get(7).points.size(),2); + assertEquals(re.get(7).name, "Matrix transpose with [[1,2],[3,4]] works"); + assertEquals(re.get(8).points.size(),2); + assertEquals(re.get(8).name, "Constant string works"); + for (int i = 1;i <= 13;i++) { + assertEquals(re.get(8 + i).name, "Exercise " + i + " is correct"); + if (i == 3) { + assertEquals(re.get(8 + i).points.size(),3); + } else { + assertEquals(re.get(8 + i).points.size(),2); + } + } } } diff --git a/tmc-langs-r/src/test/java/fi/helsinki/cs/tmc/langs/r/RPluginTest.java b/tmc-langs-r/src/test/java/fi/helsinki/cs/tmc/langs/r/RPluginTest.java index 52bad761b..c6b379550 100644 --- a/tmc-langs-r/src/test/java/fi/helsinki/cs/tmc/langs/r/RPluginTest.java +++ b/tmc-langs-r/src/test/java/fi/helsinki/cs/tmc/langs/r/RPluginTest.java @@ -1,12 +1,18 @@ package fi.helsinki.cs.tmc.langs.r; + import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; + +import fi.helsinki.cs.tmc.langs.domain.RunResult; +import fi.helsinki.cs.tmc.langs.domain.TestResult; import fi.helsinki.cs.tmc.langs.io.StudentFilePolicy; import fi.helsinki.cs.tmc.langs.utils.TestUtils; +import com.google.common.collect.ImmutableList; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.SystemUtils; import org.junit.After; @@ -21,6 +27,13 @@ + + + + + + + public class RPluginTest { private RPlugin plugin; @@ -32,9 +45,12 @@ public void setUp() { @After public void tearDown() { - Path testDir = TestUtils.getPath(getClass(), "passing"); + Path testDir = TestUtils.getPath(getClass(), "project1"); File resultsJson = new File(testDir.toAbsolutePath().toString() + "/.results.json"); resultsJson.delete(); + File availablePointsJson = new File(testDir.toAbsolutePath().toString() + + "/.available_points.json"); + availablePointsJson.delete(); } @Test @@ -71,14 +87,42 @@ public void testGetPluginName() { @Test public void testScanExercise() { - Path testDir = TestUtils.getPath(getClass(), "passing"); + Path testDir = TestUtils.getPath(getClass(), "project1"); plugin.scanExercise(testDir, "arithmetics.R"); + File availablePointsJson = new File(testDir.toAbsolutePath().toString() + + "/.available_points.json"); + + assertTrue(availablePointsJson.exists()); } @Test public void testRunTests() { - Path testDir = TestUtils.getPath(getClass(), "passing"); - plugin.runTests(testDir); + Path testDir = TestUtils.getPath(getClass(), "project1"); + RunResult runRes = plugin.runTests(testDir); + ImmutableList re = runRes.testResults; + assertEquals(re.size(),22); + assertEquals(re.get(0).getName(),"Addition works"); + assertTrue(re.get(1).isSuccessful()); + assertEquals(re.get(1).getName(),"Multiplication works"); + assertTrue(re.get(2).isSuccessful()); + assertEquals(re.get(2).getName(),"Subtraction works"); + assertTrue(re.get(3).isSuccessful()); + assertEquals(re.get(3).getName(),"Division works"); + assertTrue(re.get(4).isSuccessful()); + assertEquals(re.get(4).getName(), "Test with no points"); + assertFalse(re.get(5).isSuccessful()); + assertEquals(re.get(5).getName(), "Dummy test set to fail"); + assertTrue(re.get(6).isSuccessful()); + assertEquals(re.get(6).getName(), "Matrix transpose with [[1,2]] works"); + assertTrue(re.get(7).isSuccessful()); + assertEquals(re.get(7).getName(), "Matrix transpose with [[1,2],[3,4]] works"); + assertTrue(re.get(8).isSuccessful()); + assertEquals(re.get(8).getName(), "Constant string works"); + for (int i = 1;i <= 13;i++) { + assertEquals(re.get(8 + i).getName(), "Exercise " + i + " is correct"); + assertTrue(re.get(8 + i).isSuccessful());; + + } File resultsJson = new File(testDir.toAbsolutePath().toString() + "/.results.json"); assertTrue(resultsJson.exists()); diff --git a/tmc-langs-r/src/test/resources/example_json/.available_points.json b/tmc-langs-r/src/test/resources/example_json/.available_points.json index 25862cfca..8b706636d 100644 --- a/tmc-langs-r/src/test/resources/example_json/.available_points.json +++ b/tmc-langs-r/src/test/resources/example_json/.available_points.json @@ -1,8 +1,158 @@ -{"Addition works": ["r1.1","r1.2"], - "Multiplication works":["r1.3", "r1.4"], - "Subtraction works":["r1.5"], - "Division works":["r1.6"], - "Test with no points":[], - "Dummy test set to fail":[] -} +[ + { + "name": "Addition works", + "points": [ + "r1", + "r1.1", + "r1.2" + ] + }, + { + "name": "Multiplication works", + "points": [ + "r1", + "r1.3", + "r1.4" + ] + }, + { + "name": "Subtraction works", + "points": [ + "r1", + "r1.5" + ] + }, + { + "name": "Division works", + "points": [ + "r1", + "r1.6" + ] + }, + { + "name": "Test with no points", + "points": [ + "r1" + ] + }, + { + "name": "Dummy test set to fail", + "points": [ + "r1" + ] + }, + { + "name": "Matrix transpose with [[1,2]] works", + "points": [ + "r2", + "r2.1" + ] + }, + { + "name": "Matrix transpose with [[1,2],[3,4]] works", + "points": [ + "r2", + "r2.2" + ] + }, + { + "name": "Constant string works", + "points": [ + "r3", + "r3.1" + ] + }, + { + "name": "Exercise 1 is correct", + "points": [ + "r4", + "r4.1" + ] + }, + { + "name": "Exercise 2 is correct", + "points": [ + "r4", + "r4.2" + ] + }, + { + "name": "Exercise 3 is correct", + "points": [ + "r4", + "r4.3", + "r4.4" + ] + }, + { + "name": "Exercise 4 is correct", + "points": [ + "r4", + "r4.5" + ] + }, + { + "name": "Exercise 5 is correct", + "points": [ + "r4", + "r4.6" + ] + }, + { + "name": "Exercise 6 is correct", + "points": [ + "r4", + "r4.7" + ] + }, + { + "name": "Exercise 7 is correct", + "points": [ + "r4", + "r4.8" + ] + }, + { + "name": "Exercise 8 is correct", + "points": [ + "r4", + "r4.9" + ] + }, + { + "name": "Exercise 9 is correct", + "points": [ + "r4", + "r4.10" + ] + }, + { + "name": "Exercise 10 is correct", + "points": [ + "r4", + "r4.11" + ] + }, + { + "name": "Exercise 11 is correct", + "points": [ + "r4", + "r4.12" + ] + }, + { + "name": "Exercise 12 is correct", + "points": [ + "r4", + "r4.13" + ] + }, + { + "name": "Exercise 13 is correct", + "points": [ + "r4", + "r4.14" + ] + } +] diff --git a/tmc-langs-r/src/test/resources/project1/.Rbuildignore b/tmc-langs-r/src/test/resources/project1/.Rbuildignore new file mode 100644 index 000000000..4434527ce --- /dev/null +++ b/tmc-langs-r/src/test/resources/project1/.Rbuildignore @@ -0,0 +1,3 @@ +^\.travis\.yml$ +^.*\.Rproj$ +^\.Rproj\.user$ diff --git a/tmc-langs-r/src/test/resources/project1/.gitignore b/tmc-langs-r/src/test/resources/project1/.gitignore new file mode 100644 index 000000000..131c08e07 --- /dev/null +++ b/tmc-langs-r/src/test/resources/project1/.gitignore @@ -0,0 +1,4 @@ +.Rdata +.Rhistory +.results.json +.available_points.json diff --git a/tmc-langs-r/src/test/resources/project1/DESCRIPTION b/tmc-langs-r/src/test/resources/project1/DESCRIPTION new file mode 100644 index 000000000..329bf0b74 --- /dev/null +++ b/tmc-langs-r/src/test/resources/project1/DESCRIPTION @@ -0,0 +1,9 @@ +Package: project1 +Title: What the Package Does (one line, title case) +Version: 0.0.0.9000 +Authors@R: person("First", "Last", email = "first.last@example.com", role = c("aut", "cre")) +Description: What the package does (one paragraph). +Depends: R (>= 3.2.3) +License: What license is it under? +Encoding: UTF-8 +LazyData: true diff --git a/tmc-langs-r/src/test/resources/project1/NAMESPACE b/tmc-langs-r/src/test/resources/project1/NAMESPACE new file mode 100644 index 000000000..ce085262b --- /dev/null +++ b/tmc-langs-r/src/test/resources/project1/NAMESPACE @@ -0,0 +1,2 @@ +# Generated by roxygen2: fake comment so roxygen2 overwrites silently. +exportPattern("^[^\\.]") \ No newline at end of file diff --git a/tmc-langs-r/src/test/resources/project1/R/arithmetics.R b/tmc-langs-r/src/test/resources/project1/R/arithmetics.R new file mode 100644 index 000000000..fe5f31853 --- /dev/null +++ b/tmc-langs-r/src/test/resources/project1/R/arithmetics.R @@ -0,0 +1,16 @@ + +add <- function(a, b) { + return(a+b) +} + +subtract <- function(a, b) { + return(a-b) +} + +multiply <- function(a, b) { + return(a*b) +} + +divide <- function(a, b) { + return(a/b) +} diff --git a/tmc-langs-r/src/test/resources/project1/R/matrices.R b/tmc-langs-r/src/test/resources/project1/R/matrices.R new file mode 100644 index 000000000..066d87d15 --- /dev/null +++ b/tmc-langs-r/src/test/resources/project1/R/matrices.R @@ -0,0 +1,3 @@ +transpose_matrix <- function(matrix) { + return(t(matrix)) +} diff --git a/tmc-langs-r/src/test/resources/project1/R/strings.R b/tmc-langs-r/src/test/resources/project1/R/strings.R new file mode 100644 index 000000000..7feafdf95 --- /dev/null +++ b/tmc-langs-r/src/test/resources/project1/R/strings.R @@ -0,0 +1,3 @@ +constant_string <- function() { + return("jono") +} diff --git a/tmc-langs-r/src/test/resources/project1/R/week1.R b/tmc-langs-r/src/test/resources/project1/R/week1.R new file mode 100644 index 000000000..07deb637a --- /dev/null +++ b/tmc-langs-r/src/test/resources/project1/R/week1.R @@ -0,0 +1,73 @@ +##These exercises are taken from the course "Data-analyysi R-ohjelmistolla" +#(https://wiki.helsinki.fi/pages/viewpage.action?pageId=135074576). +## + +##Exercise 1 + +a1 <- 4 + 10 +b1 <- 5*a1 +c1 <- b1^3 +d1 <- exp(b1) +e1 <- d1^(1/10) +f1 <- sin(c1) +res1 <- (b1 + c1 + e1 + f1) + +##Exercise 2 + +a2 <- 51%%7 + +##Excercise 3 +a3 <- 51%%7 + 51%/%7 + +##Excercise 4 +v4_1 <- c(20, 5, -2, 3, 47) +v4_2 <- seq(0, 100, 5) +v4_3 <- c(v4_1, v4_2) +v4_4 <- v4_3[(v4_3 > 3) & (v4_3 < 50)] +v4_5 <- v4_4[(v4_4 %% 10) == 0] + +##Exercise 5 +v5_1 <- rep(0, 1, 50) +v5_1[c(F, T)] <- 2 + +sum5_1 <- sum(v5_1) +v5_1 +v5_2 <- v5_1 +v5_2[c(T, F)] <- 1.2 +sum5_2 <- sum(v5_2) + +##Excerice 6 + +A <- matrix(c(3, 5, 6, 1/2, sqrt(5), 16, 0, 2, 0),nrow = 3, ncol = 3, byrow = TRUE) + + +##Excercise 7 +B <- c(1, 1, 0)%*% solve(A) + +##Excercise 8 +I_3 <- diag(c(1, 1, 1)) +A_8 <- A %*%I_3 + +##Excercise 9 +is_eq_matrix <- t(A) == A +is_eq_matrix <- F + +##Excercise 10 +C_10 <- matrix(c(runif(20, min = 1, max=20)), ncol=4) +v10_1 <- C_10[C_10 < 5] +number10 <- length(v10_1) + +D_10 <- C_10 +D_10[D_10 < 5] <- 10 + +E_10 <- D_10 +E_10 <- D_10[c(T, T, T, T, F),c(F,T,T, T)] + + +##Excercise 11 +C_11 <- matrix(1:100, ncol=2) +C_11[c(F, T)] <- NA + +##Excercise 12 +C_12 <- C_11 +C_12[is.na(C_12)] <- 0 diff --git a/tmc-langs-r/src/test/resources/project1/README.md b/tmc-langs-r/src/test/resources/project1/README.md new file mode 100644 index 000000000..2d9b43401 --- /dev/null +++ b/tmc-langs-r/src/test/resources/project1/README.md @@ -0,0 +1,8 @@ +# Project 1 + +This is a project that we use to test if testthat-tests that we have written +work and how the results can be parsed. + +## How to use + +To run tests on this test project, run the script `tmc_run_test_example.sh`. diff --git a/tmc-langs-r/src/test/resources/project1/project1.Rproj b/tmc-langs-r/src/test/resources/project1/project1.Rproj new file mode 100644 index 000000000..21a4da087 --- /dev/null +++ b/tmc-langs-r/src/test/resources/project1/project1.Rproj @@ -0,0 +1,17 @@ +Version: 1.0 + +RestoreWorkspace: Default +SaveWorkspace: Default +AlwaysSaveHistory: Default + +EnableCodeIndexing: Yes +UseSpacesForTab: Yes +NumSpacesForTab: 2 +Encoding: UTF-8 + +RnwWeave: Sweave +LaTeX: pdfLaTeX + +BuildType: Package +PackageUseDevtools: Yes +PackageInstallArgs: --no-multiarch --with-keep.source diff --git a/tmc-langs-r/src/test/resources/project1/tests/testthat/testArithmetics.R b/tmc-langs-r/src/test/resources/project1/tests/testthat/testArithmetics.R new file mode 100644 index 000000000..56585853a --- /dev/null +++ b/tmc-langs-r/src/test/resources/project1/tests/testthat/testArithmetics.R @@ -0,0 +1,34 @@ +library('testthat') + +points_for_all_tests(c("r1")) + +test("Addition works", c("r1.1", "r1.2"), { + expect_equal(add(1, 2), 3) + expect_equal(add(1, 2), 3.0) + expect_equal(add(1, 4), 5) +}) + +test("Multiplication works", c("r1.3", "r1.4"), { + expect_equal(multiply(1, 2), 2) + expect_equal(multiply(2, 10), 20) +}) + +test("Subtraction works", c("r1.5"), { + expect_equal(subtract(10, 2), 8) + expect_equal(subtract(0, 0), 0) + expect_equal(subtract(0, 4), -4) +}) + +test("Division works", c("r1.6"), { + expect_equal(divide(10, 2), 5) + expect_equal(divide(1, 2), 0.5) +}) + +test("Test with no points", c(), { + expect_equal(1,1) +}) + +test("Dummy test set to fail", c(), { + expect_true(FALSE) + expect_equal(1,2) +}) diff --git a/tmc-langs-r/src/test/resources/project1/tests/testthat/testMatrices.R b/tmc-langs-r/src/test/resources/project1/tests/testthat/testMatrices.R new file mode 100644 index 000000000..9cede7dfd --- /dev/null +++ b/tmc-langs-r/src/test/resources/project1/tests/testthat/testMatrices.R @@ -0,0 +1,13 @@ +library('testthat') + +points_for_all_tests(c("r2")) + +test("Matrix transpose with [[1,2]] works", c("r2.1"), { + A<- matrix(c(1,2),nrow=1) + expect_equal(transpose_matrix(A),matrix(c(1,2),nrow=2)) +}) + +test("Matrix transpose with [[1,2],[3,4]] works", c("r2.2"), { + A<- matrix(c(1,2,3,4),nrow=2) + expect_equal(transpose_matrix(A),matrix(c(1,3,2,4),nrow=2)) +}) diff --git a/tmc-langs-r/src/test/resources/project1/tests/testthat/testStrings.R b/tmc-langs-r/src/test/resources/project1/tests/testthat/testStrings.R new file mode 100644 index 000000000..6f019272f --- /dev/null +++ b/tmc-langs-r/src/test/resources/project1/tests/testthat/testStrings.R @@ -0,0 +1,7 @@ +library('testthat') + +points_for_all_tests(c("r3")) + +test("Constant string works", c("r3.1"), { + expect_equal(constant_string(), "jono") +}) diff --git a/tmc-langs-r/src/test/resources/project1/tests/testthat/testWeek1.R b/tmc-langs-r/src/test/resources/project1/tests/testthat/testWeek1.R new file mode 100644 index 000000000..e031fafa6 --- /dev/null +++ b/tmc-langs-r/src/test/resources/project1/tests/testthat/testWeek1.R @@ -0,0 +1,78 @@ +library('testthat') + +points_for_all_tests(c("r4")) + +help_A <- matrix(c(3, 5, 6, 1/2, sqrt(5), 16, 0, 2, 0),nrow = 3, ncol = 3, byrow = TRUE) + +test("Exercise 1 is correct", c("r4.1"), { + expect_equal(a1, 14) + expect_equal(b1, 70) + expect_equal(c1, 343000) + expect_true(abs(e1-1096.63) < 0.1) + expect_true(abs(f1 - 0.7920019) < 0.1) + expect_true(abs(res1 - 344167.4) < 0.1) +}) + +test("Exercise 2 is correct", c("r4.2"), { + expect_equal(a2, 2) +}) + +test("Exercise 3 is correct", c("r4.3", "r4.4"), { + expect_equal(a3, 9) +}) + +test("Exercise 4 is correct", c("r4.5"), { + expect_equal(v4_1, c(20, 5, -2, 3, 47)) + expect_equal(v4_2, c(0:20)*5) + expect_equal(v4_3, c(c(20, 5, -2, 3, 47), seq(0, 100, 5))) + expect_equal(v4_4, c(20, 5, 47, 5, 10, 15, 20, 25, 30, 35, 40, 45)) + expect_equal(v4_5, c(20, 10, 20, 30, 40)) +}) + +test("Exercise 5 is correct", c("r4.6"), { + t1 <- rep(0, 1, 50) + t1[c(F, T)] <- 2 + expect_equal(v5_1, t1) + expect_equal(sum5_1, 50) + expect_equal(sum5_2, 80) +}) + +test("Exercise 6 is correct", c("r4.7"), { + expect_equal(A, matrix(c(3, 5, 6, 1/2, sqrt(5), 16, 0, 2, 0),nrow = 3, ncol = 3, byrow = TRUE)) +}) + +test("Exercise 7 is correct", c("r4.8"), { + expect_equal(A, help_A) +}) + +test("Exercise 8 is correct", c("r4.9"), { + expect_equal(B, c(1, 1, 0)%*%solve(help_A)) +}) + +test("Exercise 9 is correct", c("r4.10"), { + expect_equal(I_3, diag(c(1, 1, 1))) + expect_equal(A_8, help_A) +}) + +test("Exercise 10 is correct", c("r4.11"), { + expect_false(is_eq_matrix) +}) + +test("Exercise 11 is correct", c("r4.12"), { + expect_true(number10 < 10) + + expect_true(dim(E_10)[1] == 4) + expect_true(dim(E_10)[2] == 3) +}) + +test("Exercise 12 is correct", c("r4.13"), { + M <- matrix(1:100, ncol=2) + M[c(F, T)] <- NA + expect_equal(C_11, M) +}) + +test("Exercise 13 is correct", c("r4.14"), { + M <- matrix(1:100, ncol=2) + M[c(F, T)] <- 0 + expect_equal(C_12, M) +}) diff --git a/tmc-langs-r/src/test/resources/project1/tmc/result.R b/tmc-langs-r/src/test/resources/project1/tmc/result.R new file mode 100644 index 000000000..17f2dff64 --- /dev/null +++ b/tmc-langs-r/src/test/resources/project1/tmc/result.R @@ -0,0 +1,4 @@ +library(tmcRtestrunner) + +# Note: working directory must be the projects root! +run_tests(getwd())