Skip to content

Commit 86d507c

Browse files
Merge pull request #1 from NIDAP-Community/dev-sovacool
test: create tests
2 parents 42545b8 + 8937b42 commit 86d507c

6 files changed

Lines changed: 268 additions & 29 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,7 @@
22

33
Code Ocean capsule: MOSuite - filter low counts
44

5+
[![tests](https://github.com/CCBR/MOSuite-filter-counts/actions/workflows/tests.yml/badge.svg)](https://github.com/CCBR/MOSuite-filter-counts/actions/workflows/tests.yml)
6+
57
- [Code Ocean Capsule](https://poc-nci.codeocean.io/capsule/2922767/tree)
68
- [MOSuite R package docs](https://ccbr.github.io/MOSuite/)

code/main.R

Lines changed: 83 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#!/usr/bin/env Rscript
2-
rlang::global_entrace()
32
library(argparse)
43
library(glue)
54
library(MOSuite)
@@ -13,38 +12,93 @@ setup_capsule_environment()
1312
# parse CLI arguments
1413
parser <- ArgumentParser()
1514

16-
parser$add_argument("--count_type", type="character", default="clean")
17-
parser$add_argument("--feature_id_colname", type="character", default=NULL, help="Column name for feature IDs")
18-
parser$add_argument("--sample_id_colname", type="character", default=NULL, help="Column name for sample IDs")
19-
parser$add_argument("--group_colname", type="character", default="Group", help="Column name for sample groups")
20-
parser$add_argument("--label_colname", type="character", default=NULL, help="Column name for sample labels")
21-
parser$add_argument("--minimum_count_value_to_be_considered_nonzero", type="integer", default=8, help="Minimum count threshold")
22-
parser$add_argument("--minimum_number_of_samples_with_nonzero_counts_in_total", type="integer", default=7, help="Minimum samples with nonzero counts")
23-
parser$add_argument("--minimum_number_of_samples_with_nonzero_counts_in_a_group", type="integer", default=3, help="Minimum samples per group with nonzero counts")
24-
parser$add_argument("--use_cpm_counts_to_filter", type="logical", default=TRUE, help="Transform to CPM before filtering")
25-
parser$add_argument("--use_group_based_filtering", type="logical", default=FALSE, help="Use group-based filtering")
26-
parser$add_argument("--plot_corr_matrix_heatmap", type="logical", default=TRUE, help="Plot correlation heatmap")
27-
parser$add_argument("--interactive_plots", type="logical", default=FALSE, help="Create interactive plots with plotly")
15+
parser$add_argument("--count_type", type = "character", default = "clean")
16+
parser$add_argument(
17+
"--feature_id_colname",
18+
type = "character",
19+
default = NULL,
20+
help = "Column name for feature IDs"
21+
)
22+
parser$add_argument(
23+
"--sample_id_colname",
24+
type = "character",
25+
default = NULL,
26+
help = "Column name for sample IDs"
27+
)
28+
parser$add_argument(
29+
"--group_colname",
30+
type = "character",
31+
default = "Group",
32+
help = "Column name for sample groups"
33+
)
34+
parser$add_argument(
35+
"--label_colname",
36+
type = "character",
37+
default = NULL,
38+
help = "Column name for sample labels"
39+
)
40+
parser$add_argument(
41+
"--minimum_count_value_to_be_considered_nonzero",
42+
type = "integer",
43+
default = 8,
44+
help = "Minimum count threshold"
45+
)
46+
parser$add_argument(
47+
"--minimum_number_of_samples_with_nonzero_counts_in_total",
48+
type = "integer",
49+
default = 7,
50+
help = "Minimum samples with nonzero counts"
51+
)
52+
parser$add_argument(
53+
"--minimum_number_of_samples_with_nonzero_counts_in_a_group",
54+
type = "integer",
55+
default = 3,
56+
help = "Minimum samples per group with nonzero counts"
57+
)
58+
parser$add_argument(
59+
"--use_cpm_counts_to_filter",
60+
type = "logical",
61+
default = TRUE,
62+
help = "Transform to CPM before filtering"
63+
)
64+
parser$add_argument(
65+
"--use_group_based_filtering",
66+
type = "logical",
67+
default = FALSE,
68+
help = "Use group-based filtering"
69+
)
70+
parser$add_argument(
71+
"--plot_corr_matrix_heatmap",
72+
type = "logical",
73+
default = TRUE,
74+
help = "Plot correlation heatmap"
75+
)
76+
parser$add_argument(
77+
"--interactive_plots",
78+
type = "logical",
79+
default = FALSE,
80+
help = "Create interactive plots with plotly"
81+
)
2882

2983
args <- parser$parse_args()
3084

3185
# load multiOmicDataSet from data directory
3286
moo <- load_moo_from_data_dir()
3387

3488
# run MOSuite
35-
moo |>
36-
filter_counts(
37-
count_type = args$count_type,
38-
feature_id_colname = args$feature_id_colname,
39-
sample_id_colname = args$sample_id_colname,
40-
group_colname = args$group_colname,
41-
label_colname = args$label_colname,
42-
minimum_count_value_to_be_considered_nonzero = args$minimum_count_value_to_be_considered_nonzero,
43-
minimum_number_of_samples_with_nonzero_counts_in_total = args$minimum_number_of_samples_with_nonzero_counts_in_total,
44-
minimum_number_of_samples_with_nonzero_counts_in_a_group = args$minimum_number_of_samples_with_nonzero_counts_in_a_group,
45-
use_cpm_counts_to_filter = args$use_cpm_counts_to_filter,
46-
use_group_based_filtering = args$use_group_based_filtering,
47-
plot_corr_matrix_heatmap = args$plot_corr_matrix_heatmap,
48-
interactive_plots = args$interactive_plots
49-
) |>
50-
write_rds(file.path(getOption("moo_plots_dir"), "..", "moo", "moo.rds"))
89+
moo |>
90+
filter_counts(
91+
count_type = args$count_type,
92+
feature_id_colname = args$feature_id_colname,
93+
sample_id_colname = args$sample_id_colname,
94+
group_colname = args$group_colname,
95+
label_colname = args$label_colname,
96+
minimum_count_value_to_be_considered_nonzero = args$minimum_count_value_to_be_considered_nonzero,
97+
minimum_number_of_samples_with_nonzero_counts_in_total = args$minimum_number_of_samples_with_nonzero_counts_in_total,
98+
minimum_number_of_samples_with_nonzero_counts_in_a_group = args$minimum_number_of_samples_with_nonzero_counts_in_a_group,
99+
use_cpm_counts_to_filter = args$use_cpm_counts_to_filter,
100+
use_group_based_filtering = args$use_group_based_filtering,
101+
plot_corr_matrix_heatmap = args$plot_corr_matrix_heatmap,
102+
interactive_plots = args$interactive_plots
103+
) |>
104+
write_rds(file.path(getOption("moo_plots_dir"), "..", "moo", "moo-filt.rds"))

tests/data/moo-clean.rds

7.83 MB
Binary file not shown.

tests/test-setup.R

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/usr/bin/env Rscript
2+
3+
# Simple test to verify the test setup and data exists
4+
cat("Testing basic test setup...\n")
5+
6+
# Get the current working directory during test execution
7+
cwd <- getwd()
8+
cat("Current directory:", cwd, "\n")
9+
10+
# Calculate repo root the same way the test does in tests/testthat/test-main.R
11+
# When running from tests/testthat, dirname(getwd()) goes to tests/
12+
repo_root_test_calculation <- normalizePath(file.path(dirname(cwd), ".."))
13+
cat(
14+
"Calculated repo_root (test calculation):",
15+
repo_root_test_calculation,
16+
"\n"
17+
)
18+
19+
# From script running in tests directory:
20+
# When this script is in tests/ directory, repo_root should be dirname(getwd())
21+
repo_root_script <- normalizePath(dirname(cwd))
22+
cat("Calculated repo_root (script location):", repo_root_script, "\n")
23+
24+
# Check if test data exists using test calculation
25+
test_data_file <- file.path(repo_root_script, "data", "moo-batch.rds")
26+
cat("\nLooking for test data at:", test_data_file, "\n")
27+
cat("Test data exists:", file.exists(test_data_file), "\n")
28+
29+
# Check code files
30+
code_main <- file.path(repo_root_script, "..", "code", "main.R")
31+
code_run <- file.path(repo_root_script, "..", "code", "run")
32+
cat("code/main.R exists:", file.exists(code_main), "\n")
33+
cat("code/run exists:", file.exists(code_run), "\n")
34+
35+
# Try to load the MOO object
36+
if (file.exists(test_data_file)) {
37+
cat("\nTrying to load MOO object...\n")
38+
library(readr)
39+
moo <- readr::read_rds(test_data_file)
40+
cat("MOO object loaded successfully!\n")
41+
cat("MOO class:", class(moo), "\n")
42+
if (hasSlot(moo, "counts")) {
43+
cat("MOO columns in counts:", names(moo@counts), "\n")
44+
}
45+
}

tests/testthat.R

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
library(testthat)
2+
test_dir(file.path('tests', 'testthat'), stop_on_failure = TRUE)

tests/testthat/test-main.R

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
test_that("code/run executes successfully with default CLI arguments", {
2+
# Create temporary workspace
3+
workspace <- tempfile("mosuite_filter_counts_test_")
4+
dir.create(workspace)
5+
on.exit(unlink(workspace, recursive = TRUE), add = TRUE)
6+
7+
# Set up directory structure
8+
code_dir <- file.path(workspace, "code")
9+
data_dir <- file.path(workspace, "data")
10+
results_dir <- file.path(code_dir, "..", "results")
11+
dir.create(code_dir)
12+
dir.create(data_dir)
13+
dir.create(results_dir)
14+
15+
# Get test data from package tests directory
16+
repo_root <- normalizePath(file.path(dirname(getwd()), ".."))
17+
test_data_file <- file.path(repo_root, "tests", "data", "moo-clean.rds")
18+
19+
expect_true(
20+
file.exists(test_data_file),
21+
info = paste("Test data file should exist at", test_data_file)
22+
)
23+
file.copy(test_data_file, file.path(data_dir, "moo.rds"))
24+
25+
# Copy main.R and run script to workspace
26+
file.copy(
27+
file.path(repo_root, "code", "main.R"),
28+
file.path(code_dir, "main.R")
29+
)
30+
file.copy(
31+
file.path(repo_root, "code", "run"),
32+
file.path(code_dir, "run")
33+
)
34+
35+
# Run the script from code directory
36+
old_wd <- getwd()
37+
setwd(code_dir)
38+
on.exit(setwd(old_wd), add = TRUE)
39+
40+
# Execute run script with default CLI arguments
41+
exit_code <- system2(
42+
"bash",
43+
args = c(
44+
"run",
45+
"--count_type=clean",
46+
"--minimum_count_value_to_be_considered_nonzero=8",
47+
"--minimum_number_of_samples_with_nonzero_counts_in_total=7",
48+
"--minimum_number_of_samples_with_nonzero_counts_in_a_group=3",
49+
"--use_cpm_counts_to_filter=TRUE",
50+
"--use_group_based_filtering=FALSE",
51+
"--plot_corr_matrix_heatmap=FALSE"
52+
)
53+
)
54+
55+
# Check for successful execution
56+
expect_equal(exit_code, 0, info = "run script should execute without error")
57+
expect_true(
58+
file.exists(file.path(results_dir, "moo", "moo-filt.rds")),
59+
info = "Output file moo-filt.rds should be created"
60+
)
61+
62+
# Validate output is a valid MOO object
63+
moo <- readr::read_rds(file.path(results_dir, "moo", "moo-filt.rds"))
64+
expect_true(
65+
S7::S7_inherits(moo, MOSuite::multiOmicDataSet),
66+
info = "Output should be an S7 multiOmicDataSet object"
67+
)
68+
})
69+
70+
test_that("code/run executes with custom CLI arguments", {
71+
# Create temporary workspace
72+
workspace <- tempfile("mosuite_filter_counts_custom_test_")
73+
dir.create(workspace)
74+
on.exit(unlink(workspace, recursive = TRUE), add = TRUE)
75+
76+
# Set up directory structure
77+
code_dir <- file.path(workspace, "code")
78+
data_dir <- file.path(workspace, "data")
79+
results_dir <- file.path(code_dir, "..", "results")
80+
dir.create(code_dir)
81+
dir.create(data_dir)
82+
dir.create(results_dir)
83+
84+
# Get test data from package tests directory
85+
repo_root <- normalizePath(file.path(dirname(getwd()), ".."))
86+
test_data_file <- file.path(repo_root, "tests", "data", "moo-clean.rds")
87+
88+
# Copy test data to workspace
89+
file.copy(test_data_file, file.path(data_dir, "moo.rds"))
90+
91+
# Copy main.R and run script to workspace
92+
file.copy(
93+
file.path(repo_root, "code", "main.R"),
94+
file.path(code_dir, "main.R")
95+
)
96+
file.copy(
97+
file.path(repo_root, "code", "run"),
98+
file.path(code_dir, "run")
99+
)
100+
101+
# Run the script from code directory
102+
old_wd <- getwd()
103+
setwd(code_dir)
104+
on.exit(setwd(old_wd), add = TRUE)
105+
106+
# Execute run script with custom CLI arguments
107+
exit_code <- system2(
108+
"bash",
109+
args = c(
110+
"run",
111+
"--count_type=clean",
112+
"--minimum_count_value_to_be_considered_nonzero=5",
113+
"--minimum_number_of_samples_with_nonzero_counts_in_total=3",
114+
"--use_cpm_counts_to_filter=FALSE",
115+
"--plot_corr_matrix_heatmap=FALSE"
116+
)
117+
)
118+
119+
# Check for successful execution
120+
expect_equal(
121+
exit_code,
122+
0,
123+
info = "run script with custom args should execute without error"
124+
)
125+
expect_true(
126+
file.exists(file.path(results_dir, "moo", "moo-filt.rds")),
127+
info = "Output file moo-filt.rds should be created with custom args"
128+
)
129+
130+
# Validate output is a valid MOO object
131+
moo <- readr::read_rds(file.path(results_dir, "moo", "moo-filt.rds"))
132+
expect_true(
133+
S7::S7_inherits(moo, MOSuite::multiOmicDataSet),
134+
info = "Output should be an S7 multiOmicDataSet object"
135+
)
136+
})

0 commit comments

Comments
 (0)