find_all_objects <- find_all_objects # case 1 test_that("magic N", { N <- 5 design <- declare_model(N = N, k = rnorm(N)) + NULL expect_equal(nrow(draw_data(design)),5) rm(N) expect_equal(nrow(draw_data(design)),5) expect_true(nrow(find_all_objects(design)) == 1) }) test_that("pars are saved", { n <- 5 b <- 2 f <- function(x, b) b*x design <- declare_model(N = n, x = runif(N), B = b) + declare_model(y = f(x, b)) expect_equal(nrow(draw_data(design)),5) rm(b) expect_equal(nrow(draw_data(design)),5) rm(f) expect_equal(nrow(draw_data(design)),5) }) test_that("all steps", { b1 <- 1 b2 <- 2 b3 <- 3 b4 <- 4 b5 <- 5 b6 <- 6 b7 <- 7 b8 <- 8 design <- declare_model(N = 20, Y = rnorm(N), B = b1) + declare_inquiry(Q = b2) + declare_assignment(Z = simple_ra(N, prob = b3/b3)) + declare_potential_outcomes(Y ~ Z + b4) + declare_sampling(S = complete_rs(N = N, n = b5)) + declare_measurement(K = b6) + declare_estimator(Y ~ 1, subset = Y < b7) + declare_model(D = 1) rm(b1, b2, b3, b4, b5, b6, b7, b8) x <- find_all_objects(design) x # appears in every step (step 4 not yet functioning) expect_true(all(c(1,2,3,5,6,7) %in% x$step)) }) test_that("n is saved", { n <- 5 b <- 2 f <- function(x, b) b*x step <- declare_model(N = n, x = runif(N)) expect_true( nrow(step()) == 5) rm(n) expect_true( nrow(step()) == 5) }) test_that("find object after redesign", { n <- 5 b <- 2 r <- 2 f <- function(x, b) b*x + r design <- declare_model(N = n, x = runif(N), w = f(x, b), s = 2*w) + NULL rm(n,b,r, f) find_all_objects(design) design <- modify_edit(design, n = 3) expect_true(draw_data(design) |> nrow() ==3) find_all_objects(design) design <- redesign(design, n = 7) expect_true(draw_data(design) |> nrow() ==7) }) test_that("formula OK", { b = 2; n = 2 step <- declare_model(N = n, potential_outcomes( Y ~ b*Z)) rm(b) expect_true( all(step()[1, 2:3] == c(0,2))) }) test_that("potential outcomes OK", { b = 2 d <- declare_model(N = 2, B = b) + declare_potential_outcomes( Y ~ b*Z) rm(b) expect_true(all( draw_data(d)[1, 3:4] == c(0,2))) }) test_that("deeper arguments saved", { n <- 5 b <- 0 f <- function(x) b*x step <- declare_model(N = n, x = runif(N), y = f(x)) expect_true( mean(step()$y) == 0) rm(b) expect_true( mean(step()$y) == 0) }) test_that("data saved", { ddf <- data.frame(X = runif(5)) step <- declare_model(data = ddf) step() rm(ddf) expect_true(nrow(step()) == 5) find_all_objects(step + NULL) }) # edge case: test_that("data called 'df' (or other function name)", { df <- data.frame(X = runif(5)) step <- declare_model(data = df) step() rm(df) expect_true(nrow(step()) == 5) }) test_that("estimator steps", { n <- 100 b <- B <- .2 d <- declare_model(N = n, Y = runif(N)) + declare_estimator(Y ~ 1, subset = Y < b) expect_true(draw_estimates(d)$estimate < B) rm(b) expect_true(draw_estimates(d)$estimate < B) }) test_that("custom estimator", { my_estimator <- function(data) { data.frame(estimate = mean(data$Y)) } design <- declare_model( N = 500, Y = rnorm(N, sd = 0.25) ) + declare_inquiry(Y_bar = mean(Y)) + declare_estimator(handler = label_estimator(my_estimator), label = "mean", inquiry = "Y_bar") expect_true(nrow(run_design(design)) ==1) rm(my_estimator) expect_true(nrow(run_design(design)) ==1) }) test_that("potential outcomes environment", { a <- .2 b <- 2 m <- declare_model( N = 5, U = rnorm(N, sd = a), potential_outcomes(Y ~ b) ) expect_true(nrow(m()) ==5) expect_true(environment(environment(m)$dots$U)$a ==a) expect_true(environment(environment(m)$dots[[4]])$b ==b) rm(a,b) expect_true(nrow(m()) ==5) }) test_that("check not overriding pipe", { U <- 1:5 m <- declare_model( N = 5, U = rnorm(N), Y = U ) # Global U is scooped up but not actually required or used expect_true(all(environment(environment(m)$dots$Y)$U == U)) expect_true(m()$Y[1] !=1) }) # Issue here test_that("check not overriding pipe", { n1 <- 3 n2 <- 4 m <- declare_model( classrooms = add_level(n1), individuals = add_level(n2) ) rm(n1, n2) expect_true(m() |> nrow() ==12) }) # Design 16.1 test_that("Design 16.1", { skip_if_not_installed("CausalQueries") library(rdss) # for helper functions library(CausalQueries) causal_model <- make_model("X -> M -> Y <- W -> M") |> set_restrictions("(M[X=1] < M[X=0]) | (M[X=1, W=1] == M[X=0, W=1])") |> set_restrictions("(Y[M=1] < Y[M=0]) | (Y[M=1, W=1] == Y[M=0, W=1])") strategies = c("X-Y", "X-Y-M", "X-Y-W", "X-Y-W-M") declaration_16.1 <- declare_model(draw_causal_type(causal_model)) + declare_inquiry( CoE = query_distribution( causal_model, query = "Y[X=1] - Y[X=0]", parameters = causal_type)) + declare_measurement( handler = function(data) causal_model |> make_data(parameters = data$causal_type)) + declare_estimator( handler = label_estimator(process_tracing_estimator), causal_model = causal_model, query = "Y[X=1] - Y[X=0]", strategies = strategies) rm(causal_model, strategies) expect_true(nrow(draw_data(declaration_16.1)) == 1) }) # Design 16.5 test_that("Design 16.5", { skip_if_not_installed("rdss") skip_if_not_installed("rdrobust") library(rdss) # for helper functions library(rdrobust) cutoff <- 0.5 control <- function(X) { as.vector(poly(X - cutoff, 4, raw = TRUE) %*% c(.7, -.8, .5, 1))} treatment <- function(X) { as.vector(poly(X - cutoff, 4, raw = TRUE) %*% c(0, -1.5, .5, .8)) + .15} declaration_16.5 <- declare_model( N = 500, U = rnorm(N, 0, 0.1), X = runif(N, 0, 1) + U, D = 1 * (X > cutoff), Y_D_0 = control(X) + U, Y_D_1 = treatment(X) + U ) + declare_inquiry(LATE = treatment(cutoff) - control(cutoff)) + declare_measurement(Y = reveal_outcomes(Y ~ D)) + declare_estimator( Y, X, c = cutoff, term = "Bias-Corrected", .method = rdrobust_helper, inquiry = "LATE", label = "optimal" ) rm(cutoff, control, treatment) expect_true(nrow(draw_data(declaration_16.5)) == 500) }) # Inside function test_that("parameter assigned in function", { designer <- function(n = 1) declare_model(N = n) + NULL expect_true(nrow(draw_data(designer(3))) == 3) designer <- function() { n = 4 d <- declare_model(N = n) + NULL rm(n) d } expect_true(nrow(draw_data(designer())) == 4) }) test_that("runif not saved", { n <- 5 design <- declare_model(N = n, x = runif(N)) + NULL expect_false("runif" %in% find_all_objects(design)$name) }) test_that("functions saved", { f <- runif n <- 5 design <- declare_model(N = n, x = f(N)) + NULL expect_true("f" %in% find_all_objects(design)$name) }) test_that("environment sharing", { N <- 5 design <- declare_model(N = N, x = runif(N)) + NULL design_2 <- modify_edit(design, N = 6) design_3 <- modify_edit(design, N = 7) find_all_objects(design_2) find_all_objects(design_3) expect_false("runif" %in% find_all_objects(design)$name) }) # Test with formula test_that("param in po formula quosure", { N <- 2 b <- .2 design <- declare_model(N = N, U = rnorm(N)) + declare_potential_outcomes(Y ~ b*N*Z) rm(N, b) draw_data(design) obs <- find_all_objects(design) expect_true(all(obs$name == c("N", "b"))) design <- redesign(design, N = 4, b =.1) expect_true(all(find_all_objects(design) |> dplyr::pull(value_str) == c(4, .1))) }) # Currently failing (saving OK, but recovery not) # to do: remove N from handlr environment test_that("param in handler", { N <- 2 b <- .2 f <- function(...) fabricate(...) hdl <- function(...) f(..., extra = rnorm(N, b)) hdl ls(environment(hdl)) hdl <- capture_function_dependencies(hdl) rm(N, b, f) expect_true(all(ls(environment(hdl)) == c("b", "f"))) }) test_that("behavior when packaged used and removed", { skip_if_not_installed("CausalQueries") library(CausalQueries) model_handler <- function(N) make_model() |> make_data(N) n <- 2 design <- declare_model(handler = model_handler, N = n) + NULL rm(n) obs <- find_all_objects(design) obs expect_true(nrow(draw_data(design)) ==2) detach("package:CausalQueries", unload = TRUE) # Object can be inspected expect_error(find_all_objects(design), NA) # But does not run without a path to the functions used expect_error(draw_data(design)) }) test_that("variables confused for arguments", { n <- 1 design <- declare_model(N = n, A = 1) + declare_model(B = A) + declare_potential_outcomes(Y ~ Z + A) expect_true(find_all_objects(design) |> nrow() ==1) n <- 1 step_1 <- declare_model(N = n, A = 1) step_2 <- declare_model(B = A) step_3 <- declare_potential_outcomes(Y ~ Z + A) design <- step_1 + step_2 + step_3 expect_true(find_all_objects(design) |> nrow() ==1) }) test_that("multiple appearances", { # Two different values for a parameter can be saved in different steps # But redesign replaces all values a <- 2 step_1 <- declare_model(N = 1, A1 = a) a <- 1 step_2 <- declare_model(A2 = a) rm(a) design <- step_1 + step_2 expect_true(all(find_all_objects(design)$value_str == 2:1)) design <- design |> redesign(a = 3) expect_true(all(find_all_objects(design)$value_str == 3)) }) test_that("many parameters", { a = 1; b = 2; c = 3; d= 4; e = 5; f = 6; g = 7; h = 8; i = 9; j = 10 design <- declare_model(N = 1, A1 = a + b + c + d + e + f + g + h + i + j) + NULL out <- capture.output(DeclareDesign:::print.design(design)) expect_true(any(grepl("a, b, c, d, e, f, g, h, i, j", out))) }) test_that("declare_population handles environments OK", { # 1 simple a <- 1 design <- declare_population(N = 5, u_1 = rnorm(N), u_2 = rnorm(N)) + declare_potential_outcomes(formula = Y ~ a) rm(a) expect_true(nrow(draw_data(design)) == 5) # 2 with conditions a <- 1.1 design <- declare_population(N = 5, u_1 = rnorm(N), u_2 = rnorm(N)) + declare_potential_outcomes(formula = Y ~ a + (Z=="1") + rnorm(N)/100, conditions = list(Z = c("1", "2"))) rm(a) expect_true(sd(draw_data(design)$Y_Z_1) != 0) a <- 1.12 design <- declare_population(N = 5, u_1 = 1.3, u_2 = rnorm(N)) + declare_potential_outcomes(formula = Y ~ a + u_1, conditions = list(Z = c("1", "2"))) rm(a) expect_true(mean(draw_data(design)$Y_Z_1) == 2.42) # sd type parameter handled properly sd <- 1000 design <- declare_model(N = 5, u_W = rnorm(N), u_Y = rnorm(n = N, mean = .5 * u_W, sd = sqrt(1 - .5^2))) + declare_potential_outcomes(Y ~ (u_Y * sd )) design expect_true(sd(draw_data(design)$Y_Z_1) > 5) })