library(testthat) library(agroIoT) test_that("demo_npk_data returns correct structure", { df <- demo_npk_data(n_hours = 10) expect_s3_class(df, "data.frame") expect_named(df, c("timestamp", "sensor_id", "parameter", "value", "unit")) expect_equal(nrow(df), 60L) # 6 params * 10 hours expect_true(all(c("N","P","K","pH","moisture","temperature") %in% df$parameter)) }) test_that("demo_fruit_data returns correct structure", { df <- demo_fruit_data(n_hours = 24) expect_s3_class(df, "data.frame") expect_true(all(c("ethylene","CO2") %in% df$parameter)) expect_equal(nrow(df), 48L) }) test_that("demo_water_data returns correct structure", { df <- demo_water_data(n_hours = 12) expect_s3_class(df, "data.frame") expect_true(all(c("DO","pH","turbidity","TDS","NO3") %in% df$parameter)) expect_equal(nrow(df), 60L) }) test_that("qc_flag_outliers adds qc_flag column", { df <- demo_npk_data() df_flag <- qc_flag_outliers(df) expect_true("qc_flag" %in% names(df_flag)) expect_true(all(df_flag$qc_flag %in% c("ok", "outlier", "missing"))) }) test_that("qc_flag_outliers detects injected outliers", { df <- demo_npk_data() df$value[df$parameter == "pH"][1] <- -5 # impossible pH df_flag <- qc_flag_outliers(df) expect_true(any(df_flag$qc_flag == "outlier")) }) test_that("qc_flag_outliers action='remove' drops outlier rows", { df <- demo_npk_data() df$value[1] <- -9999 n_before <- nrow(df) df_clean <- qc_flag_outliers(df, action = "remove") expect_lt(nrow(df_clean), n_before) }) test_that("qc_gap_fill fills introduced NAs", { df <- demo_npk_data() df$value[c(5, 10, 15)] <- NA df_filled <- qc_gap_fill(df, method = "linear") expect_true("gap_filled" %in% names(df_filled)) expect_gt(sum(df_filled$gap_filled), 0) }) test_that("qc_drift_correct adds value_corrected column", { df <- demo_npk_data() df_c <- qc_drift_correct(df) expect_true("value_corrected" %in% names(df_c)) expect_equal(nrow(df_c), nrow(df)) }) test_that("soil_fertility_index returns expected columns and range", { df <- demo_npk_data() sfi <- soil_fertility_index(df) expect_true(all(c("sfi","fertility_class") %in% names(sfi))) expect_true(all(sfi$sfi >= 0 & sfi$sfi <= 100, na.rm = TRUE)) expect_true(all(sfi$fertility_class %in% c("Very Low","Low","Medium","High","Very High"))) }) test_that("soil_quefts_score returns limiting factor column", { df <- demo_npk_data() qs <- soil_quefts_score(df) expect_true("limiting_factor" %in% names(qs)) expect_true(all(qs$limiting_factor %in% c("N","P","K"))) }) test_that("fruit_ripening_state classifies banana stages", { df <- demo_fruit_data(n_hours = 120) rs <- fruit_ripening_state(df, fruit = "banana") expect_true("ripening_stage" %in% names(rs)) expect_true(all(rs$ripening_stage %in% c("Pre-climacteric","Climacteric rise","Ripe","Over-ripe","Senescent"))) }) test_that("water_quality_index returns wqi in valid range", { df <- demo_water_data() wq <- water_quality_index(df) expect_true("wqi" %in% names(wq)) expect_true(all(wq$wqi >= 0, na.rm = TRUE)) expect_true(all(wq$wq_class %in% c("Excellent","Good","Poor","Very Poor","Unsuitable"))) }) test_that("recommend_crop returns top_n rows", { df <- demo_npk_data() sfi <- soil_fertility_index(df) rec <- recommend_crop(sfi, top_n = 3) expect_lte(nrow(rec), 3L) expect_true("suitability_score" %in% names(rec)) }) test_that("recommend_fertilizer returns dose columns", { df <- demo_npk_data() qs <- soil_quefts_score(df) rec <- recommend_fertilizer(qs, target_yield = 5, crop = "wheat") expect_true(all(c("N_dose_kg_ha","P_dose_kg_ha","K_dose_kg_ha") %in% names(rec))) expect_true(all(rec$N_dose_kg_ha >= 0)) }) test_that("plot_sensor_ts returns a ggplot object", { df <- demo_npk_data() p <- plot_sensor_ts(df, parameters = c("N","P")) expect_s3_class(p, "ggplot") }) test_that("ndvi_health_class works correctly", { df <- dplyr::tibble( timestamp = Sys.time(), sensor_id = "s1", parameter = "NDVI", value = c(0.05, 0.2, 0.45, 0.65, 0.8), unit = "index" ) out <- ndvi_health_class(df) expect_true("health_class" %in% names(out)) expect_equal(nrow(out), 5L) }) test_that("read_sensor_csv round-trips demo data", { df <- demo_npk_data(n_hours = 5) tmp <- tempfile(fileext = ".csv") utils::write.csv(df, tmp, row.names = FALSE) df2 <- read_sensor_csv(tmp, sensor_id = "sensor_01") expect_s3_class(df2, "data.frame") unlink(tmp) })