diff --git a/test/io_tests.jl b/test/io_tests.jl
index 42d1fa089afadb76874739a0e360109f635824f3..435bd253c25385511cce3c344484d4fafde8cdc0 100644
--- a/test/io_tests.jl
+++ b/test/io_tests.jl
@@ -18,7 +18,7 @@
 end
 
 @testset "Output functions" begin
-    model = smalltestlandscape()
+    model = inittestmodel()
     # test that the output directory is created with all files
     outdir = @param(core.outdir)
     Ps.createdatadir(outdir, @param(core.overwrite))
@@ -37,12 +37,12 @@ end
                Ps.createdatadir(outdir, @param(core.overwrite)))
     @test_throws ErrorException Ps.createdatadir(outdir, false)
     # test that creating a DataOutput works, and outputs data with the required frequency
-    testoutput(model) = string(model.date)*"\n"
-    Ps.newdataoutput!(model, "never.csv", "Date", testoutput, "never")
-    Ps.newdataoutput!(model, "daily.csv", "Date", testoutput, "daily")
-    Ps.newdataoutput!(model, "monthly.csv", "Date", testoutput, "monthly")
-    Ps.newdataoutput!(model, "yearly.csv", "Date", testoutput, "yearly")
-    Ps.newdataoutput!(model, "end.csv", "Date", testoutput, "end")
+    testoutput(model) = [[string(model.date)]]
+    Ps.newdataoutput!(model, "never", ["Date"], testoutput, "never")
+    Ps.newdataoutput!(model, "daily", ["Date"], testoutput, "daily")
+    Ps.newdataoutput!(model, "monthly", ["Date"], testoutput, "monthly")
+    Ps.newdataoutput!(model, "yearly", ["Date"], testoutput, "yearly")
+    Ps.newdataoutput!(model, "end", ["Date"], testoutput, "end")
     @param(core.enddate) = Date(2023,2,1)
     @test_logs((:info, "Simulated 366 days."),
                match_mode=:any,
@@ -51,12 +51,15 @@ end
     @test !isfile(joinpath(outdir, "never.csv"))
     @test isfile(joinpath(outdir, "daily.csv"))
     @test countlines(joinpath(outdir, "daily.csv")) == 367
+    @test size(model.datatables["daily"]) == (366, 1)
     @test isfile(joinpath(outdir, "monthly.csv"))
     @test countlines(joinpath(outdir, "monthly.csv")) == 14
+    @test size(model.datatables["monthly"]) == (13, 1)
     @test isfile(joinpath(outdir, "yearly.csv"))
     @test countlines(joinpath(outdir, "yearly.csv")) == 3
+    @test size(model.datatables["yearly"]) == (2, 1)
     @test isfile(joinpath(outdir, "end.csv"))
     @test countlines(joinpath(outdir, "end.csv")) == 2
+    @test size(model.datatables["end"]) == (1, 1)
     rm(outdir, force=true, recursive=true)
-    #TODO test dataframe output
 end
diff --git a/test/landscape_tests.jl b/test/landscape_tests.jl
index 1fa2ac5a0754fb3ce2952748133b5673e94f149a..aaf1f8e4628538c16601e2fdc20bdc67f18bbe8a 100644
--- a/test/landscape_tests.jl
+++ b/test/landscape_tests.jl
@@ -4,13 +4,7 @@
 ###
 
 @testset "Landscape initialisation" begin
-    # initialise the landscape part of the model
-    landscape = Ps.initlandscape(TESTSETTINGS["world.landcovermap"],
-                                 TESTSETTINGS["world.farmfieldsmap"])
-    space = GridSpace(size(landscape), periodic=false)
-    properties = Dict{Symbol,Any}(:landscape=>landscape, :settings=>TESTSETTINGS,
-                                  :date=>TESTSETTINGS["core.startdate"])
-    model = AgentBasedModel(FarmPlot, space, properties=properties, warn=false)
+    model = inittestmodel(false)
     # these tests are specific to the Jena maps
     @test_logs (:info, "Initialised 2092 farm plots.") match_mode=:any Ps.initfields!(model)
     @test size(model.landscape) == (1754, 1602)
@@ -26,7 +20,7 @@
 end
 
 @testset "Event system" begin
-    model = smalltestlandscape()
+    model = inittestmodel()
     createevent!(model, [(1,1), (1,2), (1,3), (2,1), (2,3)], Ps.tillage)
     createevent!(model, [(1,1), (1,2), (1,3), (2,2)], Ps.sowing, 2)
     @test model.landscape[1,1].events == [Ps.tillage, Ps.sowing]
@@ -47,7 +41,7 @@ end
 end
 
 @testset "Landscape functions" begin
-    model = smalltestlandscape()
+    model = inittestmodel()
     @test Ps.distanceto((2,3), model, Ps.forest) == 0
     @test Ps.distanceto((2,3), model, Ps.grass) == 2
     @test Ps.distanceto((2,3), model, Ps.water) == 4
@@ -59,7 +53,7 @@ end
 
 @testset "Weather initialisation" begin
     # these tests are specific to the Jena weather file
-    model = smalltestlandscape()
+    model = inittestmodel()
     @test_logs((:warn, "There are missing days in the weather input file."),
                Ps.initweather(TESTSETTINGS["world.weatherfile"],
                               Date("2022-01-01"), Date("2023-12-31")))
diff --git a/test/nature_tests.jl b/test/nature_tests.jl
index 614780daa2fc31df723b0d482982354bbdeb4136..1d6276b05a591bd374d4e18e2464182f9fcdb765 100644
--- a/test/nature_tests.jl
+++ b/test/nature_tests.jl
@@ -5,15 +5,17 @@
 
 @testset "Habitat macros" begin
     # set up the testing landscape
-    model = smalltestlandscape()
+    model = inittestmodel()
     model.landscape[6,6] = Pixel(Ps.agriculture, 1, [])
     species::Dict{String,Any} = Dict("name"=>"test_animal")
-    add_agent!((6,6), FarmPlot, model, [(6,6)], Ps.wheat, 1.2, 3.4) #FIXME
+    add_agent!((6,6), FarmPlot, model,
+               [(6,6)], model.crops["winter wheat"], Ps.janfirst,
+               0.0, 0.0, 0.0, 0.0, Vector{Ps.EventType}())
     add_agent!((3,3), Animal, model, species, Ps.male, 1)
     add_agent!((4,4), Animal, model, species, Ps.female, 1)
     # create a set of habitat descriptors
     h1 = @habitat(@landcover() == Ps.water)
-    h2 = @habitat(@cropname() == "wheat" &&
+    h2 = @habitat(@cropname() == "winter wheat" &&
                   @cropheight() < 2)
     h3 = @habitat(@distanceto(Ps.water) > 2 &&
                   @distancetoedge() <= 2)
@@ -32,7 +34,7 @@
 end
 
 @testset "Species initialisation" begin
-    model = smalltestlandscape()
+    model = inittestmodel()
     spec = "test_animal"
     species::Dict{String,Any} = Dict("name"=>spec)
     # create a set of initialisation functions
@@ -68,7 +70,7 @@ end
 
 @testset "Species macros" begin
     # create a model landscape and a test species
-    model = smalltestlandscape()
+    model = inittestmodel()
     
     @species Mermaid begin
         ageofmaturity = 2
@@ -139,7 +141,7 @@ end
 
 @testset "Insect submodel" begin
     # create a set of pixels and dates for testing
-    model = smalltestlandscape()
+    model = inittestmodel()
     date1 = Date("2023-05-08") # day 128 (season begin)
     date2 = Date("2023-07-06") # day 187 (insect max)
     date3 = Date("2023-09-27") # day 270 (season end)
diff --git a/test/runtests.jl b/test/runtests.jl
index cfa6d69c2a1ccfd1528b2f66e872dc16b602328d..dc86b72f29752292c7427b6868526835af8ede2a 100644
--- a/test/runtests.jl
+++ b/test/runtests.jl
@@ -8,6 +8,7 @@ Pkg.activate("..")
 
 using Agents
 using Dates
+using DataFrames
 using Logging
 using LoggingExtras
 using Persefone
@@ -20,6 +21,37 @@ const Ps = Persefone
 const TESTPARAMETERS = joinpath(pkgdir(Persefone), "test/test_parameters.toml")
 const TESTSETTINGS = Ps.getsettings(TESTPARAMETERS)
 
+"""
+Initialise an AgentBasedModel for testing purposes.
+
+`smallmap`: use a hypothetical small landscape rather than a real one?
+"""
+function inittestmodel(smallmap=true)
+    if smallmap
+        landscape = smalltestlandscape()
+    else
+        landscape = Ps.initlandscape(TESTSETTINGS["world.landcovermap"],
+                                     TESTSETTINGS["world.farmfieldsmap"])
+    end
+    space = GridSpace(size(landscape), periodic=false)
+    weather = Ps.initweather(TESTSETTINGS["world.weatherfile"],
+                             TESTSETTINGS["core.startdate"],
+                             TESTSETTINGS["core.enddate"])
+    crops = Ps.readcropparameters(TESTSETTINGS["crop.cropfile"],
+                                  TESTSETTINGS["crop.growthfile"])
+    properties = Dict{Symbol,Any}(:date=>TESTSETTINGS["core.startdate"],
+                                  :landscape=>landscape,
+                                  :weather=>weather,
+                                  :crops=>crops,
+                                  :events=>Vector{FarmEvent}(),
+                                  :logger=>global_logger(),
+                                  :dataoutputs=>Vector{DataOutput}(),
+                                  :datatables=>Dict{String,DataFrame}(),
+                                  :settings=>TESTSETTINGS)
+    return AgentBasedModel(Union{Farmer,Animal,FarmPlot}, space, properties=properties,
+                           rng=StableRNG(TESTSETTINGS["core.seed"]), warn=false)
+end    
+
 """
     smalltestlandscape()
 
@@ -41,22 +73,7 @@ function smalltestlandscape()
         end
     end
     landscape[6,4] = Pixel(Ps.water, 0, [])
-    space = GridSpace(size(landscape), periodic=false)
-    weather = Ps.initweather(TESTSETTINGS["world.weatherfile"],
-                             TESTSETTINGS["core.startdate"],
-                             TESTSETTINGS["core.enddate"])
-    crops = Ps.readcropparameters(TESTSETTINGS["crop.cropfile"],
-                                  TESTSETTINGS["crop.growthfile"])
-    properties = Dict{Symbol,Any}(:date=>TESTSETTINGS["core.startdate"],
-                                  :landscape=>landscape,
-                                  :weather=>weather,
-                                  :crops=>crops,
-                                  :events=>Vector{FarmEvent}(),
-                                  :logger=>global_logger(),
-                                  :dataoutputs=>Vector{DataOutput}(),
-                                  :settings=>TESTSETTINGS)
-    return AgentBasedModel(Union{Farmer,Animal,FarmPlot}, space, properties=properties,
-                           rng=StableRNG(TESTSETTINGS["core.seed"]), warn=false)
+    landscape
 end
 
 @testset "Persefone Tests" begin