library(testthat) library(ausoa) context("API Contract Tests") # Test function signatures and return types test_that("Core functions have correct signatures", { # Test simulation_cycle_fcn signature sim_func <- simulation_cycle_fcn # Should accept required parameters expect_error( sim_func(), "argument \"population_data\" is missing" ) # Should work with correct parameters result <- sim_func( population_data = 100, time_horizon = 5, scenario = "base_case" ) expect_true(!is.null(result)) }) # Test parameter validation test_that("Parameter validation works correctly", { # Test population_data validation expect_error( simulation_cycle_fcn( population_data = "invalid", time_horizon = 5, scenario = "base_case" ), "population_data must be numeric" ) expect_error( simulation_cycle_fcn( population_data = -100, time_horizon = 5, scenario = "base_case" ), "population_data must be positive" ) # Test time_horizon validation expect_error( simulation_cycle_fcn( population_data = 100, time_horizon = "invalid", scenario = "base_case" ), "time_horizon must be numeric" ) expect_error( simulation_cycle_fcn( population_data = 100, time_horizon = 0, scenario = "base_case" ), "time_horizon must be positive" ) # Test scenario validation expect_error( simulation_cycle_fcn( population_data = 100, time_horizon = 5, scenario = 123 ), "scenario must be a character string" ) }) # Test return value contracts test_that("Functions return expected data types", { result <- simulation_cycle_fcn( population_data = 100, time_horizon = 5, scenario = "base_case" ) # Should return a list or data frame expect_true(is.list(result) || is.data.frame(result)) # Should have expected structure expect_gt(length(result), 0) # If it's a list, check for common elements if (is.list(result)) { # Should have some expected elements (adjust based on actual structure) expect_true(length(names(result)) > 0) } # If it's a data frame, check structure if (is.data.frame(result)) { expect_gt(nrow(result), 0) expect_gt(ncol(result), 0) } }) # Test error handling contracts test_that("Error messages are informative", { # Test that error messages contain useful information error_msg <- tryCatch({ simulation_cycle_fcn( population_data = -100, time_horizon = 5, scenario = "base_case" ) NULL }, error = function(e) e) expect_false(is.null(error_msg)) expect_gt(nchar(error_msg), 10) # Should be informative expect_true(grepl("population|positive|invalid", error_msg, ignore.case = TRUE)) }) # Test configuration loading contracts test_that("Configuration loading follows contracts", { # Test that config loading works config_path <- system.file("config", package = "ausoa", mustWork = TRUE) if (dir.exists(config_path)) { config <- load_config(config_path) # Should return a list expect_true(is.list(config)) # Should have expected structure expect_gt(length(config), 0) # Should contain coefficients expect_true("coefficients" %in% names(config) || length(config) > 0) } }) # Test data input/output contracts test_that("Data I/O follows expected contracts", { # Test data loading test_data <- list( population = 100, time_horizon = 5, scenario = "base_case" ) # Should be able to save and load data temp_file <- tempfile(fileext = ".rds") # Save saveRDS(test_data, temp_file) expect_true(file.exists(temp_file)) # Load loaded_data <- readRDS(temp_file) expect_equal(test_data, loaded_data) # Clean up unlink(temp_file) }) # Test function composition contracts test_that("Functions can be composed correctly", { # Test that functions work together in pipelines # Example pipeline (adjust based on actual functions) population_data <- 100 time_horizon <- 5 scenario <- "base_case" # Should be able to chain operations result <- simulation_cycle_fcn( population_data = population_data, time_horizon = time_horizon, scenario = scenario ) expect_true(!is.null(result)) # Test that results can be processed further if (is.data.frame(result) || is.list(result)) { # Should be able to extract information expect_true(length(result) > 0) } }) # Test backward compatibility contracts test_that("API maintains backward compatibility", { # Test that existing function calls still work # This is a regression test for API changes result <- simulation_cycle_fcn( population_data = 100, time_horizon = 5, scenario = "base_case" ) # Should work the same as before expect_true(!is.null(result)) expect_true(is.list(result) || is.data.frame(result)) }) # Test performance contracts test_that("Performance meets API contracts", { # Test that functions complete within expected time start_time <- Sys.time() result <- simulation_cycle_fcn( population_data = 100, time_horizon = 5, scenario = "base_case" ) end_time <- Sys.time() duration <- as.numeric(difftime(end_time, start_time, units = "secs")) # Should complete within 2 minutes for standard test case expect_lt(duration, 120) # Should return results expect_true(!is.null(result)) }) # Test resource usage contracts test_that("Resource usage follows contracts", { # Test memory usage mem_before <- gc() result <- simulation_cycle_fcn( population_data = 100, time_horizon = 5, scenario = "base_case" ) mem_after <- gc() # Memory increase should be reasonable mem_increase <- sum(mem_after[, 2] - mem_before[, 2]) expect_lt(mem_increase, 500 * 1024 * 1024) # Less than 500MB # Should return valid results expect_true(!is.null(result)) })