Skip to content

Commit 3f577b1

Browse files
bschilderclaude
andcommitted
Add 27 test files for utility/data functions, coverage 41% -> ~55%
Tests for credset_colnames, construct_data, check_args, filepath handling, SUSIE/ABF/FINEMAP/POLYFUN parameter functions, result parsing, data preparation, and plot utilities. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent af1127a commit 3f577b1

File tree

56 files changed

+2606
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+2606
-0
lines changed

tests/testthat/test-COJO_args.R

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
test_that("COJO_args constructs basic command string", {
2+
3+
res <- echofinemap:::COJO_args(
4+
cojo_file = "sumstats.ma",
5+
bfile = "test_plink",
6+
out = "results"
7+
)
8+
testthat::expect_true(is.character(res))
9+
testthat::expect_true(grepl("--bfile test_plink", res))
10+
testthat::expect_true(grepl("--cojo-file sumstats.ma", res))
11+
testthat::expect_true(grepl("--out results", res))
12+
})
13+
14+
test_that("COJO_args includes optional flags when set", {
15+
16+
res <- echofinemap:::COJO_args(
17+
cojo_file = "sumstats.ma",
18+
bfile = "test_plink",
19+
out = "results",
20+
cojo_slct = TRUE,
21+
maf = 0.01,
22+
cojo_p = 5e-8,
23+
cojo_wind = 500
24+
)
25+
testthat::expect_true(grepl("--cojo-slct", res))
26+
testthat::expect_true(grepl("--maf 0.01", res))
27+
testthat::expect_true(grepl("--cojo-p 5e-08", res))
28+
testthat::expect_true(grepl("--cojo-wind 500", res))
29+
})
30+
31+
test_that("COJO_args omits NULL optional arguments", {
32+
33+
res <- echofinemap:::COJO_args(
34+
cojo_file = "sumstats.ma",
35+
bfile = "test_plink",
36+
out = "results",
37+
cojo_slct = NULL,
38+
cojo_joint = NULL
39+
)
40+
testthat::expect_false(grepl("--cojo-slct", res))
41+
testthat::expect_false(grepl("--cojo-joint", res))
42+
})
43+
44+
test_that("COJO_args includes conditional analysis flag", {
45+
46+
res <- echofinemap:::COJO_args(
47+
cojo_file = "sumstats.ma",
48+
bfile = "test_plink",
49+
out = "results",
50+
cojo_cond = "cond_snps.txt"
51+
)
52+
testthat::expect_true(grepl("--cojo-cond cond_snps.txt", res))
53+
})
54+
55+
test_that("COJO_args includes cojo_gc flag", {
56+
57+
res <- echofinemap:::COJO_args(
58+
cojo_file = "sumstats.ma",
59+
bfile = "test_plink",
60+
out = "results",
61+
cojo_gc = TRUE
62+
)
63+
testthat::expect_true(grepl("--cojo-gc", res))
64+
})
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
test_that("COJO_get_stepwise_results returns NULL for NULL path", {
2+
3+
res <- echofinemap:::COJO_get_stepwise_results(
4+
jma_cojo_path = NULL,
5+
verbose = FALSE
6+
)
7+
testthat::expect_null(res)
8+
})
9+
10+
test_that("COJO_get_stepwise_results returns NULL for non-existent path", {
11+
12+
res <- echofinemap:::COJO_get_stepwise_results(
13+
jma_cojo_path = file.path(tempdir(), "nonexistent.jma.cojo"),
14+
verbose = FALSE
15+
)
16+
testthat::expect_null(res)
17+
})
18+
19+
test_that("COJO_get_stepwise_results reads valid file", {
20+
21+
tmp <- tempfile(fileext = ".jma.cojo")
22+
on.exit(unlink(tmp), add = TRUE)
23+
24+
mock_data <- data.table::data.table(
25+
Chr = 4L,
26+
SNP = c("rs1", "rs2"),
27+
bp = c(100L, 200L),
28+
refA = c("A", "G"),
29+
freq = c(0.3, 0.5),
30+
freq_geno = c(0.31, 0.49),
31+
b = c(0.1, 0.2),
32+
se = c(0.01, 0.02),
33+
p = c(1e-8, 1e-6),
34+
n = c(1000L, 1000L),
35+
bJ = c(0.09, 0.19),
36+
bJ_se = c(0.011, 0.021),
37+
pJ = c(1e-7, 1e-5),
38+
LD_r = c(0.1, 0.2)
39+
)
40+
data.table::fwrite(mock_data, tmp, sep = "\t")
41+
42+
res <- echofinemap:::COJO_get_stepwise_results(
43+
jma_cojo_path = tmp,
44+
verbose = FALSE
45+
)
46+
testthat::expect_true(data.table::is.data.table(res))
47+
testthat::expect_equal(nrow(res), 2)
48+
## LD_r2 should be computed
49+
testthat::expect_true("LD_r2" %in% colnames(res))
50+
testthat::expect_equal(res$LD_r2, res$LD_r^2)
51+
})
52+
53+
test_that("COJO_get_conditional_results returns empty list for NULL paths", {
54+
55+
res <- echofinemap:::COJO_get_conditional_results(
56+
cma_cojo_path = NULL,
57+
cond_path = NULL,
58+
verbose = FALSE
59+
)
60+
testthat::expect_true(is.list(res))
61+
testthat::expect_length(res, 0)
62+
})
63+
64+
test_that("COJO_get_conditional_results reads valid cma file", {
65+
66+
tmp_cma <- tempfile(fileext = ".cma.cojo")
67+
on.exit(unlink(tmp_cma), add = TRUE)
68+
69+
mock_cma <- data.table::data.table(
70+
Chr = 4L,
71+
SNP = c("rs1", "rs2", "rs3"),
72+
bp = c(100L, 200L, 300L),
73+
refA = c("A", "G", "T"),
74+
freq = c(0.3, 0.5, 0.4),
75+
freq_geno = c(0.31, 0.49, 0.41),
76+
b = c(0.1, 0.2, 0.15),
77+
se = c(0.01, 0.02, 0.015),
78+
p = c(1e-8, 1e-6, 1e-4),
79+
n = c(1000L, 1000L, 1000L),
80+
bC = c(0.09, 0.19, 0.14),
81+
bC_se = c(0.011, 0.021, 0.016),
82+
pC = c(0.001, 0.04, 0.1)
83+
)
84+
data.table::fwrite(mock_cma, tmp_cma, sep = "\t")
85+
86+
res <- echofinemap:::COJO_get_conditional_results(
87+
cma_cojo_path = tmp_cma,
88+
cond_path = NULL,
89+
pC_max = 0.05,
90+
verbose = FALSE
91+
)
92+
testthat::expect_true("cma.cojo" %in% names(res))
93+
## Only SNPs with pC <= 0.05 should remain
94+
testthat::expect_true(all(res[["cma.cojo"]]$pC <= 0.05))
95+
testthat::expect_equal(nrow(res[["cma.cojo"]]), 2)
96+
})
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
test_that("COJO_list_files returns only existing files", {
2+
3+
cojo_dir <- file.path(tempdir(), "test_cojo_list")
4+
dir.create(cojo_dir, showWarnings = FALSE, recursive = TRUE)
5+
on.exit(unlink(cojo_dir, recursive = TRUE), add = TRUE)
6+
7+
prefix <- "cojo"
8+
## Create only some of the expected files
9+
writeLines("test", file.path(cojo_dir, paste0(prefix, ".jma.cojo")))
10+
writeLines("test", file.path(cojo_dir, paste0(prefix, ".ldr.cojo")))
11+
12+
res <- echofinemap:::COJO_list_files(
13+
cojo_dir = cojo_dir,
14+
prefix = prefix
15+
)
16+
testthat::expect_true(is.list(res))
17+
testthat::expect_true(all(file.exists(unlist(res))))
18+
testthat::expect_true("jma.cojo" %in% names(res))
19+
testthat::expect_true("ldr.cojo" %in% names(res))
20+
## file.ma was not created, so should not appear
21+
testthat::expect_false("file.ma" %in% names(res))
22+
})
23+
24+
test_that("COJO_list_files returns empty list when no files exist", {
25+
26+
cojo_dir <- file.path(tempdir(), "test_cojo_list_empty")
27+
dir.create(cojo_dir, showWarnings = FALSE, recursive = TRUE)
28+
on.exit(unlink(cojo_dir, recursive = TRUE), add = TRUE)
29+
30+
res <- echofinemap:::COJO_list_files(
31+
cojo_dir = cojo_dir,
32+
prefix = "cojo"
33+
)
34+
testthat::expect_true(is.list(res))
35+
testthat::expect_length(res, 0)
36+
})
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
test_that("COJO_locus_subdir creates directory and returns path", {
2+
3+
locus_dir <- file.path(tempdir(), "test_COJO_subdir")
4+
on.exit(unlink(locus_dir, recursive = TRUE), add = TRUE)
5+
6+
cojo_dir <- echofinemap:::COJO_locus_subdir(locus_dir = locus_dir)
7+
testthat::expect_true(dir.exists(cojo_dir))
8+
testthat::expect_equal(cojo_dir, file.path(locus_dir, "COJO"))
9+
})
10+
11+
test_that("COJO_locus_subdir is idempotent", {
12+
13+
locus_dir <- file.path(tempdir(), "test_COJO_subdir2")
14+
on.exit(unlink(locus_dir, recursive = TRUE), add = TRUE)
15+
16+
cojo_dir1 <- echofinemap:::COJO_locus_subdir(locus_dir = locus_dir)
17+
cojo_dir2 <- echofinemap:::COJO_locus_subdir(locus_dir = locus_dir)
18+
testthat::expect_equal(cojo_dir1, cojo_dir2)
19+
testthat::expect_true(dir.exists(cojo_dir2))
20+
})
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
test_that("COJO_process_results merges stepwise results into dat", {
2+
3+
tmp_dir <- file.path(tempdir(), "test_cojo_process")
4+
dir.create(tmp_dir, showWarnings = FALSE, recursive = TRUE)
5+
on.exit(unlink(tmp_dir, recursive = TRUE), add = TRUE)
6+
7+
## Create a mock jma.cojo file
8+
jma_path <- file.path(tmp_dir, "cojo.jma.cojo")
9+
mock_jma <- data.table::data.table(
10+
Chr = c(4L, 4L),
11+
SNP = c("rs1", "rs3"),
12+
bp = c(100L, 300L),
13+
refA = c("A", "G"),
14+
freq = c(0.3, 0.4),
15+
freq_geno = c(0.31, 0.41),
16+
b = c(0.1, 0.15),
17+
se = c(0.01, 0.015),
18+
p = c(1e-8, 1e-5),
19+
n = c(1000L, 1000L),
20+
bJ = c(0.09, 0.14),
21+
bJ_se = c(0.011, 0.016),
22+
pJ = c(0.001, 0.1),
23+
LD_r = c(0.1, 0.05)
24+
)
25+
data.table::fwrite(mock_jma, jma_path, sep = "\t")
26+
27+
dat <- data.table::data.table(
28+
SNP = c("rs1", "rs2", "rs3"),
29+
Effect = c(0.1, 0.2, 0.15)
30+
)
31+
32+
paths <- list("jma.cojo" = jma_path)
33+
res <- echofinemap:::COJO_process_results(
34+
dat = dat,
35+
paths = paths,
36+
credset_thresh = 0.95,
37+
freq_cutoff = 0.1,
38+
verbose = FALSE
39+
)
40+
testthat::expect_true(data.table::is.data.table(res))
41+
testthat::expect_equal(nrow(res), 3)
42+
testthat::expect_true("bJ" %in% colnames(res))
43+
testthat::expect_true("CS" %in% colnames(res))
44+
## rs1 has pJ=0.001 < 0.05, so CS should be 1
45+
testthat::expect_equal(res[res$SNP == "rs1"]$CS, 1)
46+
## rs2 was not in jma results, so bJ should be NA
47+
testthat::expect_true(is.na(res[res$SNP == "rs2"]$bJ))
48+
})
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
test_that("FINEMAP_check_existing_results returns NULL when no files exist", {
2+
3+
tmp_dir <- file.path(tempdir(), "test_fm_existing_1")
4+
dir.create(file.path(tmp_dir, "FINEMAP"),
5+
recursive = TRUE, showWarnings = FALSE)
6+
on.exit(unlink(tmp_dir, recursive = TRUE), add = TRUE)
7+
8+
dat <- data.table::data.table(
9+
SNP = c("rs1", "rs2"),
10+
Effect = c(0.5, 0.3),
11+
StdErr = c(0.1, 0.2)
12+
)
13+
14+
res <- echofinemap:::FINEMAP_check_existing_results(
15+
dat = dat,
16+
locus_dir = tmp_dir,
17+
credset_thresh = 0.95,
18+
finemap_version = package_version("1.4.1"),
19+
force_new = FALSE,
20+
verbose = FALSE
21+
)
22+
testthat::expect_null(res)
23+
})
24+
25+
test_that("FINEMAP_check_existing_results returns NULL when force_new=TRUE", {
26+
27+
tmp_dir <- file.path(tempdir(), "test_fm_existing_2")
28+
fm_dir <- file.path(tmp_dir, "FINEMAP")
29+
dir.create(fm_dir, recursive = TRUE, showWarnings = FALSE)
30+
on.exit(unlink(tmp_dir, recursive = TRUE), add = TRUE)
31+
32+
## Create a dummy file that would normally be found
33+
writeLines("rsid prob", file.path(fm_dir, "data.snp"))
34+
35+
dat <- data.table::data.table(
36+
SNP = c("rs1"),
37+
Effect = c(0.5),
38+
StdErr = c(0.1)
39+
)
40+
41+
res <- echofinemap:::FINEMAP_check_existing_results(
42+
dat = dat,
43+
locus_dir = tmp_dir,
44+
credset_thresh = 0.95,
45+
finemap_version = package_version("1.4.1"),
46+
force_new = TRUE,
47+
verbose = FALSE
48+
)
49+
testthat::expect_null(res)
50+
## Directory should be recreated (old contents deleted)
51+
testthat::expect_true(dir.exists(fm_dir))
52+
})
53+
54+
test_that("FINEMAP_check_existing_results cleans up old dir on force_new", {
55+
56+
tmp_dir <- file.path(tempdir(), "test_fm_existing_3")
57+
fm_dir <- file.path(tmp_dir, "FINEMAP")
58+
dir.create(fm_dir, recursive = TRUE, showWarnings = FALSE)
59+
on.exit(unlink(tmp_dir, recursive = TRUE), add = TRUE)
60+
61+
## Create files that should be removed
62+
writeLines("old data", file.path(fm_dir, "data.snp"))
63+
64+
dat <- data.table::data.table(SNP = "rs1", Effect = 0.5, StdErr = 0.1)
65+
66+
echofinemap:::FINEMAP_check_existing_results(
67+
dat = dat,
68+
locus_dir = tmp_dir,
69+
credset_thresh = 0.95,
70+
finemap_version = package_version("1.4.1"),
71+
force_new = TRUE,
72+
verbose = FALSE
73+
)
74+
75+
## Old data.snp should have been deleted
76+
testthat::expect_false(file.exists(file.path(fm_dir, "data.snp")))
77+
})

0 commit comments

Comments
 (0)