Nothing
# Comprehensive helper file for birdnetR tests
# Contains mocks, fixtures, and shared resources for testing
#' SECTION 1: MOCK OBJECTS FOR UNIT TESTS
#' These functions create mock objects that don't require Python
#' Create a mock Python object for testing
#'
#' This helper creates a mock that satisfies is_py_object() checks.
#' To use this in tests, you need to mock the is_py_object function.
#'
#' @param attributes List of attributes to attach to the mock object
#' @return A mock object that behaves like a Python object
create_mock_py_object <- function(attributes = list()) {
obj <- structure(
attributes,
class = c("mock_py_object")
)
return(obj)
}
#' Creates a function to check if an object is a mock Python object for testing
#'
#' @return Function that returns TRUE for mock objects and real Python objects
mock_is_py_object <- function() {
function(object) {
inherits(object, "mock_py_object") ||
inherits(object, "birdnet_py_mock") ||
reticulate::py_is_null_xptr(object) == FALSE
}
}
#' Create a mock BirdNET model for unit testing
#'
#' Creates a mock model that doesn't require Python dependencies or
#' actual model initialization. Use this in unit tests.
#'
#' @param version Version string
#' @param language Language code
#' @param model_type Type of model (tflite, protobuf, meta, etc.)
#' @return A mock model object that can be used for testing
create_mock_model <- function(version = "v2.4", language = "en_us", model_type = "tflite") {
# Create a mock Python object
mock_py_obj <- create_mock_py_object(list(
language = language,
predict = function(...) {
# Return a mock prediction structure that matches what the real model would return
list(
"(0.0, 3.0)" = list(
"Cyanocitta cristata_Blue Jay" = 0.85,
"Zenaida macroura_Mourning Dove" = 0.65
),
"(3.0, 6.0)" = list(
"Poecile atricapillus_Black-capped Chickadee" = 0.75
)
)
}
))
# Temporarily override reticulate::is_py_object to recognize our mock objects
old_is_py_object <- reticulate::is_py_object
tryCatch({
# Assign the mocked function
assignInNamespace("is_py_object", mock_is_py_object(), ns = "reticulate")
# Now create the model using the package function
model <- new_birdnet_model(
mock_py_obj,
model_version = version,
language = language,
subclass = model_type
)
return(model)
}, finally = {
# Always restore the original function to prevent side effects
assignInNamespace("is_py_object", old_is_py_object, ns = "reticulate")
})
}
#' SECTION 2: SHARED TEST RESOURCES
#' These functions provide cached access to real models for integration tests
# Lazy-loaded models - only initialized when needed
.test_models <- new.env()
#' Get a TFLite model for integration testing
#'
#' This function returns a cached model or initializes a new one
#' @param skip_if_not_available If TRUE, skips the test if model can't be initialized
#' @return A TFLite model or skips the test
get_test_tflite_model <- function(skip_if_not_available = TRUE) {
if (!exists("tflite", envir = .test_models)) {
# First check if we should even attempt model initialization
if (is_full_test_env()) {
tryCatch({
message("Initializing TFLite model for tests...")
model <- birdnet_model_tflite(version = "v2.4", language = "en_us")
assign("tflite", model, envir = .test_models)
}, error = function(e) {
if (skip_if_not_available) {
skip(paste("Failed to initialize TFLite model:", e$message))
} else {
NULL
}
})
} else {
if (skip_if_not_available) {
skip("Not in a full test environment - TFLite model not available")
}
return(NULL)
}
}
return(get("tflite", envir = .test_models))
}
#' Get a Meta model for integration testing
#'
#' This function returns a cached model or initializes a new one
#' @param skip_if_not_available If TRUE, skips the test if model can't be initialized
#' @return A Meta model or skips the test
get_test_meta_model <- function(skip_if_not_available = TRUE) {
if (!exists("meta", envir = .test_models)) {
# First check if we should even attempt model initialization
if (is_full_test_env()) {
tryCatch({
message("Initializing Meta model for tests...")
model <- birdnet_model_meta(version = "v2.4", language = "en_us")
assign("meta", model, envir = .test_models)
}, error = function(e) {
if (skip_if_not_available) {
skip(paste("Failed to initialize Meta model:", e$message))
} else {
NULL
}
})
} else {
if (skip_if_not_available) {
skip("Not in a full test environment - Meta model not available")
}
return(NULL)
}
}
return(get("meta", envir = .test_models))
}
#' Get standard test audio file path
#'
#' @return Path to the test audio file or skips the test if not found
test_audio_file <- function() {
audio_file <- system.file("extdata", "soundscape.mp3", package = "birdnetR")
if (audio_file == "") {
skip("Test audio file not found")
}
return(audio_file)
}
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.