From f4515e3da02c86cfae977d639540a3829dffe60f Mon Sep 17 00:00:00 2001 From: James Hollway Date: Fri, 17 Apr 2026 11:39:35 +0200 Subject: [PATCH 1/8] Moved test_tutorials() to a testthat helper check_tute_rendering() --- NAMESPACE | 1 - R/tutorial_test.R | 34 ------------------------------- man/test_tutorials.Rd | 27 ------------------------ tests/testthat/helper-functions.R | 21 +++++++++++++++++++ 4 files changed, 21 insertions(+), 62 deletions(-) delete mode 100644 R/tutorial_test.R delete mode 100644 man/test_tutorials.Rd diff --git a/NAMESPACE b/NAMESPACE index df07aa52..5faec42e 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -33,7 +33,6 @@ export(test_fit) export(test_gof) export(test_permutation) export(test_random) -export(test_tutorials) export(tidy) importFrom(autograph,ag_base) importFrom(dplyr,"%>%") diff --git a/R/tutorial_test.R b/R/tutorial_test.R deleted file mode 100644 index 0af38efc..00000000 --- a/R/tutorial_test.R +++ /dev/null @@ -1,34 +0,0 @@ -#' Test tutorials -#' -#' @description -#' For our purposes, "testing" a tutorial means being able to -#' (successfully) run `render()` on it. -#' This function renders the tutorial provided in `path`. -#' There is no check to see if the rendered file looks OK. -#' If a tutorial fails to render, then an error will be generated which will -#' propagate to the caller. -#' @param path Character vector of the paths to the tutorials to be knitted. -#' @param quiet Logical, whether to suppress messages from `render()`. -#' @returns No return value, called for side effects. -#' @author David Kane, see tutorial.helpers -#' @export -test_tutorials <- function(path, quiet = TRUE){ - - stopifnot(all(file.exists(path))) - - for(i in path){ - if(!quiet) message("Rendering: ", basename(i)) - tryCatch({ - rmarkdown::render(input = i, - output_dir = tempdir(), - intermediates_dir = tempdir(), quiet = quiet) - # Note that the Debian setup on CRAN does not allow for writing files to any - # location other than the temporary directory, which is why we must specify - # tempdir() in the two dir arguments. - if(!quiet) message("Successfully rendered: ", basename(i)) - }, error = function(e) { - stop("Failed to render ", i, ": ", e$message, call. = FALSE) - }) - } - invisible(NULL) -} \ No newline at end of file diff --git a/man/test_tutorials.Rd b/man/test_tutorials.Rd deleted file mode 100644 index 2e36367d..00000000 --- a/man/test_tutorials.Rd +++ /dev/null @@ -1,27 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/tutorial_test.R -\name{test_tutorials} -\alias{test_tutorials} -\title{Test tutorials} -\usage{ -test_tutorials(path, quiet = TRUE) -} -\arguments{ -\item{path}{Character vector of the paths to the tutorials to be knitted.} - -\item{quiet}{Logical, whether to suppress messages from \code{render()}.} -} -\value{ -No return value, called for side effects. -} -\description{ -For our purposes, "testing" a tutorial means being able to -(successfully) run \code{render()} on it. -This function renders the tutorial provided in \code{path}. -There is no check to see if the rendered file looks OK. -If a tutorial fails to render, then an error will be generated which will -propagate to the caller. -} -\author{ -David Kane, see tutorial.helpers -} diff --git a/tests/testthat/helper-functions.R b/tests/testthat/helper-functions.R index 414f5a87..6802fba1 100644 --- a/tests/testthat/helper-functions.R +++ b/tests/testthat/helper-functions.R @@ -25,3 +25,24 @@ bot5 <- function(res, dec = 4){ unname(round(res, dec))[(lr-4):lr] } else unname(res)[(lr-2):lr] } +check_tute_rendering <- function(path, quiet = TRUE){ + + stopifnot(all(file.exists(path))) + + for(i in path){ + if(!quiet) message("Rendering: ", basename(i)) + tryCatch({ + rmarkdown::render(input = i, + output_dir = tempdir(), + intermediates_dir = tempdir(), quiet = quiet) + # Note that the Debian setup on CRAN does not allow for writing files to any + # location other than the temporary directory, which is why we must specify + # tempdir() in the two dir arguments. + if(!quiet) message("Successfully rendered: ", basename(i)) + }, error = function(e) { + stop("Failed to render ", i, ": ", e$message, call. = FALSE) + }) + } + invisible(NULL) +} + From 69bd72aad6d1c6315b18ab2ed4ff312b69735f70 Mon Sep 17 00:00:00 2001 From: James Hollway Date: Fri, 17 Apr 2026 11:40:51 +0200 Subject: [PATCH 2/8] Fixed namespace issues --- R/model_distrib.R | 2 +- tests/testthat/test-model_distrib.R | 2 +- tests/testthat/test-model_predict.R | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/R/model_distrib.R b/R/model_distrib.R index 40874cbd..7afea13a 100644 --- a/R/model_distrib.R +++ b/R/model_distrib.R @@ -57,7 +57,7 @@ test_distribution <- function(diff_model1, diff_model2){ #' @export test_fit <- function(diff_model, diff_models){ # make into method? x <- diff_model - if(is_graph(x)) x <- as_diffusion(x) + if(manynet::is_graph(x)) x <- manynet::as_diffusion(x) y <- diff_models sim <- `0` <- NULL sims <- y %>% dplyr::select(sim, time, I) diff --git a/tests/testthat/test-model_distrib.R b/tests/testthat/test-model_distrib.R index 70c8b481..ca4fac83 100644 --- a/tests/testthat/test-model_distrib.R +++ b/tests/testthat/test-model_distrib.R @@ -7,6 +7,6 @@ test_that("test_distribution works", { test_that("test_fit works", { x <- play_diffusion(generate_random(15), transmissibility = 0.7) y <- play_diffusions(generate_random(15), transmissibility = 0.1, times = 40) - res <- test_fit(as_diffusion(x), y) + res <- test_fit(x, y) expect_output(print(res), "statistic") }) \ No newline at end of file diff --git a/tests/testthat/test-model_predict.R b/tests/testthat/test-model_predict.R index 1940ee1b..5c73ccba 100644 --- a/tests/testthat/test-model_predict.R +++ b/tests/testthat/test-model_predict.R @@ -1,7 +1,7 @@ test_that("predict.netlm works", { networkers <- ison_networkers %>% to_subgraph(Discipline == "Sociology") model1 <- net_regression(weight ~ ego(Citations) + alter(Citations) + sim(Citations), - networkers, times = 10) + networkers, times = 5) pred <- predict(model1, matrix(c(1,10,5,2),1,4)) expect_length(pred, 1) expect_type(pred, "double") @@ -11,7 +11,7 @@ test_that("predict.netlogit works", { networkers <- ison_networkers %>% to_subgraph(Discipline == "Sociology") %>% to_unweighted() model1 <- net_regression(. ~ ego(Citations) + alter(Citations) + sim(Citations), - networkers, times = 10) + networkers, times = 5) pred_link <- predict(model1, matrix(c(1,10,5,2),1,4), type = "link") pred_response <- predict(model1, matrix(c(1,10,5,2),1,4), type = "response") From a7430c96c92f37e0c58d149d20d3e41867d3aedc Mon Sep 17 00:00:00 2001 From: James Hollway Date: Fri, 17 Apr 2026 11:43:39 +0200 Subject: [PATCH 3/8] Added find_pkg_tutorial_paths() helper for identifying stocnet package tutorials --- tests/testthat/helper-functions.R | 10 ++++++++++ tests/testthat/test-tutorials_autograph.R | 2 +- tests/testthat/test-tutorials_manynet.R | 6 ++---- tests/testthat/test-tutorials_netrics.R | 2 +- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/tests/testthat/helper-functions.R b/tests/testthat/helper-functions.R index 6802fba1..342279c1 100644 --- a/tests/testthat/helper-functions.R +++ b/tests/testthat/helper-functions.R @@ -25,6 +25,16 @@ bot5 <- function(res, dec = 4){ unname(round(res, dec))[(lr-4):lr] } else unname(res)[(lr-2):lr] } + +find_pkg_tutorial_paths <- function(pkg) { + tute_folders <- list.dirs(system.file("tutorials", package = pkg), + recursive = F) + tute_files <- unlist(lapply(tute_folders, function(folder) { + list.files(folder, pattern = "*.Rmd", full.names = TRUE) + })) + tute_files +} + check_tute_rendering <- function(path, quiet = TRUE){ stopifnot(all(file.exists(path))) diff --git a/tests/testthat/test-tutorials_autograph.R b/tests/testthat/test-tutorials_autograph.R index 2b5aeb9e..11f33c55 100644 --- a/tests/testthat/test-tutorials_autograph.R +++ b/tests/testthat/test-tutorials_autograph.R @@ -2,7 +2,7 @@ test_that("autograph tutorials work", { for(tute.dir in list.dirs(system.file("tutorials", package = "autograph"), recursive = F)){ tute.file <- list.files(tute.dir, pattern = "*.Rmd", full.names = T) - expect_null(test_tutorials(tute.file)) + expect_null(check_tute_rendering(tute.file)) } }) diff --git a/tests/testthat/test-tutorials_manynet.R b/tests/testthat/test-tutorials_manynet.R index d2f6e55e..3af9bf83 100644 --- a/tests/testthat/test-tutorials_manynet.R +++ b/tests/testthat/test-tutorials_manynet.R @@ -1,7 +1,5 @@ test_that("manynet tutorials work", { - for(tute.dir in list.dirs(system.file("tutorials", package = "manynet"), - recursive = F)){ - tute.file <- list.files(tute.dir, pattern = "*.Rmd", full.names = T) - expect_null(test_tutorials(tute.file)) + for(tute in find_pkg_tutorial_paths("manynet")){ + expect_null(check_tute_rendering(tute)) } }) \ No newline at end of file diff --git a/tests/testthat/test-tutorials_netrics.R b/tests/testthat/test-tutorials_netrics.R index 912f638a..15b3c868 100644 --- a/tests/testthat/test-tutorials_netrics.R +++ b/tests/testthat/test-tutorials_netrics.R @@ -2,6 +2,6 @@ test_that("netrics tutorials work", { for(tute.dir in list.dirs(system.file("tutorials", package = "netrics"), recursive = F)){ tute.file <- list.files(tute.dir, pattern = "*.Rmd", full.names = T) - expect_null(test_tutorials(tute.file)) + expect_null(check_tute_rendering(tute.file)) } }) \ No newline at end of file From 6777011a22dbc75547cc36ef97db731bebd39cfb Mon Sep 17 00:00:00 2001 From: James Hollway Date: Fri, 17 Apr 2026 11:44:27 +0200 Subject: [PATCH 4/8] Added check_tute_functions() helper for seeing whether the solution functions in stocnet tutorials run without error or warning --- tests/testthat/helper-functions.R | 72 +++++++++++++++++++ tests/testthat/test-tutorials_manynet.R | 10 ++- tests/testthat/test-tutorials_migraph.R | 94 +++++++++++++++++++++++-- 3 files changed, 169 insertions(+), 7 deletions(-) diff --git a/tests/testthat/helper-functions.R b/tests/testthat/helper-functions.R index 342279c1..666272af 100644 --- a/tests/testthat/helper-functions.R +++ b/tests/testthat/helper-functions.R @@ -56,3 +56,75 @@ check_tute_rendering <- function(path, quiet = TRUE){ invisible(NULL) } +check_tute_functions <- function(path, skip = "ergm\\(", quiet = TRUE){ + tmp <- tempfile(fileext = ".R") + knitr::purl( + input = path, + output = tmp, + quiet = TRUE + ) + exprs <- parse(tmp) # your purled file + env <- new.env(parent = globalenv()) + + skip_rest <- FALSE + is_skipped_call <- function(expr) { + any(grepl(skip, deparse(expr))) + } + + for (i in seq_along(exprs)) { + if (skip_rest) { + skip(paste("Skipping dependent expressions in", basename(path))) + next + } + + if (is_skipped_call(exprs[[i]])) { + skip_rest <- TRUE + skip(paste("Skipping slow functions in", basename(path))) + next + } + + w <- NULL + e <- NULL + m <- NULL + + not_out <- withCallingHandlers( + tryCatch( + eval(exprs[[i]], envir = env), + error = function(err) { + e <<- err + NULL + } + ), + warning = function(wrn) { + w <<- wrn + invokeRestart("muffleWarning") + }, + message = function(msg) { + m <<- c(m, conditionMessage(msg)) + invokeRestart("muffleMessage") + } + ) + + # If there *was* a warning, check if it's a deprecated/defunct one + if (!is.null(w)) { + msg <- conditionMessage(w) + + # Only fail if it's a deprecated/defunct warning + if (!grepl("deprecate|defunct|moved", msg, ignore.case = TRUE)) { + w <- NULL + } + } + + # Now test what happened + expect_null( + e, + info = paste0("Error in expression ", i, + " of ", basename(path), ": ", deparse(exprs[[i]])) + ) + + expect_null( + w, + info = paste("Warning in expression", i, ":", deparse(exprs[[i]])) + ) + } +} diff --git a/tests/testthat/test-tutorials_manynet.R b/tests/testthat/test-tutorials_manynet.R index 3af9bf83..9d6dd37c 100644 --- a/tests/testthat/test-tutorials_manynet.R +++ b/tests/testthat/test-tutorials_manynet.R @@ -2,4 +2,12 @@ test_that("manynet tutorials work", { for(tute in find_pkg_tutorial_paths("manynet")){ expect_null(check_tute_rendering(tute)) } -}) \ No newline at end of file +}) + +test_that("manynet tutorial code runs without warnings or errors", { + skip_if_not_installed("manynet", minimum_version = "2.0.2") + for(tute in find_pkg_tutorial_paths("manynet")){ + expect_null(check_tute_functions(tute), + info = paste("Error in tutorial", basename(tute))) + } +}) diff --git a/tests/testthat/test-tutorials_migraph.R b/tests/testthat/test-tutorials_migraph.R index 1087eeab..3246326d 100644 --- a/tests/testthat/test-tutorials_migraph.R +++ b/tests/testthat/test-tutorials_migraph.R @@ -1,7 +1,89 @@ -test_that("migraph tutorials work", { - for(tute.dir in list.dirs(system.file("tutorials", package = "migraph"), - recursive = F)){ - tute.file <- list.files(tute.dir, pattern = "*.Rmd", full.names = T) - expect_null(test_tutorials(tute.file)) +# test_that("migraph tutorials render", { +# skip_on_cran() +# for(tute.dir in list.dirs(system.file("tutorials", package = "migraph"), +# recursive = F)){ +# tute.file <- list.files(tute.dir, pattern = "*.Rmd", full.names = T) +# expect_null(check_tute_rendering(tute.file)) +# } +# }) + +test_that("migraph tutorial code runs without warnings or errors", { + for(tute in find_pkg_tutorial_paths("migraph")){ + expect_null(check_tute_functions(tute, skip = "ergm\\(|play_diffusions\\("), + info = paste("Error in tutorial", basename(tute))) } -}) \ No newline at end of file +}) + +# test_that("migraph tutorial code runs without warnings or errors", { +# migraph_tutes <- list.dirs(system.file("tutorials", package = "migraph"), +# recursive = F) +# migraph_tutes <- migraph_tutes[!grepl("tutorial9", migraph_tutes)] +# for(tute.dir in migraph_tutes){ +# tute.file <- list.files(tute.dir, pattern = "*.Rmd", full.names = T) +# tmp <- tempfile(fileext = ".R") +# knitr::purl( +# input = tute.file, +# output = tmp, +# quiet = TRUE +# ) +# exprs <- parse(tmp) # your purled file +# env <- new.env(parent = globalenv()) +# +# skip_rest <- FALSE +# is_ergm_call <- function(expr) { +# any(grepl("ergm\\(", deparse(expr))) +# } +# +# for (i in seq_along(exprs)) { +# +# if (skip_rest) { +# skip(paste("Skipping dependent expressions in", basename(tute.file))) +# next +# } +# +# if (is_ergm_call(exprs[[i]])) { +# skip_rest <- TRUE +# skip(paste("Skipping ergm model in", basename(tute.file))) +# next +# } +# +# w <- NULL +# e <- NULL +# +# not_out <- testthat::capture_output(withCallingHandlers( +# tryCatch( +# eval(exprs[[i]], envir = env), +# error = function(err) { +# e <<- err +# NULL +# } +# ), +# warning = function(wrn) { +# w <<- wrn +# invokeRestart("muffleWarning") +# } +# )) +# +# # If there *was* a warning, check if it's a deprecated/defunct one +# if (!is.null(w)) { +# msg <- conditionMessage(w) +# +# # Only fail if it's a deprecated/defunct warning +# if (grepl("deprecated|defunct|moved", msg, ignore.case = TRUE)) { +# fail(paste( +# "Deprecated/defunct warning in expression", i, ":\n", +# deparse(exprs[[i]]), "\nMessage:", msg +# )) +# } +# } +# +# +# # Now test what happened +# expect_null( +# e, +# info = paste0("Error in expression ", i, +# " of ", basename(tute.file), ": ", deparse(exprs[[i]])) +# ) +# } +# } +# }) \ No newline at end of file From 8157bdafcc7d21b0a38eaf2ba1995d5f1e574075 Mon Sep 17 00:00:00 2001 From: James Hollway Date: Fri, 17 Apr 2026 11:46:16 +0200 Subject: [PATCH 5/8] Updated examples across migraph tutorials where errors could creep in --- DESCRIPTION | 4 ++-- NEWS.md | 17 ++++++++++++++++- cran-comments.md | 2 +- inst/tutorials/tutorial0/tutorial0.Rmd | 2 +- inst/tutorials/tutorial7/diffusion.Rmd | 22 +++++++++++----------- inst/tutorials/tutorial8/diversity.Rmd | 3 ++- inst/tutorials/tutorial9/ergm.Rmd | 2 +- 7 files changed, 34 insertions(+), 18 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 28ff21df..7ca3a33d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: migraph Title: Inferential Methods for Multimodal and Other Networks -Version: 1.6.1 -Date: 2026-04-14 +Version: 1.6.2 +Date: 2026-04-17 Description: A set of tools for testing networks. It includes functions for univariate and multivariate conditional uniform graph and quadratic assignment procedure testing, diff --git a/NEWS.md b/NEWS.md index 612d868f..76f5a2fd 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,21 @@ +# migraph 1.6.2 + +2026-04-17 + +## Testing + +- Fixed namespace issues + +## Tutorials + +- Added function testing for migraph tutorials +- Added function testing for manynet tutorials (> v2.0.2) +- Updated examples in solutions in migraph tutorials where errors could creep in +- Skipped extracting some solutions in migraph where errors could creep in + # migraph 1.6.1 -2026-04-13 +2026-04-14 ## Package diff --git a/cran-comments.md b/cran-comments.md index 8d0c3374..bd6a0342 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -9,4 +9,4 @@ 0 errors | 0 warnings | 0 notes -- Updates to bring autograph into line with latest version of manynet (> v2.0.0) +- Updates to improve testing length diff --git a/inst/tutorials/tutorial0/tutorial0.Rmd b/inst/tutorials/tutorial0/tutorial0.Rmd index a1af70dd..49f93cd7 100644 --- a/inst/tutorials/tutorial0/tutorial0.Rmd +++ b/inst/tutorials/tutorial0/tutorial0.Rmd @@ -127,7 +127,7 @@ Much more flexible than a high school calculator! It is important to note that R is case-sensitive, i.e. `Print("Hello World")` will not work. Try it! -```{r Print-hello-world, exercise = TRUE} +```{r Print-hello-world, exercise = TRUE, purl=FALSE} Print("Hello World") ``` diff --git a/inst/tutorials/tutorial7/diffusion.Rmd b/inst/tutorials/tutorial7/diffusion.Rmd index c5042758..68cb6907 100644 --- a/inst/tutorials/tutorial7/diffusion.Rmd +++ b/inst/tutorials/tutorial7/diffusion.Rmd @@ -202,7 +202,7 @@ You can start the infection in California by specifying `seeds = 5`. ```{r usstates-hint} us_diff <- play_diffusion(irps_usgeo, seeds = 5) plot(us_diff) -graphr(us_diff) +# graphr(us_diff) net_by_infection_complete(us_diff) ``` @@ -577,7 +577,7 @@ to indicate that in only 1/2 cases is contagion successful. ```{r diffusions, exercise = TRUE, fig.width=9} rando <- generate_random(32, 0.1) graphr(rando) -plot(play_diffusions(rando, transmissibility = 0.5, times = 5, steps = 10)) +plot(play_diffusions(ison_lawfirm, transmissibility = 0.5, times = 5, steps = 10)) ``` Note that in this plot the number of new infections is not plotted @@ -610,7 +610,7 @@ plot(play_diffusions(____, recovery = ____)) ``` ```{r sir-solution} -plot(play_diffusions(rando, recovery = 0.2)) +plot(play_diffusions(ison_lawfirm, recovery = 0.2)) ``` What we see in these kinds of models is typically a spike in infections @@ -624,8 +624,8 @@ which should average out these differences and make the results more reliable. ``` -```{r sirtimes-solution} -plot(play_diffusions(rando, recovery = 0.2, times = 100)) +```{r sirtimes-solution, purl=FALSE} +plot(play_diffusions(ison_lawfirm, recovery = 0.2, times = 100)) ``` ### SIRS models @@ -642,7 +642,7 @@ Play a single diffusion so that you can see what's going on in a particular run. ``` ```{r sirs-solution} -plot(play_diffusion(rando, recovery = 0.2, waning = 0.05)) +plot(play_diffusion(ison_lawfirm, recovery = 0.2, waning = 0.05)) ``` @@ -659,7 +659,7 @@ Depending on your particular simulation, there might be some variation, so let's run this same diffusion but multiple (100?) times. -```{r sirstimes-solution, exercise.setup = "diffusions", exercise = TRUE, fig.width=9} +```{r sirstimes-solution, exercise.setup = "diffusions", exercise = TRUE, fig.width=9, purl=FALSE} plot(play_diffusions(rando, recovery = 0.2, waning = 0.05, times = 100)) ``` @@ -689,10 +689,10 @@ Play a single diffusion so that you can see what's going on in a particular run. ```{r seir-solution} set.seed(123) -plot(play_diffusion(rando, seeds = 10, latency = 0.25, recovery = 0.2)) +plot(play_diffusion(ison_lawfirm, seeds = 10, latency = 0.75, recovery = 0.2)) # visualise diffusion with latency and recovery -graphs(play_diffusion(rando, seeds = 10, latency = 0.25, recovery = 0.2), waves = c(1,5,10)) +# graphs(play_diffusion(ison_lawfirm, seeds = 10, latency = 0.75, recovery = 0.2), waves = c(1,5,10)) ``` ## Make it stop @@ -716,7 +716,7 @@ So how can we establish the $R_0$ here? We can use `net_by_reproduction()`. ```{r r0, exercise = TRUE, exercise.setup = "diffusions", fig.width=9} -rd_diff <- play_diffusion(rando, transmissibility = 0.25, recovery = 0.05) +rd_diff <- play_diffusion(ison_lawfirm, transmissibility = 0.25, recovery = 0.05) plot(rd_diff) # R-nought net_by_reproduction(rd_diff) @@ -777,7 +777,7 @@ The unnormalised version gives the number of nodes that would need to be vaccina Ok, so let's try this strategy. ```{r vaccinate, exercise = TRUE, exercise.setup = "diffusions", fig.width=9} -rd_diff_vacc <- play_diffusion(rando, transmissibility = 0.25, recovery = 0.05, +rd_diff_vacc <- play_diffusion(ison_lawfirm, transmissibility = 0.25, recovery = 0.05, immune = 2:9) plot(rd_diff_vacc) net_by_infection_total(rd_diff_vacc) diff --git a/inst/tutorials/tutorial8/diversity.Rmd b/inst/tutorials/tutorial8/diversity.Rmd index b0906e65..a9d3b1f9 100644 --- a/inst/tutorials/tutorial8/diversity.Rmd +++ b/inst/tutorials/tutorial8/diversity.Rmd @@ -118,7 +118,8 @@ marvel_friends ``` ```{r friends-solution} -marvel_friends <- to_unsigned(ison_marvel_relationships, keep = "positive") +marvel_friends <- to_uniplex(fict_marvel, "relationship") +marvel_friends <- to_unsigned(marvel_friends, keep = "positive") marvel_friends <- to_giant(marvel_friends) marvel_friends <- marvel_friends %>% to_subgraph(Appearances >= mean(Appearances)) marvel_friends diff --git a/inst/tutorials/tutorial9/ergm.Rmd b/inst/tutorials/tutorial9/ergm.Rmd index 87c77ba3..cf7d196b 100644 --- a/inst/tutorials/tutorial9/ergm.Rmd +++ b/inst/tutorials/tutorial9/ergm.Rmd @@ -573,7 +573,7 @@ see papers in e.g. *Social Networks* v.29 and *J Stat Software* v. 24. Now let's try to fit a triangle model like with the Florentine dataset above: -```{r magnmark1, exercise = TRUE} +```{r magnmark1, exercise = TRUE, purl=FALSE} magn.mark1 <- ergm(magnolia ~ edges + triangle) ``` From c53479a9a8e40f15bad8d352ca19129e645b2944 Mon Sep 17 00:00:00 2001 From: James Hollway Date: Fri, 17 Apr 2026 21:20:12 +0200 Subject: [PATCH 6/8] Using check_tute_functions() for autograph and netrics tutorials too --- NEWS.md | 2 + tests/testthat/helper-functions.R | 3 +- tests/testthat/test-tutorials_autograph.R | 16 +++-- tests/testthat/test-tutorials_migraph.R | 74 ----------------------- tests/testthat/test-tutorials_netrics.R | 16 +++-- 5 files changed, 26 insertions(+), 85 deletions(-) diff --git a/NEWS.md b/NEWS.md index 76f5a2fd..daa98584 100644 --- a/NEWS.md +++ b/NEWS.md @@ -12,6 +12,8 @@ - Added function testing for manynet tutorials (> v2.0.2) - Updated examples in solutions in migraph tutorials where errors could creep in - Skipped extracting some solutions in migraph where errors could creep in +- Removed `test_tutorials()` from the public API; + use `run_tute()` and `extract_tute()` for supported tutorial execution and extraction workflows # migraph 1.6.1 diff --git a/tests/testthat/helper-functions.R b/tests/testthat/helper-functions.R index 666272af..8c85a0ff 100644 --- a/tests/testthat/helper-functions.R +++ b/tests/testthat/helper-functions.R @@ -37,6 +37,7 @@ find_pkg_tutorial_paths <- function(pkg) { check_tute_rendering <- function(path, quiet = TRUE){ + skip_if_not_installed("rmarkdown") stopifnot(all(file.exists(path))) for(i in path){ @@ -61,7 +62,7 @@ check_tute_functions <- function(path, skip = "ergm\\(", quiet = TRUE){ knitr::purl( input = path, output = tmp, - quiet = TRUE + quiet = quiet ) exprs <- parse(tmp) # your purled file env <- new.env(parent = globalenv()) diff --git a/tests/testthat/test-tutorials_autograph.R b/tests/testthat/test-tutorials_autograph.R index 11f33c55..fa4c0700 100644 --- a/tests/testthat/test-tutorials_autograph.R +++ b/tests/testthat/test-tutorials_autograph.R @@ -1,8 +1,14 @@ -test_that("autograph tutorials work", { - for(tute.dir in list.dirs(system.file("tutorials", package = "autograph"), - recursive = F)){ - tute.file <- list.files(tute.dir, pattern = "*.Rmd", full.names = T) - expect_null(check_tute_rendering(tute.file)) +# test_that("autograph tutorials work", { +# for(tute in find_pkg_tutorial_paths("autograph")){ +# expect_null(check_tute_rendering(tute)) +# } +# }) + +test_that("autograph tutorial code runs without warnings or errors", { + skip_if_not_installed("autograph", minimum_version = "1.0.0") + for(tute in find_pkg_tutorial_paths("autograph")){ + expect_null(check_tute_functions(tute), + info = paste("Error in tutorial", basename(tute))) } }) diff --git a/tests/testthat/test-tutorials_migraph.R b/tests/testthat/test-tutorials_migraph.R index 3246326d..ee90d76d 100644 --- a/tests/testthat/test-tutorials_migraph.R +++ b/tests/testthat/test-tutorials_migraph.R @@ -13,77 +13,3 @@ test_that("migraph tutorial code runs without warnings or errors", { info = paste("Error in tutorial", basename(tute))) } }) - -# test_that("migraph tutorial code runs without warnings or errors", { -# migraph_tutes <- list.dirs(system.file("tutorials", package = "migraph"), -# recursive = F) -# migraph_tutes <- migraph_tutes[!grepl("tutorial9", migraph_tutes)] -# for(tute.dir in migraph_tutes){ -# tute.file <- list.files(tute.dir, pattern = "*.Rmd", full.names = T) -# tmp <- tempfile(fileext = ".R") -# knitr::purl( -# input = tute.file, -# output = tmp, -# quiet = TRUE -# ) -# exprs <- parse(tmp) # your purled file -# env <- new.env(parent = globalenv()) -# -# skip_rest <- FALSE -# is_ergm_call <- function(expr) { -# any(grepl("ergm\\(", deparse(expr))) -# } -# -# for (i in seq_along(exprs)) { -# -# if (skip_rest) { -# skip(paste("Skipping dependent expressions in", basename(tute.file))) -# next -# } -# -# if (is_ergm_call(exprs[[i]])) { -# skip_rest <- TRUE -# skip(paste("Skipping ergm model in", basename(tute.file))) -# next -# } -# -# w <- NULL -# e <- NULL -# -# not_out <- testthat::capture_output(withCallingHandlers( -# tryCatch( -# eval(exprs[[i]], envir = env), -# error = function(err) { -# e <<- err -# NULL -# } -# ), -# warning = function(wrn) { -# w <<- wrn -# invokeRestart("muffleWarning") -# } -# )) -# -# # If there *was* a warning, check if it's a deprecated/defunct one -# if (!is.null(w)) { -# msg <- conditionMessage(w) -# -# # Only fail if it's a deprecated/defunct warning -# if (grepl("deprecated|defunct|moved", msg, ignore.case = TRUE)) { -# fail(paste( -# "Deprecated/defunct warning in expression", i, ":\n", -# deparse(exprs[[i]]), "\nMessage:", msg -# )) -# } -# } -# -# -# # Now test what happened -# expect_null( -# e, -# info = paste0("Error in expression ", i, -# " of ", basename(tute.file), ": ", deparse(exprs[[i]])) -# ) -# } -# } -# }) \ No newline at end of file diff --git a/tests/testthat/test-tutorials_netrics.R b/tests/testthat/test-tutorials_netrics.R index 15b3c868..0140489b 100644 --- a/tests/testthat/test-tutorials_netrics.R +++ b/tests/testthat/test-tutorials_netrics.R @@ -1,7 +1,13 @@ -test_that("netrics tutorials work", { - for(tute.dir in list.dirs(system.file("tutorials", package = "netrics"), - recursive = F)){ - tute.file <- list.files(tute.dir, pattern = "*.Rmd", full.names = T) - expect_null(check_tute_rendering(tute.file)) +# test_that("netrics tutorials work", { +# for(tute in find_pkg_tutorial_paths("netrics")){ +# expect_null(check_tute_rendering(tute)) +# } +# }) + +test_that("netrics tutorial code runs without warnings or errors", { + skip_if_not_installed("netrics", minimum_version = "0.2.2") + for(tute in find_pkg_tutorial_paths("netrics")){ + expect_null(check_tute_functions(tute), + info = paste("Error in tutorial", basename(tute))) } }) \ No newline at end of file From 6a31d742a9f66fb7f41c584e23b4772945e756e6 Mon Sep 17 00:00:00 2001 From: James Hollway Date: Fri, 17 Apr 2026 21:20:35 +0200 Subject: [PATCH 7/8] Don't purl write chunks --- inst/tutorials/tutorial0/tutorial0.Rmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inst/tutorials/tutorial0/tutorial0.Rmd b/inst/tutorials/tutorial0/tutorial0.Rmd index 49f93cd7..d97cc8ea 100644 --- a/inst/tutorials/tutorial0/tutorial0.Rmd +++ b/inst/tutorials/tutorial0/tutorial0.Rmd @@ -360,7 +360,7 @@ list.files() # This tells you what files are in your working directory Compare the above with functions like the following, which enables you to write an object out of R to some path on your hard-drive that you specify: -```{r function-write, exercise = TRUE} +```{r function-write, exercise = TRUE, purl=FALSE} write.csv(x = mydf, file = "~/Desktop/jamesdf.csv") ``` From fe79f87bb8e752ab92bb4637338fbfab3dc4075c Mon Sep 17 00:00:00 2001 From: James Hollway Date: Fri, 17 Apr 2026 21:30:21 +0200 Subject: [PATCH 8/8] autograph tutorials only from version 1.0.1 or greater --- tests/testthat/test-tutorials_autograph.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test-tutorials_autograph.R b/tests/testthat/test-tutorials_autograph.R index fa4c0700..d41d50a0 100644 --- a/tests/testthat/test-tutorials_autograph.R +++ b/tests/testthat/test-tutorials_autograph.R @@ -5,7 +5,7 @@ # }) test_that("autograph tutorial code runs without warnings or errors", { - skip_if_not_installed("autograph", minimum_version = "1.0.0") + skip_if_not_installed("autograph", minimum_version = "1.0.1") for(tute in find_pkg_tutorial_paths("autograph")){ expect_null(check_tute_functions(tute), info = paste("Error in tutorial", basename(tute)))