Nothing
# test-detectionMaps.R
context("detectionMaps")
# Load necessary libraries for testing
library(testthat)
library(sf)
library(withr)
# --- Test Setup ---
# This block creates shared, self-contained data for all tests.
# 1. Load sample data from the package
data(camtraps)
data(recordTableSample)
# 2. Create the sample Area of Interest (AOI) polygon from the example
aoi_poly <- st_polygon(list(cbind(c(521500, 526500, 527000, 521500, 521500),
c(607500, 608000, 603500, 603500, 607500))))
aoi <- st_sf(name = "My AOI", geometry = st_sfc(aoi_poly), crs = 32650)
# --- Test Suite ---
testthat::describe("Core Functionality & Return Value", {
test_that("it returns a correct data.frame with expected calculations", {
# Run with plotting and file writing disabled to test only the data output
maps_df <- detectionMaps(
CTtable = camtraps,
recordTable = recordTableSample,
Xcol = "utm_x",
Ycol = "utm_y",
stationCol = "Station",
speciesCol = "Species",
plotR = FALSE, # Disable plotting for this test
writePNG = FALSE,
writeShapefile = FALSE
)
# 1. Check the output type and dimensions
expect_s3_class(maps_df, "data.frame")
expect_equal(nrow(maps_df), nrow(camtraps)) # Should return a row for every station
# 2. Check for expected columns (station, coords, species, richness)
expected_species <- sort(unique(recordTableSample$Species))
expected_cols <- c("Station", "utm_x", "utm_y", expected_species, "n_species")
expect_named(maps_df, expected_cols)
# 3. Verify specific calculated values based on sample data
stationA_data <- maps_df[maps_df$Station == "StationA", ]
expect_equal(stationA_data$PBE, 4)
expect_equal(stationA_data$VTA, 2)
expect_equal(stationA_data$n_species, 2) # PBE, VTA were detected here
stationC_data <- maps_df[maps_df$Station == "StationC", ]
expect_equal(stationC_data$EGY, 6)
expect_equal(stationC_data$PBE, 6)
expect_equal(stationC_data$MNE, 0)
expect_equal(stationC_data$n_species, 4)
})
})
testthat::describe("Filtering and Subset Options", {
plot(1) # avoid warning: calling par(new=TRUE) with no plot
test_that("speciesToShow argument correctly filters the output", {
species_subset <- c("PBE", "VTA")
maps_df_filtered <- detectionMaps(
CTtable = camtraps,
recordTable = recordTableSample,
speciesToShow = species_subset,
Xcol = "utm_x", Ycol = "utm_y", plotR = FALSE
)
# 1. Check that only the specified species columns exist
expected_cols <- c("Station", "utm_x", "utm_y", sort(species_subset), "n_species")
expect_named(maps_df_filtered, expected_cols)
# 2. Check that richness is recalculated based on the subset
stationB_data <- maps_df_filtered[maps_df_filtered$Station == "StationB", ]
# StationB had MNE, PBE VTA. After filtering, it should only count 2 species.
expect_equal(stationB_data$n_species, 2)
})
})
testthat::describe("File Generation (Side Effects)", {
# Use a temporary directory to avoid creating files in the project
with_tempdir({
test_that("writePNG = TRUE creates the expected number of PNG files", {
# Suppress plotting to the R device to keep the test console clean
pdf(NULL)
detectionMaps(
CTtable = camtraps,
recordTable = recordTableSample,
Xcol = "utm_x", Ycol = "utm_y",
writePNG = TRUE,
plotR = FALSE, # Don't plot to R device
plotDirectory = ".", # Write to the temp directory
createPlotDir = FALSE
)
dev.off() # Close the null PDF device
png_files <- list.files(pattern = "\\.png$")
# Expecting 7 PNGs: 1 for richness + 6 for the unique species in the sample data
n_species <- length(unique(recordTableSample$Species))
expect_equal(length(png_files), 1 + n_species)
expect_true(any(grepl("n_Species_", png_files)))
expect_true(any(grepl("Presence_PBE", png_files)))
})
test_that("writeShapefile = TRUE creates a valid shapefile", {
skip_if_not_installed("sf")
# Generate a unique name to avoid conflicts
shapefile_name <- "test_detections"
maps_sf_obj <- detectionMaps(
CTtable = camtraps,
recordTable = recordTableSample,
Xcol = "utm_x", Ycol = "utm_y", plotR = FALSE,
writeShapefile = TRUE,
shapefileName = shapefile_name,
shapefileDirectory = ".", # Write to the temp directory
shapefileProjection= 4326 # Use a known CRS (WGS84)
)
# 1. Check that the shapefile components were created
expect_true(file.exists(paste0(shapefile_name, ".shp")))
expect_true(file.exists(paste0(shapefile_name, ".dbf")))
# 2. Check that the returned object is an sf object
expect_s3_class(maps_sf_obj, "sf")
# 3. Read the shapefile back in and verify its properties
sf_read <- st_read(dsn = ".", layer = shapefile_name, quiet = TRUE)
expect_s3_class(sf_read, "sf")
expect_equal(nrow(sf_read), nrow(camtraps))
expect_true(st_crs(sf_read) == st_crs(4326)) # Verify projection was set
})
})
})
testthat::describe("Spatial Features and Plotting Options", {
test_that("backgroundPolygon argument runs without error", {
# The main test is that the function doesn't crash when trying to plot the polygon.
# We can't easily test the visual output, so we just check for successful execution.
pdf(NULL) # Suppress plot output
expect_no_error(
detectionMaps(
CTtable = camtraps,
recordTable = recordTableSample,
backgroundPolygon = aoi,
Xcol = "utm_x", Ycol = "utm_y",
plotR = TRUE,
writePNG = FALSE
)
)
dev.off()
})
})
testthat::describe("Input Validation", {
plot(1) # avoid warning: calling par(new=TRUE) with no plot
test_that("it stops for missing or invalid column names", {
expect_error(
detectionMaps(CTtable = camtraps, recordTable = recordTableSample, Xcol = "WRONG_X", Ycol = "utm_y"),
regexp = "Xcol = \"WRONG_X\" is not a column name in CTtable"
)
# Mismatched station IDs
recordTable_bad_station <- recordTableSample
recordTable_bad_station$Station[1] <- "UNKNOWN_STATION"
expect_error(
detectionMaps(CTtable = camtraps, recordTable = recordTable_bad_station, Xcol = "utm_x", Ycol = "utm_y"),
regexp = "items of stationCol in recordTable are not matched"
)
})
test_that("it stops if writeShapefile = TRUE and directory is missing", {
expect_error(
detectionMaps(CTtable = camtraps, recordTable = recordTableSample, Xcol = "utm_x", Ycol = "utm_y",
writeShapefile = TRUE, plotR = FALSE),
fixed = "hasArg(shapefileDirectory) is not TRUE"
)
})
})
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.