Skip to content

Commit 9b72518

Browse files
authored
Merge pull request #7 from Boehringer-Ingelheim/rc/4.0.0
Rc/4.0.0
2 parents 9cb7400 + 6cd2c86 commit 9b72518

18 files changed

Lines changed: 591 additions & 36 deletions

.gitignore

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
1-
.Rproj.user/
2-
README.html
1+
.Rproj.user
32
.Rhistory
4-
.lintr
3+
.RData
4+
.Ruserdata
5+
.directory
6+
.Renviron
7+
.Rprofile
58
docs/
6-
9+
README.html
10+
vignettes/*\.html
11+
vignettes/*\.R
12+
inst/validation/results/val_param.rds
13+
inst/validation/results/val_report.html
14+
tests/testthat/app/shiny_bookmarks

.lintr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
linters: linters_with_defaults(
2+
line_length_linter(120),
3+
object_usage_linter = NULL,
4+
indentation_linter = NULL,
5+
trailing_whitespace_linter = NULL
6+
)

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Package: dv.listings
22
Type: Package
33
Title: Data listings module
4-
Version: 3.1.0
4+
Version: 4.0.0
55
Authors@R:
66
c(
77
person("Boehringer-Ingelheim Pharma GmbH & Co.KG", role = c("cph", "fnd")),

NEWS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# dv.listings 3.1.0
1+
# dv.listings 4.0.0
22

33
Package was renamed to dv.listings.
44

_pkgdown.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@ template:
33

44
navbar:
55
type: inverse
6-
6+
structure:
7+
left: [intro, reference, articles, tutorials, news, qc]
8+
components:
9+
qc:
10+
text: Quality Control
11+
href: articles/qc.html
712
home:
813
title: dv.listings
914
links:

inst/validation/results/.gitempty

Whitespace-only changes.

inst/validation/run_validation.R

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
pkg_name <- read.dcf("DESCRIPTION")[, "Package"]
2+
pkg_version <- read.dcf("DESCRIPTION")[, "Version"]
3+
test_results <- tibble::as_tibble(devtools::test())
4+
5+
local({
6+
# This is evaluated inside a local because, otherwise, all the variables created in the chunks of the rendered
7+
# document leak into the environment
8+
9+
validation_root <- "./inst/validation"
10+
validation_report_rmd <- file.path(validation_root, "val_report.Rmd")
11+
validation_report_html <- "val_report.html"
12+
validation_results <- file.path(validation_root, "results")
13+
val_param_rds <- file.path(validation_results, "val_param.rds")
14+
15+
stopifnot(dir.exists(validation_root))
16+
stopifnot(file.exists(validation_report_rmd))
17+
18+
stopifnot(dir.exists(validation_results))
19+
unlink(list.files(validation_results))
20+
21+
saveRDS(
22+
list(
23+
package = pkg_name,
24+
tests = test_results,
25+
version = pkg_version
26+
),
27+
val_param_rds
28+
)
29+
30+
rmarkdown::render(
31+
input = validation_report_rmd,
32+
params = list(
33+
package = pkg_name,
34+
tests = test_results,
35+
version = pkg_version
36+
),
37+
output_dir = validation_results,
38+
output_file = validation_report_html
39+
)
40+
41+
# We use one of the leaked variables, created inside the validation report to asses if the validation is
42+
# succesful or not
43+
VALIDATION_PASSED
44+
})

inst/validation/specs.R

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Use a list to declare the specs
2+
# nolint start line_length_linter
3+
specs_list <- list
4+
5+
listing <- specs_list(
6+
"display_listing" = "dv.listings displays a dataset as listing",
7+
"listing_selection" = "dv.listings includes a dropdown menu to select which dataset to be shown.",
8+
"listings_label" = "dv.listings displays the label of a dataset if available. The label is concatenated to the dataset name and the resulting strings are provided as choices in the module's dropdown menu.",
9+
"column_selection" = "dv.listings includes a dropdown menu to select the columns from the selected listing to be shown and arrange their order.",
10+
"column_label" = "dv.listings displays extended column headers consisting of the variable name pasted together with its label, if available. These extended column headers replace the original variable names in the column dropdown menu.",
11+
"sorting_columns" = "dv.listings includes sorting functionality for each of the column.",
12+
"restore_row_order" = "dv.listings includes a button to restore the row order of a listing to the state as it is in the original data.",
13+
"default_vars" = "If pre-specifications for default columns are available, dv.listings will display them at app launch for the respective listing. If not, dv.listings will show the first six columns of the listing - or all columns, in case the number of columns is less than six.",
14+
"retain_last_selection" = "dv.listings can remember and retain the last column selections after switching listings during the current session. It also restores the remembered selections for all listings after bookmarking.",
15+
"bookmarking" = "The module is compatible with the bookmarking feature of the dv.manager."
16+
)
17+
export <- specs_list(
18+
"export" = "dv.listings includes a button to export the listing(s). A click to the button envokes a pop-up to appear that allows the user to decide whether the download should only contain the displayed listing or all available listings, provide a file name (defaulted to the dataset name), and select from available file types.",
19+
"export_active_listing" = "For downloading only the currently active listing, the listing will be saved as it is displayed, either in .xlsx or .pdf format. In case filters were applied, the downloaded output will only contain the filtered data.",
20+
"export_excel" = "For downloading all listings, the tables can be saved in .xlsx format only without considering local filters. Each listing will be placed in an individual worksheet within the file.",
21+
"export_pdf" = "For downloading in .pdf format, users can select one or multiple reference column(s), which will be displayed on all document pages."
22+
)
23+
# nolint end line_length_linter
24+
25+
specs <- c(
26+
listing,
27+
export
28+
)

inst/validation/utils-validation.R

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
#' Setting up the validation
2+
3+
if (!exists("package_name")) stop("package name must be in the environment when this script is sourced")
4+
5+
#' How to link tests and specs
6+
7+
if (FALSE) {
8+
test_that(
9+
vdoc[["add_spec"]]("my test description", specs$a_spec),
10+
{
11+
expect_true(TRUE)
12+
}
13+
)
14+
}
15+
#' The specs variable on the call references the one declared in specs.R
16+
17+
#' 3. For those tests covering more than one spec.
18+
#' NOTE: It must be c() and not list()
19+
#'
20+
21+
if (FALSE) {
22+
test_that(
23+
vdoc[["add_spec"]]("my test_description", c(specs$my$hier$spec, vdoc_specs$my$hier$other_spec)),
24+
{
25+
expect_true(TRUE)
26+
}
27+
)
28+
}
29+
30+
#' Considerations:
31+
#' - parse_spec uses deparse(substitute()). These spec_ids are later used to check if all requirements
32+
#' are covered or not, therefore those calls cannot by substituted for:
33+
34+
if (FALSE) {
35+
my_spec <- specs$my$hier$spec
36+
test_that(vdoc[["add_spec"]]("my test_description", my_spec), {
37+
...
38+
})
39+
40+
test_that(vdoc[["add_spec"]]("my test_description", specs[["my"]][["hier"]][["spec"]]), {
41+
...
42+
})
43+
}
44+
45+
# In this case the substitute captures my_spec and cannot be used later.
46+
# If you want to do this you must use the spec_id parameter where you pass a
47+
# character vector with the ids.
48+
# Notice that the ids in character form do no longer have the specs particle
49+
# at the beginning, only the pathing of the spec is needed.
50+
51+
if (FALSE) {
52+
my_spec <- specs$my$hier$spec
53+
test_that(vdoc$parse_spec(my_spec, "my test_description", spec_id = c("my$hier$spec")), {
54+
...
55+
})
56+
}
57+
58+
# Validation code
59+
# nolint start cyclocomp_linter
60+
local({
61+
specs <- source(
62+
system.file("validation", "specs.R", package = package_name, mustWork = TRUE),
63+
local = TRUE
64+
)[["value"]]
65+
recursive_ids <- function(x, parent = character(0)) {
66+
if (!is.list(x)) {
67+
return(parent)
68+
}
69+
unlist(mapply(recursive_ids,
70+
x,
71+
paste(parent, names(x),
72+
sep = if (identical(parent, character(0))) "" else "$"
73+
),
74+
SIMPLIFY = FALSE, USE.NAMES = FALSE
75+
))
76+
}
77+
78+
recursive_ids <- function(x, parent = character(0)) {
79+
if (!is.list(x)) {
80+
return(parent)
81+
}
82+
unlist(mapply(recursive_ids, x,
83+
paste(parent, names(x),
84+
sep = if (identical(parent, character(0))) "" else "$"
85+
),
86+
SIMPLIFY = FALSE, USE.NAMES = FALSE
87+
))
88+
}
89+
90+
91+
spec_id_list <- recursive_ids(specs)
92+
93+
list(
94+
specs = specs,
95+
spec_id_list = spec_id_list,
96+
add_spec = function(desc, spec, spec_id) {
97+
if (missing(spec_id)) {
98+
if (!is.character(spec) || length(spec) == 0) stop("spec must be a non-empty character vector")
99+
s_spec <- substitute(spec)
100+
if (s_spec[[1]] == "c") {
101+
spec_id <- sapply(s_spec[2:length(s_spec)], identity)
102+
} else {
103+
spec_id <- list(s_spec) # Otherwise the posterior vapply iterates over the expression
104+
}
105+
106+
spec_id_chr <- vapply(spec_id, function(x) {
107+
sub("^[^$]*\\$", "", deparse(x))
108+
}, FUN.VALUE = character(1))
109+
110+
if (!all(spec_id_chr %in% spec_id_list)) {
111+
stop("At least one spec is not declared in the spec list")
112+
} # This should be covered by pack of constants but just in case
113+
} else {
114+
spec_id_chr <- spec_id
115+
}
116+
paste0(desc, "__spec_ids{", paste0(spec_id_chr, collapse = ";"), "}")
117+
},
118+
get_spec = function(test, specs) {
119+
spec_ids <- utils::strcapture(
120+
pattern = "__spec_ids\\{(.*)\\}",
121+
x = test,
122+
proto = list(spec = character())
123+
)[["spec"]]
124+
125+
spec_ids <- strsplit(spec_ids, split = ";")
126+
127+
specs_and_id <- list()
128+
129+
for (idx in seq_along(spec_ids)){
130+
ids <- spec_ids[[idx]]
131+
if (all(!is.na(ids))) {
132+
this_specs <- list()
133+
for (sub_idx in seq_along(ids)) {
134+
id <- ids[[sub_idx]]
135+
this_specs[[sub_idx]] <- eval(str2expression(paste0("specs$", id)))
136+
}
137+
specs_and_id[[idx]] <- list(
138+
spec_id = ids,
139+
spec = this_specs
140+
)
141+
} else {
142+
specs_and_id[[idx]] <- list(
143+
spec_id = NULL,
144+
spec = NULL
145+
)
146+
}
147+
}
148+
specs_and_id
149+
}
150+
151+
152+
)
153+
})
154+
155+
# nolint end cyclocomp_linter

inst/validation/val_report.Rmd

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
title: "Quality Control"
3+
output:
4+
html_document:
5+
toc: true
6+
toc_depth: 2
7+
code_folding: hide
8+
toc-title: "----\nIndex"
9+
10+
params:
11+
package: NULL
12+
tests: NULL
13+
version: NULL
14+
---
15+
16+
```{r, child = "val_report_child.Rmd"}
17+
```

0 commit comments

Comments
 (0)