diff --git a/DESCRIPTION b/DESCRIPTION index 9a6bd6e..b380690 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -18,5 +18,6 @@ Imports: openxlsx, readODS Suggests: - testthat (>= 3.0.0) + testthat (>= 3.0.0), + mockr Config/testthat/edition: 3 diff --git a/R/input.R b/R/input.R index ae275b8..9d1bf08 100644 --- a/R/input.R +++ b/R/input.R @@ -7,13 +7,13 @@ source("R/variables.R") #' #' @param file_path The path to the file to parse #' @return The file as a data frame -select_file_type <- function(file_path) { +read_file <- function(file_path) { # Check if file extension is supported (xlsx or ods) if (grepl(".xlsx", file_path)) { - file_data <- read.xlsx(file_path, sheet = 1, skipEmptyRows = FALSE, skipEmptyCols = FALSE, colNames = TRUE, cols = (8:25)) + file_data <- openxlsx::read.xlsx(file_path, sheet = 1, skipEmptyRows = FALSE, skipEmptyCols = FALSE, colNames = TRUE, cols = (8:25), sep.names = " ") file_data <- file_data[, c(8:25)] } else if (grepl(".ods", file_path)) { - file_data <- read_ods(file_path, sheet = 1, col_names = TRUE, as_tibble = FALSE, na = "NULL") + file_data <- readODS::read_ods(file_path, sheet = 1, col_names = TRUE, as_tibble = FALSE, na = "NULL") file_data <- file_data[, c(8:25)] } else { stop("File type not supported") @@ -21,20 +21,20 @@ select_file_type <- function(file_path) { return(file_data) } -#' Synthesizes a student's wishes from multiple columns per filière to 7 columns for all filières +#' Synthesizes a student's wishes from multiple columns per filiere to 7 columns for all filieres #' #' @param wishes The wishes columns -#' @return A vector with the filière and the 7 wishes (NA if no wish) +#' @return A vector with the filiere and the 7 wishes (NA if no wish) synthesize_wishes <- function(wishes) { # Get the head of the columns colnames <- colnames(wishes) - # Extract the filière info + # Extract the filiere info if (length(grep("FC_FIRE", wishes[1])) > 0) { # Dataframe from rank number and speciality name df <- data.frame(rank = unlist(wishes[2:8]), spe = sub(Q2_PREFIX, "", colnames[2:8])) # Sort the dataframe by rank df <- df[order(df$rank), ] - # Set result to the filière and the specialities ordered by the student's preferences + # Set result to the filiere and the specialities ordered by the student's preferences result <- c("FC_FIRE", df$spe) } else if (length(grep("EMIR", wishes[1])) > 0) { df <- data.frame(rank = unlist(wishes[9:12]), spe = sub(Q3_PREFIX, "", colnames[9:12])) @@ -45,7 +45,7 @@ synthesize_wishes <- function(wishes) { df <- df[order(df$rank), ] result <- c("MICA", df$spe) } else { - stop("Unknown filière") + stop("Unknown filiere") } return(result) } @@ -57,15 +57,15 @@ synthesize_wishes <- function(wishes) { parse_file <- function(file_path) { # Get file data as a data frame tryCatch({ - file_data <- select_file_type(file_path) + file_data <- read_file(file_path) }, error = function(e) { stop("Error while reading the file : ", conditionMessage(e)) }) # Build the result data frame data <- data.frame( Nom = rep(NA_character_, nrow(file_data)), - Prénom = rep(NA_character_, nrow(file_data)), - Filière = rep(NA_character_, nrow(file_data)), + Prenom = rep(NA_character_, nrow(file_data)), + Filiere = rep(NA_character_, nrow(file_data)), V1 = rep(NA_character_, nrow(file_data)), V2 = rep(NA_character_, nrow(file_data)), V3 = rep(NA_character_, nrow(file_data)), @@ -87,8 +87,8 @@ parse_file <- function(file_path) { for (i in seq_len(nrow(file_data))) { # Name name_split <- strsplit(file_data[i, 1], split = " ")[[1]] # We assume that the first and last name are separated by a space - data[i, 1] <- name_split[1] - data[i, 2] <- name_split[2] + data[i, 1] <- name_split[2] + data[i, 2] <- name_split[1] # Wishes tryCatch({ synthesized_wishes <- synthesize_wishes(file_data[i, 3:18]) diff --git a/man/select_file_type.Rd b/man/read_file.Rd similarity index 80% rename from man/select_file_type.Rd rename to man/read_file.Rd index 0094ef6..bebb88b 100644 --- a/man/select_file_type.Rd +++ b/man/read_file.Rd @@ -1,10 +1,10 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/input.R -\name{select_file_type} -\alias{select_file_type} +\name{read_file} +\alias{read_file} \title{Reads the file and selects the needed columns} \usage{ -select_file_type(file_path) +read_file(file_path) } \arguments{ \item{file_path}{The path to the file to parse} diff --git a/man/synthesize_wishes.Rd b/man/synthesize_wishes.Rd index 070e567..e73d91a 100644 --- a/man/synthesize_wishes.Rd +++ b/man/synthesize_wishes.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/input.R \name{synthesize_wishes} \alias{synthesize_wishes} -\title{Synthesizes a student's wishes from multiple columns per filière to 7 columns for all filières} +\title{Synthesizes a student's wishes from multiple columns per filiere to 7 columns for all filieres} \usage{ synthesize_wishes(wishes) } @@ -10,8 +10,8 @@ synthesize_wishes(wishes) \item{wishes}{The wishes columns} } \value{ -A vector with the filière and the 7 wishes (NA if no wish) +A vector with the filiere and the 7 wishes (NA if no wish) } \description{ -Synthesizes a student's wishes from multiple columns per filière to 7 columns for all filières +Synthesizes a student's wishes from multiple columns per filiere to 7 columns for all filieres } diff --git a/tests/data/test_file.ods b/tests/data/test_file.ods new file mode 100644 index 0000000..d9bf1d8 Binary files /dev/null and b/tests/data/test_file.ods differ diff --git a/tests/data/test_file.xlsx b/tests/data/test_file.xlsx new file mode 100644 index 0000000..f962c82 Binary files /dev/null and b/tests/data/test_file.xlsx differ diff --git a/tests/testthat.R b/tests/testthat.R index cd0d018..66bc1df 100644 --- a/tests/testthat.R +++ b/tests/testthat.R @@ -8,5 +8,8 @@ library(testthat) library(ADSPlanner) +library(mockr) +library(openxlsx) +library(readODS) -test_check("ADSPlanner") +test_check("ADSPlanner") \ No newline at end of file diff --git a/tests/testthat/setup.R b/tests/testthat/setup.R index e69de29..e6b8ce6 100644 --- a/tests/testthat/setup.R +++ b/tests/testthat/setup.R @@ -0,0 +1,172 @@ +read_file_output <- data.frame( + "Nom complet" = c("Laurence Marchand", "Laurence ROZE", "Laurence Roze"), + "Nom d’utilisateur" = c("roze@insa-rennes.fr", "roze@inria.fr", "lroze@univ-rennes1.fr"), + "Q01_Filiere" = c("1 : FC_FIRE (Filière classique ou filière internationale)", "2 : EMIR", "3 : MICA"), + "Q02_Voeux->EII" = c(1, NA, NA), + "Q02_Voeux->E&T" = c(2, NA, NA), + "Q02_Voeux->INFO" = c(5, NA, NA), + "Q02_Voeux->MA" = c(4, NA, NA), + "Q02_Voeux->GCU" = c(3, NA, NA), + "Q02_Voeux->GMA" = c(6, NA, NA), + "Q02_Voeux->GPM" = c(7, NA, NA), + "Q03_VoeuxEMIR->EII" = c(NA, 4, NA), + "Q03_VoeuxEMIR->INFO" = c(NA, 3, NA), + "Q03_VoeuxEMIR->GPM" = c(NA, 2, NA), + "Q03_VoeuxEMIR->E&T" = c(NA, 1, NA), + "Q04_voeuxMICA->GCU" = c(NA, NA, 4), + "Q04_voeuxMICA->MA" = c(NA, NA, 1), + "Q04_voeuxMICA->GMA" = c(NA, NA, 3), + "Q04_voeuxMICA->INFO" = c(NA, NA, 2), + check.names = FALSE +) + +read_file_output_invalid <- data.frame( + "Nom complet" = c("Laurence Marchand", "Laurence ROZE", "Laurence Roze"), + "Nom d’utilisateur" = c("roze@insa-rennes.fr", "roze@inria.fr", "lroze@univ-rennes1.fr"), + "Q01_Filiere" = c("1 : FC_FIRE (Filière classique ou filière internationale)", "4 : Filière that doesn't exist", "3 : MICA"), + "Q02_Voeux->EII" = c(1, NA, NA), + "Q02_Voeux->E&T" = c(2, NA, NA), + "Q02_Voeux->INFO" = c(5, NA, NA), + "Q02_Voeux->MA" = c(4, NA, NA), + "Q02_Voeux->GCU" = c(3, NA, NA), + "Q02_Voeux->GMA" = c(6, NA, NA), + "Q02_Voeux->GPM" = c(7, NA, NA), + "Q03_VoeuxEMIR->EII" = c(NA, 4, NA), + "Q03_VoeuxEMIR->INFO" = c(NA, 3, NA), + "Q03_VoeuxEMIR->GPM" = c(NA, 2, NA), + "Q03_VoeuxEMIR->E&T" = c(NA, 1, NA), + "Q04_voeuxMICA->GCU" = c(NA, NA, 4), + "Q04_voeuxMICA->MA" = c(NA, NA, 1), + "Q04_voeuxMICA->GMA" = c(NA, NA, 3), + "Q04_voeuxMICA->INFO" = c(NA, NA, 2), + check.names = FALSE +) + +synth_wishes_input_fc_fire <- data.frame( + "Q01_Filiere" = "1 : FC_FIRE (Filière classique ou filière internationale)", + "Q02_Voeux->EII" = 1, + "Q02_Voeux->E&T" = 2, + "Q02_Voeux->INFO" = 5, + "Q02_Voeux->MA" = 4, + "Q02_Voeux->GCU" = 3, + "Q02_Voeux->GMA" = 6, + "Q02_Voeux->GPM" = 7, + "Q03_VoeuxEMIR->EII" = NA, + "Q03_VoeuxEMIR->INFO" = NA, + "Q03_VoeuxEMIR->GPM" = NA, + "Q03_VoeuxEMIR->E&T" = NA, + "Q04_voeuxMICA->GCU" = NA, + "Q04_voeuxMICA->MA" = NA, + "Q04_voeuxMICA->GMA" = NA, + "Q04_voeuxMICA->INFO" = NA, + check.names = FALSE +) + +synth_wishes_output_fc_fire <- c( + "FC_FIRE", + "EII", + "E&T", + "GCU", + "MA", + "INFO", + "GMA", + "GPM" +) + +synth_wishes_input_emir <- data.frame( + "Q01_Filiere" = "2 : EMIR", + "Q02_Voeux->EII" = NA, + "Q02_Voeux->E&T" = NA, + "Q02_Voeux->INFO" = NA, + "Q02_Voeux->MA" = NA, + "Q02_Voeux->GCU" = NA, + "Q02_Voeux->GMA" = NA, + "Q02_Voeux->GPM" = NA, + "Q03_VoeuxEMIR->EII" = 4, + "Q03_VoeuxEMIR->INFO" = 3, + "Q03_VoeuxEMIR->GPM" = 2, + "Q03_VoeuxEMIR->E&T" = 1, + "Q04_voeuxMICA->GCU" = NA, + "Q04_voeuxMICA->MA" = NA, + "Q04_voeuxMICA->GMA" = NA, + "Q04_voeuxMICA->INFO" = NA, + check.names = FALSE +) + +synth_wishes_output_emir <- c( + "EMIR", + "E&T", + "GPM", + "INFO", + "EII" +) + +synth_wishes_input_mica <- data.frame( + "Q01_Filiere" = "3 : MICA", + "Q02_Voeux->EII" = NA, + "Q02_Voeux->E&T" = NA, + "Q02_Voeux->INFO" = NA, + "Q02_Voeux->MA" = NA, + "Q02_Voeux->GCU" = NA, + "Q02_Voeux->GMA" = NA, + "Q02_Voeux->GPM" = NA, + "Q03_VoeuxEMIR->EII" = NA, + "Q03_VoeuxEMIR->INFO" = NA, + "Q03_VoeuxEMIR->GPM" = NA, + "Q03_VoeuxEMIR->E&T" = NA, + "Q04_voeuxMICA->GCU" = 4, + "Q04_voeuxMICA->MA" = 1, + "Q04_voeuxMICA->GMA" = 3, + "Q04_voeuxMICA->INFO" = 2, + check.names = FALSE +) + +synth_wishes_output_mica <- c( + "MICA", + "MA", + "INFO", + "GMA", + "GCU" +) + +synth_wishes_input_invalid <- data.frame( + "Q01_Filiere" = "4 : Filière that doesn't exist", + "Q02_Voeux->EII" = NA, + "Q02_Voeux->E&T" = NA, + "Q02_Voeux->INFO" = NA, + "Q02_Voeux->MA" = NA, + "Q02_Voeux->GCU" = NA, + "Q02_Voeux->GMA" = NA, + "Q02_Voeux->GPM" = NA, + "Q03_VoeuxEMIR->EII" = NA, + "Q03_VoeuxEMIR->INFO" = NA, + "Q03_VoeuxEMIR->GPM" = NA, + "Q03_VoeuxEMIR->E&T" = NA, + "Q04_voeuxMICA->GCU" = 4, + "Q04_voeuxMICA->MA" = 1, + "Q04_voeuxMICA->GMA" = 3, + "Q04_voeuxMICA->INFO" = 2, + check.names = FALSE +) + +parse_file_output <- data.frame( + Nom = c("Marchand", "ROZE", "Roze"), + Prenom = c("Laurence", "Laurence", "Laurence"), + Filiere = c("FC_FIRE", "EMIR", "MICA"), + V1 = c("EII", "E&T", "MA"), + V2 = c("E&T", "GPM", "INFO"), + V3 = c("GCU", "INFO", "GMA"), + V4 = c("MA", "EII", "GCU"), + V5 = c("INFO", NA_character_, NA_character_), + V6 = c("GMA", NA_character_, NA_character_), + V7 = c("GPM", NA_character_, NA_character_), + Aff_V1_S1 = c(NA_character_, NA_character_, NA_character_), + Aff_V1_S2 = c(NA_character_, NA_character_, NA_character_), + Aff_V1_S3 = c(NA_character_, NA_character_, NA_character_), + Aff_V2_S1 = c(NA_character_, NA_character_, NA_character_), + Aff_V2_S2 = c(NA_character_, NA_character_, NA_character_), + Aff_V2_S3 = c(NA_character_, NA_character_, NA_character_), + Aff_V3_S1 = c(NA_character_, NA_character_, NA_character_), + Aff_V3_S2 = c(NA_character_, NA_character_, NA_character_), + Aff_V3_S3 = c(NA_character_, NA_character_, NA_character_) +) \ No newline at end of file diff --git a/tests/testthat/test-input.R b/tests/testthat/test-input.R new file mode 100644 index 0000000..1790455 --- /dev/null +++ b/tests/testthat/test-input.R @@ -0,0 +1,80 @@ +# Testing read_file + +test_that("read_file reads xlsx files correctly", { + file_path <- "../data/test_file.xlsx" + result <- read_file(file_path) + expect_true(is.data.frame(result)) + expect_equal(ncol(result), 18) + expect_equal(result, read_file_output) +}) + +test_that("read_file reads ods files correctly", { + file_path <- "../data/test_file.ods" + result <- read_file(file_path) + expect_true(is.data.frame(result)) + expect_equal(ncol(result), 18) + expect_equal(result, read_file_output) +}) + +test_that("read_file throws error for unsupported file types", { + file_path <- "../data/test_file.csv" + expect_error(read_file(file_path), "File type not supported") +}) + +test_that("read_file throws error for non existing file", { + file_path <- "../data/imaginary_file.xlsx" + expect_error(read_file(file_path), "File does not exist") +}) + +# Testing synthesize_wishes + +test_that("synthesize_wishes return correct result for FC_FIRE", { + result <- synthesize_wishes(synth_wishes_input_fc_fire) + expect_true(is.vector(result)) + expect_equal(length(result), 8) + expect_equal(result, synth_wishes_output_fc_fire) +}) + +test_that("synthesize_wishes return correct result for EMIR", { + result <- synthesize_wishes(synth_wishes_input_emir) + expect_true(is.vector(result)) + expect_equal(length(result), 5) + expect_equal(result, synth_wishes_output_emir) +}) + +test_that("synthesize_wishes return correct result for MICA", { + result <- synthesize_wishes(synth_wishes_input_mica) + expect_true(is.vector(result)) + expect_equal(length(result), 5) + expect_equal(result, synth_wishes_output_mica) +}) + +test_that("synthesize_wishes throws error for non existing filière", { + expect_error(synthesize_wishes(synth_wishes_input_invalid), "Unknown filiere") +}) + +# Testing parse_file + +test_that("parse_file returns correct result for a valid input file", { + local_mock(read_file = function(file_path) read_file_output) + result <- parse_file("../data/test_file.xlsx") + expect_equal(result, parse_file_output) +}) + +test_that("parse_file throws error for invalid input file type", { + local_mock(read_file = function(file_path) stop("File type not supported")) + expect_error(parse_file("../data/test_file.csv"), "Error while reading the file : File type not supported") +}) + +test_that("parse_file throws error for non existent file", { + local_mock(read_file = function(file_path) stop("File does not exist")) + expect_error(parse_file("../data/imaginary_file.xlsx"), "Error while reading the file : File does not exist") +}) + +test_that("parse_file throws error for invalid data", { + local_mock( + read_file = function(file_path) read_file_output_invalid, + synthesize_wishes = function(wishes) stop("Unknown filière") + ) + expect_error(parse_file("../data/test_file.xlsx"), "Error while synthesizing the wishes \\(l\\.1\\): Unknown filière") +}) \ No newline at end of file diff --git a/tests/testthat/tests.R b/tests/testthat/tests.R deleted file mode 100644 index e69de29..0000000