diff --git a/MultiversalDiplomacyTests/ReplDriver.cs b/MultiversalDiplomacyTests/ReplDriver.cs
new file mode 100644
index 0000000..ff3b99f
--- /dev/null
+++ b/MultiversalDiplomacyTests/ReplDriver.cs
@@ -0,0 +1,51 @@
+using NUnit.Framework;
+
+using MultiversalDiplomacy.Script;
+
+namespace MultiversalDiplomacyTests;
+
+public class ReplDriver(IScriptHandler initialHandler, bool echo = false)
+{
+ public IScriptHandler? Handler { get; private set; } = initialHandler;
+
+ private string? LastInput { get; set; } = "";
+
+ ///
+ /// Whether to print the inputs as they are executed. This is primarily a debugging aid.
+ ///
+ bool Echo { get; } = echo;
+
+ ///
+ /// Input a multiline string into the repl. Call or at the end so the
+ /// statement is valid.
+ ///
+ public ReplDriver this[string input] => ExecuteAll(input);
+
+ public ReplDriver ExecuteAll(string multiline)
+ {
+ var lines = multiline.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
+ return lines.Aggregate(this, (repl, line) => repl.Execute(line));
+ }
+
+ public ReplDriver Execute(string inputLine)
+ {
+ if (Handler is null) throw new AssertionException(
+ $"Cannot execute \"{inputLine}\", handler quit. Last input was \"{LastInput}\"");
+ if (Echo) Console.WriteLine($"{Handler.Prompt}{inputLine}");
+
+ Handler = Handler.HandleInput(inputLine);
+ LastInput = inputLine;
+
+ return this;
+ }
+
+ public void Ready()
+ {
+ Assert.That(Handler, Is.Not.Null, "Handler is closed");
+ }
+
+ public void Closed()
+ {
+ Assert.That(Handler, Is.Null, "Handler is not closed");
+ }
+}
diff --git a/MultiversalDiplomacyTests/ReplTest.cs b/MultiversalDiplomacyTests/ReplTest.cs
new file mode 100644
index 0000000..2d81caf
--- /dev/null
+++ b/MultiversalDiplomacyTests/ReplTest.cs
@@ -0,0 +1,35 @@
+using NUnit.Framework;
+
+using MultiversalDiplomacy.Model;
+using MultiversalDiplomacy.Script;
+
+namespace MultiversalDiplomacyTests;
+
+public class ReplTest
+{
+ [Test]
+ public void SetupHandler()
+ {
+ SetupScriptHandler setup = new(World.WithStandardMap(), strict: true);
+ ReplDriver repl = new(setup);
+
+ repl["""
+ unit Germany A Munich
+ unit Austria Army Tyrolia
+ unit England F London
+ """].Ready();
+
+ Assert.That(repl.Handler, Is.TypeOf());
+ SetupScriptHandler handler = (SetupScriptHandler)repl.Handler!;
+ Assert.That(handler.World.Units.Count, Is.EqualTo(3));
+ Assert.That(handler.World.GetUnitAt("Mun"), Is.Not.Null);
+ Assert.That(handler.World.GetUnitAt("Tyr"), Is.Not.Null);
+ Assert.That(handler.World.GetUnitAt("Lon"), Is.Not.Null);
+
+ repl["""
+ ---
+ """].Ready();
+
+ Assert.That(repl.Handler, Is.TypeOf());
+ }
+}