Nothing
context("Image Management Workflow")
# Load necessary libraries for testing
library(testthat)
library(withr)
# --- Test Suite ---
# =========================================================================
# Tests for createStationFolders()
# =========================================================================
testthat::describe("createStationFolders()", {
test_that("it creates station directories correctly", {
with_tempdir({ # All file operations happen in a temporary, self-cleaning directory
stations <- c("StationA", "StationB", "StationC")
# Call the function
result <- createStationFolders(inDir = ".", stations = stations)
# 1. Check the returned data frame
expect_s3_class(result, "data.frame")
expect_equal(nrow(result), 3)
expect_named(result, c("station", "directory", "created", "exists"))
expect_true(all(result$created))
expect_true(all(result$exists))
# 2. Check the actual file system
created_dirs <- list.dirs(recursive = FALSE)
expect_equal(sort(basename(created_dirs)), sort(stations))
})
})
test_that("it creates nested station/camera directories correctly", {
with_tempdir({
stations <- c("StationA", "StationA", "StationB")
cameras <- c("Cam1", "Cam2", "Cam1")
result <- createStationFolders(inDir = ".", stations = stations, cameras = cameras)
# 1. Check the returned data frame
expect_true("camera" %in% names(result))
expect_true(all(result$created))
# 2. Check the actual file system
expect_true(dir.exists("StationA/Cam1"))
expect_true(dir.exists("StationA/Cam2"))
expect_true(dir.exists("StationB/Cam1"))
expect_false(dir.exists("StationB/Cam2")) # Ensure it didn't create extra dirs
})
})
test_that("it handles existing directories and createinDir correctly", {
with_tempdir({
# 1. Test createinDir = TRUE
new_root <- "new_root_dir"
expect_false(dir.exists(new_root))
createStationFolders(inDir = new_root, stations = "StationA", createinDir = TRUE)
expect_true(dir.exists(new_root))
# 2. Test idempotency (running twice)
dir.create("existing_station")
result_rerun <- createStationFolders(inDir = ".", stations = "existing_station")
expect_false(result_rerun$created) # Should report it was not created this time
expect_true(result_rerun$exists) # But that it exists
})
})
})
# =========================================================================
# Tests for imageRename()
# =========================================================================
testthat::describe("imageRename()", {
# All tests in this block require ExifTool
skip_if(Sys.which("exiftool") == "", message = "ExifTool not found, skipping tests.")
# Path to the raw sample images included with the package
wd_images_raw <- system.file("pictures/raw_images", package = "camtrapR")
test_that("it renames correctly with hasCameraFolders = FALSE", {
with_tempdir({
# Set up input and output directories
in_dir <- "raw_data"
out_dir <- "renamed_data"
dir.create(in_dir)
# Copy the sample data into our temporary input directory
file.copy(list.files(wd_images_raw, full.names = TRUE), in_dir, recursive = TRUE)
# Run the function
renaming_table <- imageRename(
inDir = in_dir,
outDir = out_dir,
hasCameraFolders = FALSE,
copyImages = TRUE
)
# 1. Check the returned table
expect_s3_class(renaming_table, "data.frame")
expect_true(all(renaming_table$CopyStatus))
# 2. Check the output files
renamed_files <- list.files(out_dir, recursive = TRUE)
expect_gt(length(renamed_files), 0)
# 3. Check the filename pattern (Station__Date__Time(n).JPG)
# Example: "StationA__2009-04-21__15-49-26(1).JPG"
expect_true(all(grepl("^Station[A-C]__\\d{4}-\\d{2}-\\d{2}__\\d{2}-\\d{2}-\\d{2}\\(\\d+\\)\\.JPG$", basename(renamed_files))))
})
})
test_that("copyImages = FALSE produces a table but no files", {
with_tempdir({
in_dir <- "raw_data"
out_dir <- "renamed_data" # This directory will not be created
dir.create(in_dir)
file.copy(list.files(wd_images_raw, full.names = TRUE), in_dir, recursive = TRUE)
renaming_table <- imageRename(
inDir = in_dir,
outDir = out_dir,
hasCameraFolders = FALSE,
copyImages = FALSE # Key argument
)
# 1. Check returned table
expect_true(all(!renaming_table$CopyStatus))
expect_s3_class(renaming_table, "data.frame")
# 2. Assert that NO output directory or files were created
expect_false(dir.exists(out_dir))
})
})
})
# =========================================================================
# Tests for appendSpeciesNames()
# =========================================================================
testthat::describe("appendSpeciesNames()", {
test_that("it can append and then remove species names (IDfrom = directory)", {
with_tempdir({
# 1. Setup a directory structure that mimics the state *after* species ID
species_id_dir <- "species_identified"
dir.create(file.path(species_id_dir, "StationA", "PBE"), recursive = TRUE)
dir.create(file.path(species_id_dir, "StationB", "VTA"), recursive = TRUE)
# Create some dummy files with the post-imageRename format
file.create(file.path(species_id_dir, "StationA", "PBE", "StationA__2023-01-01__12-00-00(1).JPG"))
file.create(file.path(species_id_dir, "StationB", "VTA", "StationB__2023-01-02__14-00-00(1).JPG"))
# 2. Append the names
append_table <- appendSpeciesNames(
inDir = species_id_dir,
IDfrom = "directory",
hasCameraFolders = FALSE,
removeNames = FALSE
)
# 3. Verify the appended files exist
files_after_append <- list.files(species_id_dir, recursive = TRUE)
expect_true(any(grepl("StationA__2023-01-01__12-00-00\\(1\\)__PBE\\.JPG", files_after_append)))
expect_true(any(grepl("StationB__2023-01-02__14-00-00\\(1\\)__VTA\\.JPG", files_after_append)))
# 4. Remove the names
remove_table <- appendSpeciesNames(
inDir = species_id_dir,
IDfrom = "directory", # Needs to know the species to remove the name
hasCameraFolders = FALSE,
removeNames = TRUE
)
# 5. Verify the files are back to their original names
files_after_remove <- list.files(species_id_dir, recursive = TRUE)
expect_false(any(grepl("__PBE\\.JPG", files_after_remove)))
expect_true(any(grepl("StationA__2023-01-01__12-00-00\\(1\\)\\.JPG", files_after_remove)))
})
})
})
# =========================================================================
# Integrated Workflow Test
# =========================================================================
testthat::describe("Full Image Management Workflow", {
skip_if(Sys.which("exiftool") == "", message = "ExifTool not found, skipping tests.")
test_that("the full workflow from creation to renaming works as expected", {
with_tempdir({
# --- STAGE 1: createStationFolders ---
raw_image_root <- "1_raw_images"
stations <- c("StationA", "StationB")
createStationFolders(inDir = raw_image_root, stations = stations, createinDir = TRUE)
# Manually copy sample images into the newly created structure
raw_images_path <- system.file("pictures/raw_images", package = "camtrapR")
# Put the first 2 sample station dirs into our new structure
file.copy(file.path(raw_images_path, "StationA"), raw_image_root, recursive = TRUE)
file.copy(file.path(raw_images_path, "StationB"), raw_image_root, recursive = TRUE)
# --- STAGE 2: imageRename ---
renamed_image_root <- "2_renamed_images"
imageRename(
inDir = raw_image_root,
outDir = renamed_image_root,
hasCameraFolders = FALSE,
copyImages = TRUE
)
# Verify that renamed files exist
renamed_files <- list.files(renamed_image_root, recursive = TRUE)
expect_gt(length(renamed_files), 0)
# --- STAGE 3: Simulate Manual Species ID ---
# Create species subdirectories and move the renamed files into them
species_id_root <- "3_species_id_images"
# We know from sample data that StationA has PBE, VTA, and SUS. We'll just ID them all as PBE for simplicity.
dir.create(file.path(species_id_root, "StationA", "PBE"), recursive = TRUE)
# And StationB has VTA
dir.create(file.path(species_id_root, "StationB", "VTA"), recursive = TRUE)
# Move files
files_to_move_A <- list.files(file.path(renamed_image_root, "StationA"), full.names = TRUE)
file.copy(files_to_move_A, file.path(species_id_root, "StationA", "PBE"))
files_to_move_B <- list.files(file.path(renamed_image_root, "StationB"), full.names = TRUE)
file.copy(files_to_move_B, file.path(species_id_root, "StationB", "VTA"))
# --- STAGE 4: appendSpeciesNames ---
appendSpeciesNames(inDir = species_id_root, IDfrom = "directory", hasCameraFolders = FALSE)
# Final verification
final_files <- list.files(species_id_root, recursive = TRUE)
expect_true(all(grepl("__PBE\\.JPG$|__VTA\\.JPG$", final_files)))
})
})
})
# =========================================================================
# Tests for getSpeciesImages()
# =========================================================================
testthat::describe("getSpeciesImages()", {
# Path to sample images included with the package
wd_images_ID <- system.file("pictures/sample_images_species_dir",
package = "camtrapR")
# create a mock record table and file structure for robustness
mock_record_table <- data.frame(
Station = c("StationA", "StationA", "StationB"),
Species = c("PBE", "VTA", "PBE"),
Directory = c("path/to/stationA", "path/to/stationA", "path/to/stationB"),
FileName = c("img1.jpg", "img2.jpg", "img3.jpg"),
stringsAsFactors = FALSE
)
test_that("it copies correct files using a recordTable", {
with_tempdir({ # All file operations happen in a temporary directory
# 1. Create the source directory structure and dummy files
dir.create("path/to/stationA", recursive = TRUE)
dir.create("path/to/stationB", recursive = TRUE)
file.create(file.path("path/to/stationA", c("img1.jpg", "img2.jpg")))
file.create(file.path("path/to/stationB", "img3.jpg"))
# Define the output directory
out_dir <- "species_images"
# 2. Call the function to copy images for species "PBE"
copy_table <- getSpeciesImages(
species = "PBE",
recordTable = mock_record_table,
outDir = out_dir
)
# 3. Verify the output
expect_s3_class(copy_table, "data.frame")
expect_equal(nrow(copy_table), 2) # Should find 2 images of PBE
expect_true(all(copy_table$copy_ok))
# 4. Check the file system
output_path <- file.path(out_dir, "PBE")
expect_true(dir.exists(output_path))
copied_files <- list.files(output_path)
expect_equal(length(copied_files), 2)
expect_equal(sort(copied_files), c("img1.jpg", "img3.jpg"))
})
})
test_that("it copies correct files using inDir and IDfrom = 'directory'", {
with_tempdir({
# 1. Create a source directory structure with species subfolders
in_dir <- "source_images"
dir.create(file.path(in_dir, "StationA", "PBE"), recursive = TRUE)
dir.create(file.path(in_dir, "StationA", "VTA"), recursive = TRUE)
dir.create(file.path(in_dir, "StationB", "PBE"), recursive = TRUE)
# Create dummy image files
file.create(file.path(in_dir, "StationA/PBE/img1.jpg"))
file.create(file.path(in_dir, "StationA/VTA/img2.jpg"))
file.create(file.path(in_dir, "StationB/PBE/img3.jpg"))
out_dir <- "species_images"
# 2. Call the function
copy_table <- getSpeciesImages(
species = "PBE",
inDir = in_dir,
outDir = out_dir,
IDfrom = "directory"
)
# 3. Verify output and file system
expect_equal(nrow(copy_table), 2) # 2 images of PBE
output_path <- file.path(out_dir, "PBE")
copied_files <- list.files(output_path)
expect_equal(length(copied_files), 2)
expect_equal(sort(copied_files), c("img1.jpg", "img3.jpg"))
})
})
test_that("createStationSubfolders = TRUE works correctly", {
with_tempdir({
# Setup is the same as the previous test
in_dir <- "source_images"
dir.create(file.path(in_dir, "StationA", "PBE"), recursive = TRUE)
dir.create(file.path(in_dir, "StationB", "PBE"), recursive = TRUE)
file.create(file.path(in_dir, "StationA/PBE/img1.jpg"))
file.create(file.path(in_dir, "StationB/PBE/img3.jpg"))
out_dir <- "species_images"
# Call with createStationSubfolders = TRUE
copy_table <- getSpeciesImages(
species = "PBE",
inDir = in_dir,
outDir = out_dir,
IDfrom = "directory",
createStationSubfolders = TRUE # Key argument
)
# Verify the nested output directory structure
expect_true(dir.exists(file.path(out_dir, "PBE", "StationA")))
expect_true(dir.exists(file.path(out_dir, "PBE", "StationB")))
expect_true(file.exists(file.path(out_dir, "PBE", "StationA", "img1.jpg")))
expect_true(file.exists(file.path(out_dir, "PBE", "StationB", "img3.jpg")))
})
})
test_that("it stops if the output directory is not empty", {
with_tempdir({
out_dir <- "species_images"
# Create a non-empty output directory beforehand
dir.create(file.path(out_dir, "PBE"), recursive = TRUE)
file.create(file.path(out_dir, "PBE", "existing_file.jpg"))
# Expect the function to stop
expect_error(
getSpeciesImages(species = "PBE", recordTable = mock_record_table, outDir = out_dir),
regexp = "target directory .* is not empty"
)
})
})
})
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.