Nothing
# Test coverage for R/motifs.R - Additional coverage tests (41)
# Targets uncovered code paths, edge cases, and functions not in 40/43
# =============================================================================
# TEST SETUP AND HELPER FUNCTIONS
# =============================================================================
# Create test matrices for motif analysis
skip_on_cran()
create_directed_matrix <- function(n = 5, seed = 42) {
set.seed(seed)
mat <- matrix(sample(0:1, n * n, replace = TRUE, prob = c(0.6, 0.4)), n, n)
diag(mat) <- 0
rownames(mat) <- colnames(mat) <- LETTERS[1:n]
mat
}
create_undirected_matrix <- function(n = 5, seed = 42) {
set.seed(seed)
mat <- matrix(0, n, n)
upper_idx <- which(upper.tri(mat))
selected <- sample(upper_idx, length(upper_idx) %/% 2)
mat[selected] <- 1
mat <- mat + t(mat)
rownames(mat) <- colnames(mat) <- LETTERS[1:n]
mat
}
create_weighted_matrix <- function(n = 5, seed = 42) {
set.seed(seed)
mat <- matrix(sample(0:10, n * n, replace = TRUE), n, n)
diag(mat) <- 0
rownames(mat) <- colnames(mat) <- LETTERS[1:n]
mat
}
# =============================================================================
# GET_EDGE_LIST FUNCTION TESTS
# =============================================================================
test_that("get_edge_list errors on non-tna input", {
mat <- create_directed_matrix(5)
expect_error(get_edge_list(mat), "tna object")
expect_error(get_edge_list("invalid"), "tna object")
expect_error(get_edge_list(list(a = 1)), "tna object")
})
test_that("get_edge_list works with tna object", {
skip_if_not_installed("tna")
# Create a simple tna model for testing
set.seed(123)
test_data <- data.frame(
V1 = sample(LETTERS[1:3], 50, replace = TRUE),
V2 = sample(LETTERS[1:3], 50, replace = TRUE),
V3 = sample(LETTERS[1:3], 50, replace = TRUE),
V4 = sample(LETTERS[1:3], 50, replace = TRUE)
)
mod <- tna::tna(test_data)
# Test with by_individual = TRUE
edges <- get_edge_list(mod, by_individual = TRUE)
expect_true(is.data.frame(edges))
expect_true(all(c("id", "from", "to", "count") %in% names(edges)))
expect_true(all(edges$count >= 0))
# Test with by_individual = FALSE
agg_edges <- get_edge_list(mod, by_individual = FALSE)
expect_true(is.data.frame(agg_edges))
expect_true(all(c("from", "to", "count") %in% names(agg_edges)))
expect_false("id" %in% names(agg_edges))
# Test drop_zeros = FALSE
edges_with_zeros <- get_edge_list(mod, by_individual = TRUE, drop_zeros = FALSE)
expect_true(is.data.frame(edges_with_zeros))
agg_with_zeros <- get_edge_list(mod, by_individual = FALSE, drop_zeros = FALSE)
expect_true(is.data.frame(agg_with_zeros))
})
# =============================================================================
# EXTRACT_MOTIFS WITH TNA OBJECT TESTS
# =============================================================================
test_that("extract_motifs works with tna object", {
skip_if_not_installed("tna")
skip_if_not_installed("igraph")
set.seed(456)
test_data <- data.frame(matrix(
sample(c("A", "B", "C", "D"), 200, replace = TRUE),
nrow = 50, ncol = 4
))
mod <- tna::tna(test_data)
result <- extract_motifs(mod, pattern = "all", min_transitions = 0)
expect_true(is.null(result) || inherits(result, "cograph_motif_analysis"))
if (!is.null(result)) {
expect_true("results" %in% names(result))
expect_true("type_summary" %in% names(result))
expect_equal(result$params$level, "individual")
}
})
test_that("extract_motifs with tna uses correct level", {
skip_if_not_installed("tna")
skip_if_not_installed("igraph")
set.seed(789)
test_data <- data.frame(matrix(
sample(c("X", "Y", "Z"), 150, replace = TRUE),
nrow = 30, ncol = 5
))
mod <- tna::tna(test_data)
# Default level for tna should be individual
result_default <- extract_motifs(mod, pattern = "all", min_transitions = 0)
if (!is.null(result_default)) {
expect_equal(result_default$params$level, "individual")
}
# Explicit aggregate level
result_agg <- extract_motifs(mod, level = "aggregate", pattern = "all", min_transitions = 0)
if (!is.null(result_agg)) {
expect_equal(result_agg$params$level, "aggregate")
}
})
# =============================================================================
# .MOTIF_CENSUS_UNDIRECTED ADDITIONAL TESTS
# =============================================================================
test_that("motif_census undirected handles various methods", {
skip_if_not_installed("igraph")
# Create a symmetric matrix
mat <- matrix(c(
0, 1, 1, 0, 1,
1, 0, 1, 1, 0,
1, 1, 0, 1, 1,
0, 1, 1, 0, 1,
1, 0, 1, 1, 0
), 5, 5)
rownames(mat) <- colnames(mat) <- LETTERS[1:5]
# Configuration method
result_config <- motif_census(mat, n_random = 5, method = "configuration", seed = 42)
expect_s3_class(result_config, "cograph_motifs")
expect_false(result_config$directed)
# GNM method
result_gnm <- motif_census(mat, n_random = 5, method = "gnm", seed = 42)
expect_s3_class(result_gnm, "cograph_motifs")
expect_equal(result_gnm$method, "gnm")
})
# =============================================================================
# .GENERATE_RANDOM_GRAPH ADDITIONAL TESTS
# =============================================================================
test_that(".generate_random_graph handles undirected with configuration", {
skip_if_not_installed("igraph")
generate_random <- cograph:::.generate_random_graph
# Undirected graph
mat <- create_undirected_matrix(6, seed = 111)
g <- igraph::graph_from_adjacency_matrix(mat, mode = "undirected")
g_rand <- generate_random(g, "configuration")
expect_true(igraph::is_igraph(g_rand))
expect_false(igraph::is_directed(g_rand))
# Verify degree sequence is preserved (approximately)
orig_deg <- sort(igraph::degree(g))
rand_deg <- sort(igraph::degree(g_rand))
expect_equal(length(orig_deg), length(rand_deg))
})
test_that(".generate_random_graph handles directed with gnm", {
skip_if_not_installed("igraph")
generate_random <- cograph:::.generate_random_graph
mat <- create_directed_matrix(6, seed = 222)
g <- igraph::graph_from_adjacency_matrix(mat, mode = "directed")
g_rand <- generate_random(g, "gnm")
expect_true(igraph::is_igraph(g_rand))
expect_true(igraph::is_directed(g_rand))
# Edge count should be approximately preserved
expect_equal(igraph::vcount(g_rand), igraph::vcount(g))
})
# =============================================================================
# PLOT.COGRAPH_MOTIFS NETWORK TYPE EDGE CASES
# =============================================================================
test_that("plot.cograph_motifs network type renders all standard triads", {
skip_if_not_installed("igraph")
skip_if_not_installed("ggplot2")
# Create a dense matrix that should have multiple triad types
mat <- create_directed_matrix(8, seed = 333)
result <- motif_census(mat, n_random = 10, seed = 42)
with_temp_png({
p <- plot(result, type = "network", show_nonsig = TRUE)
}, width = 600, height = 600)
# Should either return NULL or handle gracefully
expect_true(is.null(p) || is.null(p))
})
test_that("plot.cograph_motifs heatmap handles extreme z-scores", {
skip_if_not_installed("igraph")
skip_if_not_installed("ggplot2")
mat <- create_directed_matrix(8, seed = 444)
result <- motif_census(mat, n_random = 50, seed = 42)
with_temp_png({
p <- plot(result, type = "heatmap", show_nonsig = TRUE)
}, width = 400, height = 400)
expect_true(is.null(p) || inherits(p, "gg"))
})
# =============================================================================
# EXTRACT_TRIADS ADDITIONAL EDGE CASES
# =============================================================================
test_that("extract_triads handles directed parameter explicitly", {
skip_if_not_installed("igraph")
mat <- create_weighted_matrix(5, seed = 555)
# Explicit directed = TRUE
result_dir <- extract_triads(mat, directed = TRUE, min_total = 0)
expect_true(is.data.frame(result_dir))
# Explicit directed = FALSE
result_undir <- extract_triads(mat, directed = FALSE, min_total = 0)
expect_true(is.data.frame(result_undir))
})
test_that("extract_triads handles combined type and involving filters", {
skip_if_not_installed("igraph")
mat <- create_weighted_matrix(6, seed = 666)
result <- extract_triads(mat, type = c("030T", "030C"), involving = "A", min_total = 0)
expect_true(is.data.frame(result))
if (nrow(result) > 0) {
expect_true(all(result$type %in% c("030T", "030C")))
has_A <- apply(result[, c("A", "B", "C")], 1, function(x) "A" %in% x)
expect_true(all(has_A))
}
})
# =============================================================================
# EXTRACT_MOTIFS SIGNIFICANCE TESTING EDGE CASES
# =============================================================================
test_that("extract_motifs significance test handles edge cases", {
skip_if_not_installed("igraph")
mat <- create_weighted_matrix(5, seed = 777)
# Small n_perm
result <- extract_motifs(mat, pattern = "all", min_transitions = 0,
significance = TRUE, n_perm = 3, seed = 42)
if (!is.null(result) && nrow(result$results) > 0) {
expect_true("z" %in% names(result$results))
expect_true("p" %in% names(result$results))
expect_true("expected" %in% names(result$results))
expect_true("sig" %in% names(result$results))
}
})
test_that("extract_motifs handles by_type sorting", {
skip_if_not_installed("igraph")
mat <- create_weighted_matrix(6, seed = 888)
result <- extract_motifs(mat, pattern = "all", by_type = TRUE, min_transitions = 0)
if (!is.null(result) && nrow(result$results) > 1) {
# Check that results are grouped by type
types <- result$results$type
# Runs should be somewhat grouped
expect_true(length(types) > 0)
}
})
# =============================================================================
# PLOT.COGRAPH_MOTIF_ANALYSIS ADDITIONAL EDGE CASES
# =============================================================================
test_that("plot.cograph_motif_analysis types plot handles empty type_summary", {
skip_if_not_installed("igraph")
skip_if_not_installed("ggplot2")
# Create mock result with empty type_summary
mock_result <- list(
results = data.frame(triad = "A - B - C", type = "030T",
observed = 1, stringsAsFactors = FALSE),
type_summary = table(character(0)), # Empty
params = list(
level = "aggregate",
edge_method = "any",
pattern = "all",
significance = FALSE
)
)
class(mock_result) <- "cograph_motif_analysis"
# Should handle gracefully without error
result <- with_temp_png({
tryCatch(
plot(mock_result, type = "types"),
error = function(e) "error_caught"
)
})
# Expect either successful plot or graceful error handling
expect_true(is.null(result) || inherits(result, "gg") || result == "error_caught")
})
test_that("plot.cograph_motif_analysis triads handles various spacing values", {
skip_if_not_installed("igraph")
skip_if_not_installed("ggplot2")
mat <- create_weighted_matrix(5, seed = 999)
result <- extract_motifs(mat, pattern = "all", min_transitions = 0)
# Either result is NULL (acceptable) or we can plot
expect_true(is.null(result) || inherits(result, "cograph_motif_analysis"))
if (!is.null(result) && nrow(result$results) > 0) {
# Test different spacing values
with_temp_png({
plot(result, type = "triads", n = 4, spacing = 0.5)
}, width = 400, height = 400)
with_temp_png({
plot(result, type = "triads", n = 4, spacing = 2.0)
}, width = 400, height = 400)
}
})
test_that("plot.cograph_motif_analysis triads handles n > nrow(results)", {
skip_if_not_installed("igraph")
skip_if_not_installed("ggplot2")
mat <- create_weighted_matrix(4, seed = 111)
result <- extract_motifs(mat, pattern = "triangle", min_transitions = 0)
# Either result is NULL (acceptable) or we can plot
expect_true(is.null(result) || inherits(result, "cograph_motif_analysis"))
if (!is.null(result) && nrow(result$results) > 0) {
with_temp_png({
# Request more triads than available
plot(result, type = "triads", n = 100)
}, width = 400, height = 400)
}
})
# =============================================================================
# .PLOT_MOTIF_PATTERNS ADDITIONAL TESTS
# =============================================================================
test_that(".plot_motif_patterns handles various type counts", {
skip_if_not_installed("igraph")
skip_if_not_installed("ggplot2")
mat <- create_weighted_matrix(6, seed = 222)
result <- extract_motifs(mat, pattern = "all", min_transitions = 0)
# Either result is NULL (acceptable) or we can plot
expect_true(is.null(result) || inherits(result, "cograph_motif_analysis"))
if (!is.null(result) && length(result$type_summary) > 0) {
# Test with different n values
with_temp_png({
plot(result, type = "patterns", n = 2)
}, width = 400, height = 400)
with_temp_png({
plot(result, type = "patterns", n = 8)
}, width = 600, height = 600)
}
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.