Skip to content

Commit 361e592

Browse files
authored
Add check_row_order argument (#134)
1 parent 8702baa commit 361e592

33 files changed

+717
-695
lines changed

DESCRIPTION

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: tblcheck
22
Title: Grade Tables in Learning Exercises
3-
Version: 0.3.0.9000
3+
Version: 0.3.1
44
Authors@R: c(
55
person("Alexander", "Rossell Hayes", , "alex.rossellhayes@rstudio.com", role = c("aut", "cre"),
66
comment = c(ORCID = "0000-0001-9412-0457")),
@@ -19,19 +19,20 @@ URL: https://pkgs.rstudio.com/tblcheck,
1919
BugReports: https://github.com/rstudio/tblcheck/issues
2020
Imports:
2121
checkmate,
22+
dplyr,
2223
ellipsis,
2324
glue,
2425
gradethis (>= 0.2.7.9000),
2526
knitr,
2627
lifecycle,
2728
magrittr,
2829
methods,
30+
purrr,
2931
rlang,
3032
tidyselect,
3133
utils,
3234
vctrs
3335
Suggests:
34-
dplyr,
3536
learnr,
3637
lubridate,
3738
mockery,

NEWS.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
# tblcheck (development version)
1+
# tblcheck 0.3.1
2+
3+
* Add `check_row_order` argument to `tbl_check()`, `tbl_grade()`, and `tbl_equal()`. When `check_row_order()` is set to false, `object` and `expected` are arranged so that their row orders match before checking for differences in column values.
24

35
# tblcheck 0.3.0
46

R/grade_this.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ grade_this_table <- function(
8383
check_column_levels = check_columns,
8484
check_column_values = check_columns,
8585
tolerance = sqrt(.Machine$double.eps),
86+
check_row_order = check_columns,
8687
hint = getOption("gradethis.fail.hint", FALSE),
8788
encourage = getOption("gradethis.fail.encourage", FALSE),
8889
# gradethis pass/fail options

R/tbl_check.R

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@
6161
#' column has the same [factor levels][levels()] in `object` and `expected`.
6262
#' @param check_column_values `[logical(1)]`\cr Whether to check that each
6363
#' column has the same values in `object` and `expected`.
64+
#' @param check_row_order `[logical(1)]`\cr Whether to check that the values in
65+
#' each column are in the same order in `object` and `expected`.
6466
#' @inheritParams vec_check_values
6567
#' @param env The environment in which to find `.result` and `.solution`.
6668
#' @inheritDotParams gradethis::fail -message
@@ -125,6 +127,7 @@ tbl_check <- function(
125127
check_column_levels = check_columns,
126128
check_column_values = check_columns,
127129
tolerance = sqrt(.Machine$double.eps),
130+
check_row_order = check_columns,
128131
env = parent.frame()
129132
) {
130133
if (inherits(object, ".result")) {
@@ -141,7 +144,9 @@ tbl_check <- function(
141144
checkmate::assert_logical(check_groups, any.missing = FALSE, len = 1)
142145
checkmate::assert_logical(check_columns, any.missing = FALSE, len = 1)
143146
checkmate::assert_logical(check_column_class, any.missing = FALSE, len = 1)
147+
checkmate::assert_logical(check_column_levels, any.missing = FALSE, len = 1)
144148
checkmate::assert_logical(check_column_values, any.missing = FALSE, len = 1)
149+
checkmate::assert_logical(check_row_order, any.missing = FALSE, len = 1)
145150
checkmate::assert_data_frame(expected)
146151
})
147152

@@ -199,9 +204,24 @@ tbl_check <- function(
199204
)
200205
}
201206

207+
columns_in_common <- intersect(names(object), names(expected))
208+
209+
# If we don't care about row order,
210+
# arrange the rows in `object` and `expected` in the same way
211+
if (!check_row_order) {
212+
object <- dplyr::arrange(
213+
object,
214+
dplyr::across(tidyselect::all_of(columns_in_common))
215+
)
216+
expected <- dplyr::arrange(
217+
expected,
218+
dplyr::across(tidyselect::all_of(columns_in_common))
219+
)
220+
}
221+
202222
# check column contents ----
203223
if (check_columns) {
204-
for (column in names(expected)) {
224+
for (column in columns_in_common) {
205225
return_if_problem(
206226
tbl_check_column(
207227
column = column,
@@ -213,7 +233,8 @@ tbl_check <- function(
213233
check_values = check_column_values,
214234
tolerance = tolerance,
215235
check_length = FALSE
216-
)
236+
),
237+
check_order = check_row_order
217238
)
218239
}
219240
}
@@ -237,6 +258,7 @@ tbl_grade <- function(
237258
check_column_levels = check_columns,
238259
check_column_values = check_columns,
239260
tolerance = sqrt(.Machine$double.eps),
261+
check_row_order = check_columns,
240262
env = parent.frame(),
241263
...
242264
) {
@@ -255,6 +277,7 @@ tbl_grade <- function(
255277
check_column_class = check_column_class,
256278
check_column_levels = check_column_levels,
257279
check_column_values = check_column_values,
280+
check_row_order = check_row_order,
258281
tolerance = tolerance,
259282
env = env
260283
),

R/tbl_equal.R

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ tbl_equal <- function(
2828
check_column_levels = check_columns,
2929
check_column_values = check_columns,
3030
tolerance = sqrt(.Machine$double.eps),
31+
check_row_order = check_columns,
3132
env = parent.frame()
3233
) {
3334
is.null(
@@ -46,6 +47,7 @@ tbl_equal <- function(
4647
check_column_levels = check_column_levels,
4748
check_column_values = check_column_values,
4849
tolerance = tolerance,
50+
check_row_order = check_row_order,
4951
env = env
5052
)
5153
)

R/tests-helpers.R

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,19 @@ expect_warning <- function(...) {
1818
suppressWarnings(testthat::expect_warning(...))
1919
}
2020

21+
expect_problem <- function(object, type, expected, actual, ...) {
22+
testthat::expect_s3_class(object, "tblcheck_problem")
23+
24+
if (!rlang::is_missing(type)) testthat::expect_equal(object$type, type)
25+
if (!rlang::is_missing(expected)) testthat::expect_equal(object$expected, expected)
26+
if (!rlang::is_missing(actual)) testthat::expect_equal(object$actual, actual)
27+
28+
purrr::iwalk(
29+
list(...),
30+
function(value, name) testthat::expect_equal(object[[name]], value)
31+
)
32+
}
33+
2134
tblcheck_test_grade <- function(expr, return_all = FALSE) {
2235
expr <- rlang::enexpr(expr)
2336

R/vec_check_values.R

Lines changed: 45 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -116,47 +116,50 @@ problem_message.values_problem <- function(problem, max_diffs = 3, ...) {
116116
}
117117

118118
# First, alert the user if the first `n` values do not match
119-
problem$n_values <- min(
120-
max(length(problem$expected), length(problem$actual)),
121-
max_diffs
122-
)
123-
124-
first_n_values_are_equal <-
125-
vctrs::vec_equal(
126-
problem$expected[seq_len(problem$n_values)],
127-
problem$actual[seq_len(problem$n_values)],
128-
na_equal = TRUE
129-
)
130-
131-
if (!all(first_n_values_are_equal)) {
132-
problem$expected <- knitr::combine_words(
133-
md_code(problem$expected[seq_len(problem$n_values)])
119+
# Skip this if order was not checked, since that would make "first" meaningless
120+
if (!isFALSE(problem$check_order)) {
121+
problem$n_values <- min(
122+
max(length(problem$expected), length(problem$actual)),
123+
max_diffs
134124
)
135-
problem$actual <- knitr::combine_words(
136-
md_code(problem$actual[seq_len(problem$n_values)])
137-
)
138-
139-
problem$expected_msg <- problem$expected_msg %||%
140-
if (is_problem(problem, "column")) {
141-
ngettext(
142-
problem$n_values,
143-
"The first value of your `{column}` column should be {expected}, not {actual},",
144-
"The first {n_values} values of your `{column}` column should be {expected},"
145-
)
146-
} else {
147-
ngettext(
148-
problem$n_values,
149-
"The first value of your result should be {expected},",
150-
"The first {n_values} values of your result should be {expected},"
151-
)
152-
}
153-
154-
problem$actual_message <- problem$actual_message %||%
155-
" not {actual}."
156125

157-
return(
158-
glue::glue_data(problem, problem$expected_msg, problem$actual_message)
159-
)
126+
first_n_values_are_equal <-
127+
vctrs::vec_equal(
128+
problem$expected[seq_len(problem$n_values)],
129+
problem$actual[seq_len(problem$n_values)],
130+
na_equal = TRUE
131+
)
132+
133+
if (!all(first_n_values_are_equal)) {
134+
problem$expected <- knitr::combine_words(
135+
md_code(problem$expected[seq_len(problem$n_values)])
136+
)
137+
problem$actual <- knitr::combine_words(
138+
md_code(problem$actual[seq_len(problem$n_values)])
139+
)
140+
141+
problem$expected_msg <- problem$expected_msg %||%
142+
if (is_problem(problem, "column")) {
143+
ngettext(
144+
problem$n_values,
145+
"The first value of your `{column}` column should be {expected}, not {actual},",
146+
"The first {n_values} values of your `{column}` column should be {expected},"
147+
)
148+
} else {
149+
ngettext(
150+
problem$n_values,
151+
"The first value of your result should be {expected},",
152+
"The first {n_values} values of your result should be {expected},"
153+
)
154+
}
155+
156+
problem$actual_message <- problem$actual_message %||%
157+
" not {actual}."
158+
159+
return(
160+
glue::glue_data(problem, problem$expected_msg, problem$actual_message)
161+
)
162+
}
160163
}
161164

162165
# Next, alert if there are values in `actual` that aren't in `expected`
@@ -215,5 +218,7 @@ problem_message.values_problem <- function(problem, max_diffs = 3, ...) {
215218
}
216219

217220
# If all else fails, return vague message
218-
problem_message(problem("values"))
221+
problem$expected <- NULL
222+
problem$actual <- NULL
223+
problem_message(problem)
219224
}

man/grade_this_table.Rd

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/tbl_check.Rd

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/tbl_equal.Rd

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/_snaps/check_table.md renamed to tests/testthat/_snaps/tbl_check.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,3 +238,12 @@
238238
by `a`.
239239
>
240240

241+
# tbl_grade() ignoring row order
242+
243+
Code
244+
grade_ignore_rows_values_diff
245+
Output
246+
<gradethis_graded: [Incorrect]
247+
Your `b` column contains unexpected values.
248+
>
249+

0 commit comments

Comments
 (0)